2014-09-19 17 views
5

Ich habe einen Broadcast-Empfänger, der eine Bildschirm-Aus-Sendung empfängt, und wenn der Bildschirm ausgeschaltet wird, startet er eine Aktivität. Ich habe diese Aktivität LockScreenActivity genannt. Ich habe getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); in onCreate() der Aktivität hinzugefügt, so dass es oben auf dem Android-Lockscreen erscheint, was genau das ist, was ich will. Das funktioniert meistens gut. Das Problem tritt auf, wenn ich die Home-Taste drücke, um die App an den Hintergrund zu senden.Verzögerung beim Starten der Aktivität vom Dienst

Wenn ich die Home-Taste drücke, um von jeder App zum Home-Bildschirm zurückzukehren, drücke sofort den Netzschalter, um den Bildschirm auszuschalten, und drücke den Netzschalter innerhalb einer Sekunde, um wieder einzuschalten. Meine Aktivität wird 3-4 Sekunden später erstellt. Dies ist eine große Verzögerung und ist inakzeptabel. In anderen Szenarien tritt diese Verzögerung nicht auf. Wenn ich seit einiger Zeit im Startbildschirm bin oder eine andere App geöffnet ist und zweimal hintereinander auf die Einschalttaste klicke, sehe ich meine LockScreenActivity, bevor ich den Android-Sperrbildschirm sehe.

Meine App hat auch ein paar andere normale Aktivitäten (gestartet von der App-Schublade) und einen Dienst, der eine dauerhafte Benachrichtigung anzeigt. Die gleiche LockScreenActivity wird immer dann gestartet, wenn auf die Benachrichtigung geklickt wird. Interessanterweise, wenn ich die Home-Taste drücke, um einige Apps zu minimieren und sofort auf die Benachrichtigung meiner App zu klicken, öffnet sich die LockScreenActivity ohne Verzögerung.

Ich habe viel nach einer Lösung gesucht. Hier ist, was ich bisher ausprobiert:

  1. Aus den Rundfunkempfänger laufen in separaten Thread durch einen Handler fließt, wenn der Rundfunkempfänger Registrierung
  2. Erworbene einen WakeLock in der Rundfunkempfänger des onReceive() und veröffentlichte sie in onResume() von LockScreenActivity
  3. Erstellt einen separaten Taskstapel für LockScreenActivity, indem eine andere taskAffinity im Manifest angegeben wird. Ich habe auch mit vielen Kombinationen der Optionen im Zusammenhang mit dem Aktivitäts-Stack gespielt, aber bisher hat nichts geholfen.
  4. Anstatt die Aktivität direkt zu starten, wurde eine Absicht an den Dienst gesendet, die dann die Aktivität startet. Nichts hat funktioniert, leider.

Hier ist das Manifest Erklärung der Tätigkeit und Service:

<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> 

Rundfunkempfänger:

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; 
    } 
} 
} 

WakeLockHelper ist eine Klasse, die alle wakelocks in meiner App verwaltet. registerScreenReceiver() wird vom Dienst beim Start aufgerufen.

Hier ist die onCreate() von LockScreenActivity:

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); 
} 

Hier ist das Protokoll, wenn die Dinge funktionieren wie erwartet: (Screen intially eingeschaltet ist, wird es ausgeschaltet und wieder einschalten)

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 

Nicht viel Verzögerung zwischen Bildschirm ab und Senden der Absicht und der LockScreenActivity, die tatsächlich beginnt.Jetzt Bildschirm ist zunächst an; Ich drücke von einer App nach Hause (jede App, sogar eine andere Aktivität meiner eigenen App); Bildschirm ausgeschaltet ist und wieder ein:

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() 

Hier, wie Sie sehen können, abschirmen Sendung wird in der Zeit empfangen, Service bekommt die Absicht sofort und senden Sie die Absicht zu LockScreenActivity, aber onCreate() von LockScreenActivity verzögert um 3 Sekunden.

Dies ist, wie die LockScreenActivity vom Dienst gestartet wird:

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

Dies wird die anstehende Absicht auf die Meldung übergeben (nur um zu zeigen, dass es die gleiche Sache tut):

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); 

Ich habe keine Ahnung, warum das passiert. GC läuft auch nicht zu viel. Was könnte das Problem sein? Was kann ich tun, um das zu überwinden? Alle Vorschläge/Ideen würden sehr geschätzt werden.

Der gesamte Code finden Sie unter: https://github.com/aravindsagar/SmartLockScreen/tree/backend_code_strengthening die Ursache des Problems

+0

Ich habe versucht, auch einen anderen Launcher verwenden, und das gleiche Problem besteht fort. Wie kann ich wissen, was passiert? Ich meine, wie finde ich heraus, was falsch ist? – aravindsagar

Antwort

3

Nach viel Graben, herausgefunden. Anscheinend ist es kein Fehler, es ist eine Funktion, die es Services oder BroadcastReceivern nicht erlaubt, Aktivitäten für bis zu 5 Sekunden nach dem Drücken der Home-Taste zu starten. Keine einfache Möglichkeit, dies zu überwinden.

Mehr Infos hier: https://code.google.com/p/android/issues/detail?id=4536

ersetzte ich die Aktivität mit einem Fenster zum Fenstermanager des laufenden Dienstes hinzugefügt. Dies verursacht keine Verzögerung.

0

finden Sie die Lösung here

Mit Intent Schwebende und die Anfrage sofort das Problem für mich gelöst aussendet, hoffen, dass es Ihnen hilft auch :)

Verwandte Themen