4

I want to turn off / lock the screen of my device programmatically.

For the moment, when I try :

DevicePolicyManager mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
mDPM.lockNow();

I have this error :

java.lang.SecurityException: No active admin owned by uid 10176 for policy #3

This is my AndroidManifest.xml :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="opteamit.com.belami" >

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-feature android:name="android.hardware.location.gps" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <application...

What is wrong ?

Jéwôm'
  • 3,753
  • 5
  • 40
  • 73

3 Answers3

14

Well something with high necessity can't finished with two lines of code, lock off screen required device admin. you may follow this :

private void lock() {
    PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
    if (pm.isScreenOn()) {
        DevicePolicyManager policy = (DevicePolicyManager)
                getSystemService(Context.DEVICE_POLICY_SERVICE);
        try {
            policy.lockNow();
        } catch (SecurityException ex) {
            Toast.makeText(
                    this, 
                    "must enable device administrator",
                    Toast.LENGTH_LONG).show();
                ComponentName admin = new ComponentName(context, AdminReceiver.class);
                Intent intent = new Intent(
                    DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN).putExtra(
                        DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin);
                context.startActivity(intent);
        }           
    }
}

and AdminReceiverClass:

public class AdminReceiver extends DeviceAdminReceiver {
    public static final String ACTION_DISABLED = "device_admin_action_disabled";
    public static final String ACTION_ENABLED = "device_admin_action_enabled";

    @Override
    public void onDisabled(Context context, Intent intent) {
        super.onDisabled(context, intent);
        LocalBroadcastManager.getInstance(context).sendBroadcast(
            new Intent(ACTION_DISABLED));
    }
    @Override
    public void onEnabled(Context context, Intent intent) {
        super.onEnabled(context, intent);
        LocalBroadcastManager.getInstance(context).sendBroadcast(
            new Intent(ACTION_ENABLED));
    }
}

also we need declares the security policies used in metadata so for examples with Path android:resource="@xml/device_admin_sample" :

 <device-admin xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-policies>
    <limit-password />
    <watch-login />
    <reset-password />
    <force-lock />
    <wipe-data />
    <expire-password />
    <encrypted-storage />
    <disable-camera />
  </uses-policies>
</device-admin>

in our case we just need :

<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <force-lock />
    </uses-policies>
</device-admin>`

Now declare it in our manifist.xml :

<receiver
        android:name=".AdminReceiver"
        android:label="@string/device_admin"
        android:description="@string/device_admin_description"
        android:permission="android.permission.BIND_DEVICE_ADMIN">
        <meta-data
            android:name="android.app.device_admin"
            android:resource="@xml/device_admin_sample" />
        <intent-filter>
            <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
        </intent-filter>
    </receiver>`

Hope it will Help you.

  • Thanks but I have **android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?** (I am in a `Service`) – Jéwôm' Jun 21 '17 at 15:56
  • @Jéwôm' what is that new exception? when happened? –  Jun 21 '17 at 15:59
  • It happen in the startActivity(intent) line – Jéwôm' Jun 21 '17 at 16:02
  • @Jéwôm' Just cache the Context object via constructor, and use this line before start activity `intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);` –  Jun 21 '17 at 16:05
  • I have the message "must enable device administrator" but nothing append. – Jéwôm' Jun 21 '17 at 16:07
  • @Jéwôm' it's worked with me, please try to remove your app and reinstall. –  Jun 21 '17 at 16:12
  • One question : how can I do to check if I give the permission with a function like Boolean isDeviceAdminPermisionGranted() ? – Jéwôm' Jun 21 '17 at 16:25
  • 1
    @Jéwôm' just follow [this](http://developer.android.com/guide/topics/admin/device-admin.html) –  Jun 21 '17 at 16:35
0

See user6490462 answer below.

private void lock() {
    PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
    if (pm.isScreenOn()) {
       DevicePolicyManager policy = (DevicePolicyManager)
               getSystemService(Context.DEVICE_POLICY_SERVICE);
       try {
           policy.lockNow();
       } catch (SecurityException ex) {
           Toast.makeText(
                   this, 
                   "must enable device administrator",
                   Toast.LENGTH_LONG).show();
               ComponentName admin = new ComponentName(context, AdminReceiver.class);
               Intent intent = new Intent(
                   DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN).putExtra(
                       DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin);
               context.startActivity(intent);
       }           
   }
}

For those of us who landed here from google and weren't able to get the admin request to popup, I ended up solving it by making sure that I started the activity from a currently running Activity (thus, calls would not need the context. in front of them. While some may have had luck with intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) from a service, I had to move the call into an Activity.

ComponentName admin = new ComponentName(context, AdminReceiver.class);
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
  .putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin);
startActivity(intent);

0

This worked for me after following user6490462's instructions but I had to tweak the Intent slightly

Even with these changes, for some reason I could not get the activity window to pop up to approve the device admin privilege's. But when I went into Biometrics and security -> Other security settings -> Device admin apps I could see my app there waiting to have its admin privilege's approved.

    ComponentName admin = new ComponentName(getApplicationContext(), AdminReceiver.class);
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
                    "Allow this app to turn screen off");
startActivity(intent);
Chris H
  • 1
  • 1