1

So I am developing an app which works as device owner on the specific Android device. This app is not available on the play store, but gets transferred with a provisioning app from a different device via NFC. Since those devices will be very specific to certain tasks (scanning NFC tags), I want to enable and disable a few things from the very beginning.

I want to disable sound:

devicePolicyManager.setMasterVolumeMuted(adminComponentName, true);

But this doesn't seem to work at all, but no exception either.

But what I really want to do is enabling mobile Data and Roaming, the SIM cards which we are using support that.

devicePolicyManager.setSecureSetting(adminComponentName, Settings.Global.DATA_ROAMING, String.valueOf(1));
devicePolicyManager.setSecureSetting(adminComponentName,"mobile_data",String.valueOf(1));

But sadly, those two lines of code throw a security exception:

java.lang.SecurityException: Permission denial: Device owners cannot update mobile_data

Interestingly, inserting APNs work (later in the code) Any chance to be able to turn on mobile data and data roaming as a device admin/owner? I mean, thats the whole purpose of being a device admin, right?

Here is the full code for reference: (the parts which make the app crash are commented out)

public static void enableRestrictedAppsAndSettings(Activity activity) {

        ComponentName adminComponentName = DeviceAdminReceiver.getComponentName(activity);
        DevicePolicyManager devicePolicyManager = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // disable keyguard and sound
            devicePolicyManager.setKeyguardDisabled(adminComponentName, true);
            devicePolicyManager.setMasterVolumeMuted(adminComponentName, true);

            devicePolicyManager.setSecureSetting(adminComponentName, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY));

            //devicePolicyManager.setSecureSetting(adminComponentName, Settings.Global.DATA_ROAMING, String.valueOf(1));
            //devicePolicyManager.setSecureSetting(adminComponentName,"mobile_data",String.valueOf(1));

        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            if (devicePolicyManager.isDeviceOwnerApp(activity.getApplicationContext().getPackageName())) {
                devicePolicyManager.enableSystemApp(adminComponentName,"com.sec.android.app.camera");

                devicePolicyManager.clearUserRestriction(adminComponentName, UserManager.DISALLOW_DATA_ROAMING);

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    L.debug("KIOSK", "APN");
                    ApnSetting apn;

                    TelephonyManager manager = (TelephonyManager)activity.getSystemService(Context.TELEPHONY_SERVICE);
                    if (manager.getSimState() == TelephonyManager.SIM_STATE_READY) {

                        String mcc = manager.getSimOperator().substring(0, 3);
                        String mnc = manager.getSimOperator().substring(3);

                        L.debug("KIOSK " + mcc + " "+mnc);

                        apn = new ApnSetting.Builder()
                                .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT)
                                .setApnName("em")
                                .setEntryName("em")
                                .setOperatorNumeric(mcc + mnc) // this is a must its consists from Telephony.Carriers.MCC + Telephony.Carriers.MNC, In my case, I had to pad the MNC with a leading zero
                                .setProtocol(ApnSetting.PROTOCOL_IPV4V6) // this is a must
                                .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6) // this is a must
                                .setCarrierEnabled(true)
                                .build();

                        devicePolicyManager.removeOverrideApn(adminComponentName,0);
                        devicePolicyManager.addOverrideApn(adminComponentName, apn);

                        devicePolicyManager.setOverrideApnsEnabled(adminComponentName, true);
                    }
                }

            }
        }
Petros Mastrantonas
  • 806
  • 1
  • 15
  • 41

1 Answers1

1

Unfortunately the device owner has no access to mobile data status (you're right, weird restriction for the device owner app!).

However, you can still get the mobile data status and force the user to turn it on or off if the status is wrong. Here're the code samples (thanks to Test if background data and packet data is enabled or not).

public static boolean isMobileDataEnabled(Context context) {
    ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    try {
        Class clazz = Class.forName(cm.getClass().getName());
        Method method = clazz.getDeclaredMethod("getMobileDataEnabled");
        method.setAccessible(true); // Make the method callable
        // get the setting for "mobile data"
        return (Boolean) method.invoke(cm);
    } catch (Exception e) {
        // Let it will be true by default
        return true;
    }
}

This code works on Android 5-9 (not tested on Android 10 yet).

So you run a background service which performs this check once per some seconds and requires the user to turn on/off the mobile data in the status bar.

You can see how it is done by cloning this open source Android MDM (this is my project). The method is here: Utils.isMobileDataEnabled(Context context).

vmayorow
  • 630
  • 5
  • 15
  • thank you, I am using the code and it works perfectly. You seem to be very experienced regarding Device Owner Apps, I am still figuring out, what kind of power the Device Owner has. I still have the problem, that the device has the wrong keyboard (UK instead of German) so I am looking for a way to let my app install a new keyboard, or a new language for the Samsung keyboard, because we are using Samsung devices. – Petros Mastrantonas May 26 '20 at 07:13
  • I doubt that device owner can install new keyboards or languages. Basically, what device owner can do, is documented here: https://developer.android.com/reference/android/app/admin/DevicePolicyManager As far as I know, the keyboard and language are managed by parameters of /system/build.prop: persist.sys.language, persist.sys.region, ro.product.locale.language, ro.product.locale.country. But you must be able to create a custom ROM (or have root) to change these parameters. – vmayorow May 26 '20 at 12:04