从服务启动活动时延迟

ara*_*gar 5 android android-intent

我有一个接收屏幕广播的广播接收器,当屏幕关闭时,它会启动一个活动.我已将此活动命名为LockScreenActivity.我已经添加 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);onCreate()活性,使其出现在Android的锁屏,这正是我想要的顶部.这种方法效果很好,主要是.每当我按主页按钮将任何应用程序发送到后台时,就会出现问题.

当我按下主页按钮从任何应用程序返回主屏幕,然后立即按电源按钮关闭屏幕,并在一秒钟内按电源按钮重新打开,它显示Android锁定屏幕.我的活动在3-4秒后创建.这是一个巨大的延迟,是不可接受的.在其他情况下,这种延迟不会发生.如果我已经在主屏幕上呆了一段时间,或者某个其他应用程序已打开,我连续两次点击电源按钮,我会在看到Android锁屏之前看到我的LockScreenActivity.

我的应用程序还有一些其他正常活动(从App抽屉启动)和一个显示持久通知的服务.单击通知时将启动相同的LockScreenActivity.有趣的是,如果我按下主页按钮以最小化某个应用程序并立即单击我的应用程序的通知,它会毫不拖延地打开LockScreenActivity.

我经常搜索任何解决方案.这是我到目前为止尝试过的:

  1. 通过在注册广播接收器时传递处理程序使广播接收器在单独的线程中运行
  2. 在广播接收器中获取了一个唤醒锁,onReceive()并将其发布onResume()到LockScreenActivity中
  3. 通过在清单中指定不同的taskAffinity,为LockScreenActivity创建单独的任务堆栈.我还玩过很多与活动堆栈相关的选项组合,但到目前为止还没有任何帮助.
  4. 不是直接启动活动,而是向服务发送意图,然后启动活动.遗憾的是,没有任何工作.

这是活动和服务的清单声明:

<activity
        android:name=".LockScreenActivity"
        android:label="@string/app_name"
        android:excludeFromRecents="true"
        android:taskAffinity="@string/task_lockscreen">
</activity>
<service
        android:name=".services.BaseService"
        android:enabled="true" >
</service>
Run Code Online (Sandbox Code Playgroud)

广播接收器:

public class ScreenReceiver extends BroadcastReceiver {
private static final String LOG_TAG = ScreenReceiver.class.getSimpleName();
private static final String HANDLER_THREAD_NAME = "screen_receiver_thread";
public static final String WAKELOCK_TAG = "lockscreen_overlay_create_wakelock";

@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
        WakeLockHelper.acquireWakeLock(WAKELOCK_TAG, context);
        Log.d(LOG_TAG, "Screen off");
        context.startService(BaseService.getServiceIntent(context, null, BaseService.ACTION_START_LOCKSCREEN_ACTIVITY));
    } else {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            Log.d(LOG_TAG, "Screen on");
        }
    }
}

public static void registerScreenReceiver(Context context){
    new BroadcastReceiverRegistration().execute(context);
}

private static class BroadcastReceiverRegistration extends AsyncTask<Context, Void, Void>{
    @Override
    protected Void doInBackground(Context... params) {
        Context context = params[0];
        if(Utility.checkForNullAndWarn(context, LOG_TAG)){
            return null;
        }
        HandlerThread handlerThread = new HandlerThread(HANDLER_THREAD_NAME);
        handlerThread.start();
        Looper looper = handlerThread.getLooper(); //Will block till thread is started, hence using AsyncTask
        Handler handler = new Handler(looper);

        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        BroadcastReceiver mReceiver = new ScreenReceiver();

        context.registerReceiver(mReceiver, filter, null, handler);
        return null;
    }
}
}
Run Code Online (Sandbox Code Playgroud)

WakeLockHelper是一个管理我的应用程序中所有唤醒锁的类.registerScreenReceiver()服务在启动时调用.

这是LockScreenActivity的onCreate():

protected void onCreate(Bundle savedInstanceState) {
    Log.d(LOG_TAG, "LockscreenActivity onCreate()");
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_lock_screen);
    if (savedInstanceState == null) {
        getFragmentManager().beginTransaction()
                .add(R.id.container, new LockScreenFragment())
                .commit();
    }
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    getWindow().setDimAmount((float) 0.4);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

    int systemUiVisibilityFlags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
            View.SYSTEM_UI_FLAG_FULLSCREEN |
            View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        systemUiVisibilityFlags = systemUiVisibilityFlags | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
    }
    getWindow().getDecorView().setSystemUiVisibility(systemUiVisibilityFlags);
}
Run Code Online (Sandbox Code Playgroud)

当事情按预期工作时,这是日志:(屏幕初始亮起;它被关闭然后再打开)

09-19 11:00:09.384  31226-31243/com.pvsagar.smartlockscreen D/ScreenReceiver? Screen off
09-19 11:00:09.384  31226-31226/com.pvsagar.smartlockscreen D/BaseService? Starting lockscreen overlay.
09-19 11:00:09.394  31226-31226/com.pvsagar.smartlockscreen D/LockScreenActivity? LockscreenActivity onCreate()
09-19 11:00:09.735  31226-31243/com.pvsagar.smartlockscreen D/ScreenReceiver? Screen on
Run Code Online (Sandbox Code Playgroud)

屏幕关闭和发送意图和LockScreenActivity实际启动之间没有多少延迟.现在屏幕最初开启; 我从某个应用程序(任何应用程序,甚至我自己的应用程序的其他一些活动)按回家; 屏幕已关闭然后再打开:

09-19 11:02:51.557  31226-31243/com.pvsagar.smartlockscreen D/ScreenReceiver? Screen off
09-19 11:02:51.557  31226-31226/com.pvsagar.smartlockscreen D/BaseService? Starting lockscreen overlay.
09-19 11:02:51.708  31226-31243/com.pvsagar.smartlockscreen D/ScreenReceiver? Screen on
09-19 11:02:54.851  31226-31226/com.pvsagar.smartlockscreen D/LockScreenActivity? LockscreenActivity onCreate()
Run Code Online (Sandbox Code Playgroud)

在这里,正如您所看到的,屏幕关闭广播是及时收到的,服务立即获得意图并将意图发送到LockScreenActivity,但LockScreenActivity的onCreate()延迟3秒.

这就是服务启动LockScreenActivity的方式:

Intent lockscreenIntent = new Intent(this, LockScreenActivity.class);
lockscreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Log.d(LOG_TAG, "Starting lockscreen overlay.");
startActivity(lockscreenIntent);
Run Code Online (Sandbox Code Playgroud)

这是传递给通知的待处理意图(只是为了表明它做同样的事情):

Intent notificationIntent = new Intent(context, LockScreenActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notificationBuilder.setContentIntent(pendingIntent);
Run Code Online (Sandbox Code Playgroud)

我不知道为什么会这样.GC也没有运行太多.可能是什么问题呢?我能做些什么来克服这个问题?任何建议/想法将不胜感激.

整个代码可以在以下网址找到:https://github.com/aravindsagar/SmartLockScreen/tree/backend_code_strengthening

ara*_*gar 5

经过大量挖掘,找出了问题的原因。显然,这不是一个错误,它是一项功能,在按下主页按钮后,该功能不允许Services或BroadcastReceivers在最多5秒钟内启动活动。没有简单的方法可以克服这个问题。

此处提供更多信息:https : //code.google.com/p/android/issues/detail?id=4536

我用添加到正在运行的服务的窗口管理器中的窗口替换了活动。这不会引起任何延迟。