Вопрос

This may seem similar to other questions, but I have been looking for a while now and haven't found a solution that works in my particular case.

My app's BroadcastReceiver currently acquires a full wakelock, disables the keyguard, then starts another activity previously chosen by the user (another app, a shortcut intent, etc). The issue I have run into is when I try to re-enable the keyguard (I believe the wakelock gets released, but I will make sure of that at another time).

Since another activity is called, I can't use the Window flags, so I have been trying to use KeyguardManager.KeyguardLock to disable and enable. Also, since I have no control over what the user does in the other app, I would like to re-enable the keyguard the next time the screen is turned off. I understand that a regular BroadcastReceiver for this won't work, so I have been trying to implement a Service to take care of it, and that's where I'm having some trouble.

Currently, I start the Service when the first BroadcastReceiver is triggered, I have the Service register another BroadcastReceiver for ACTION_SCREEN_OFF in OnCreate, and have ScreenOffReceiver call the Service's onStartCommand which should re-enable the keyguard. I have a boolean in onStartCommand to know which BroadcastReceiver called it.

Right now, the keyguard either doesn't re-enable, or re-enables too quickly (before the screen turns off). Any thoughts?

Here's some code:

AlarmActivity is called by the first BroadcastReceiver to open the user-selected action:

public class AlarmActivity extends Activity {

public static Boolean keyguardDisabled = false;

PowerManager pm;
WakeLock myWakeLock;

KeyguardManager km;
@SuppressWarnings("deprecation")
KeyguardManager.KeyguardLock keylock;


@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // code to turn screen on
    // acquire wakelock
    pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    myWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "MyWakelock");

    // disable keyguard
    km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    keylock = km.newKeyguardLock("myLock");
    keyguardDisabled = true;

    // start service which will re-enable keyguard on next screen off
    Intent i = new Intent(this, ReenableKeyguardService.class);
            startService(i);

    keylock.disableKeyguard();      
    myWakeLock.acquire();

            // rest of AlarmActivity code

Here is the Service:

public class ReenableKeyguardService extends Service {
BroadcastReceiver mReceiver = null;

PowerManager pm;
WakeLock myWakeLock;

KeyguardManager km;
@SuppressWarnings("deprecation")
KeyguardManager.KeyguardLock keylock;

@Override
public void onCreate() {
    super.onCreate();
    // REGISTER RECEIVER THAT HANDLES SCREEN OFF LOGIC
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
    mReceiver = new ScreenOffReceiver();
    registerReceiver(mReceiver, filter);
}

@SuppressWarnings("deprecation")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    if (AlarmActivity.keyguardDisabled == true && ScreenOffReceiver.screenTurnedOff == true) {
        pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        myWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "MyWakelock");

        km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        keylock = km.newKeyguardLock("myLock");

        keylock.reenableKeyguard();
        keylock = null;

        if (myWakeLock.isHeld()) {
            myWakeLock.release();
            myWakeLock = null;
        }

        AlarmActivity.keyguardDisabled = false;
        ScreenOffReceiver.screenTurnedOff = false;

        stopSelf();
    }
    return 1;
}

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void onDestroy() {

    if(mReceiver!=null) {
        unregisterReceiver(mReceiver);
    }             
}
}

And here is the ScreenOffReceiver:

public class ScreenOffReceiver extends BroadcastReceiver {

public static Boolean screenTurnedOff = false;

@Override
public void onReceive(Context context, Intent intent) {

    if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
        Intent i = new Intent(context, ReenableKeyguardService.class);
        screenTurnedOff = true;
        context.startService(i);
    }
}
}
Это было полезно?

Решение

After re-thinking how I was doing this, I opted to handle all of the wakelock and keyguard code in the Service, which seems to work pretty well. So AlarmActivity just starts the Service (I removed all the other code from it), and ScreenOffReceiver stayed the same. Here is the updated Service code in case it helps anyone in the future:

public class KeyguardService extends Service {
BroadcastReceiver mReceiver = null;
Boolean keyguardDisabled;

PowerManager pm;
WakeLock myWakeLock;

KeyguardManager km;
@SuppressWarnings("deprecation")
KeyguardManager.KeyguardLock keylock;

@SuppressWarnings("deprecation")
@Override
public void onCreate() {
    super.onCreate();

    // code to turn screen on
    // acquire wakelock
    pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    myWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "MyWakelock");

    // disable keyguard
    km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    keylock = km.newKeyguardLock("myLock");


    keylock.disableKeyguard();

    // ensure secure keyguard won't be bypassed
    km.exitKeyguardSecurely(null);

    // acquire wakelock that will timeout based on current user setting
    myWakeLock.acquire(Settings.System.getLong(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 1000));
    keyguardDisabled = true;


    // REGISTER RECEIVER THAT HANDLES SCREEN OFF LOGIC
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
    mReceiver = new ScreenOffReceiver();
    registerReceiver(mReceiver, filter);
}


@SuppressWarnings("deprecation")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    if (keyguardDisabled == true && ScreenOffReceiver.screenTurnedOff == true) {
        keylock.reenableKeyguard();
        keylock = null;

        if (myWakeLock.isHeld()) {
            myWakeLock.release();
            myWakeLock = null;
        }

        keyguardDisabled = false;
        ScreenOffReceiver.screenTurnedOff = false;

        stopSelf();
    }
    return 1;
}

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void onDestroy() {

    if(mReceiver!=null) {
        unregisterReceiver(mReceiver);
    }             
}
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top