2012-05-15 6 views
23

Ich versuche ActivityLifecycleCallbacks automatisch zu erfassen und melden Ereignisse Android Lifecycle Verwendung in dieser Angelegenheit jedoch Dokumentation ist knapp, die am wenigsten zu sagen:Android-Lifecycle-Ereignisse automatisch mit ActivityLifecycleCallbacks protokollieren?

public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback) 

Ich will nicht die Aktivitätsklasse oder Überschreibung haben, zu erweitern Die vorhandenen Lifecycle-Methoden (onCreate, onResume, etc ...) Ich suche nach einer separaten Klasse, die auf diese Ereignisse wartet und entsprechend handelt.

Hat jemand Erfahrung darin oder Links zu guter solider Dokumentation oder Anleitungen, wie das funktioniert? Insbesondere, wie man sich für ActivityLifecycleCallbacks registriert und wie man damit umgeht?

+1

UPDATE: Die Standard-API ist nun schon lange Genug, dass @ ClarkXP's Roll-your-own für die meisten Apps übertrieben ist. Sehen Sie stattdessen @ Jeroen's Antwort. Ich fasse zusammen: "In Ihrer Callback-Klasse (die' Application.ActivityLifecycleCallbacks' implementiert hat), führen Sie in ihrem Konstruktor 'getApplication(). RegisterActivityLifecycleCallbacks (this);' Wenn Ihre Klasse ein 'onCreate' oder' init' oder hat ähnliche Methode, die ausgeführt wird, wenn die Instanz aktiv wird, setzen Sie diese Zeile lieber dort als im Konstruktor (weil die Klasse vermutlich keine Rückrufe empfangen soll, bis sie vollständig fertig ist). " – ToolmakerSteve

Antwort

29

Ich habe meine eigene Implementierung von Application.ActivityLifecycleCallbacks. Ich verwende SherlockActivity, aber für normale Aktivität Klasse könnte funktionieren.

Zuerst Ich erstelle eine Schnittstelle, die alle Methoden für den Lebenszyklus Aktivitäten verfolgen:

public interface ActivityLifecycleCallbacks{ 
    public void onActivityStopped(Activity activity); 
    public void onActivityStarted(Activity activity); 
    public void onActivitySaveInstanceState(Activity activity, Bundle outState); 
    public void onActivityResumed(Activity activity); 
    public void onActivityPaused(Activity activity); 
    public void onActivityDestroyed(Activity activity); 
    public void onActivityCreated(Activity activity, Bundle savedInstanceState); 
} 

Zweitens implementiert ich diese Schnittstelle in der Klasse meiner Anwendung:

public class MyApplication extends Application implements my.package.ActivityLifecycleCallbacks{ 

    @Override 
    public void onCreate() { 
     super.onCreate();   
    } 

    @Override 
    public void onActivityStopped(Activity activity) { 
     Log.i("Tracking Activity Stopped", activity.getLocalClassName()); 

    } 

    @Override 
    public void onActivityStarted(Activity activity) { 
     Log.i("Tracking Activity Started", activity.getLocalClassName()); 

    } 

    @Override 
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 
     Log.i("Tracking Activity SaveInstanceState", activity.getLocalClassName()); 
    } 

    @Override 
    public void onActivityResumed(Activity activity) { 
     Log.i("Tracking Activity Resumed", activity.getLocalClassName()); 
    } 

    @Override 
    public void onActivityPaused(Activity activity) { 
     Log.i("Tracking Activity Paused", activity.getLocalClassName()); 
    } 

    @Override 
    public void onActivityDestroyed(Activity activity) { 
     Log.i("Tracking Activity Destroyed", activity.getLocalClassName()); 
    } 

    @Override 
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 
     Log.i("Tracking Activity Created", activity.getLocalClassName()); 
    } 
} 

Drittens I bin eine Klasse, die sich von SherlockActivity erstreckt:

public class MySherlockActivity extends SherlockActivity { 

    protected MyApplication nMyApplication; 

    protected void onCreate(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onCreate(savedInstanceState); 
     nMyApplication = (MyApplication) getApplication(); 
     nMyApplication.onActivityCreated(this, savedInstanceState); 
    } 

    protected void onResume() { 
     // TODO Auto-generated method stub 
     nMyApplication.onActivityResumed(this); 
     super.onResume(); 

    } 

    @Override 
    protected void onPause() { 
     // TODO Auto-generated method stub 
     nMyApplication.onActivityPaused(this); 
     super.onPause(); 
    } 

    @Override 
    protected void onDestroy() { 
     // TODO Auto-generated method stub 
     nMyApplication.onActivityDestroyed(this); 
     super.onDestroy(); 
    } 

    @Override 
    protected void onStart() { 
     nMyApplication.onActivityStarted(this); 
     super.onStart(); 
    } 

    @Override 
    protected void onStop() { 
     nMyApplication.onActivityStopped(this); 
     super.onStop(); 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     nMyApplication.onActivitySaveInstanceState(this, outState); 
     super.onSaveInstanceState(outState); 
    } 
} 

Viertens, alle Klasse tha t von SherlockActivity zu verlängern, die ich für MySherlockActivity ersetzt:

public class MainActivity extends MySherlockActivity{ 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
    } 

} 

Jetzt, in der logcat sehen Sie die programmierten Protokolle in der Interface-Implementierung in MyApplication gemacht.

UPDATE

Diese Implementierung von API Stufe 9 (Lebkuchen), API Stufe 12 (Honeycomb) und API-Stufe 17 (Jelly Bean) und funktioniert gut getestet wurde. Könnte in älteren Android-Versionen funktionieren.

+2

Der Vollständigkeit halber sollten Sie onActivityRestart() zur Schnittstelle und den entsprechenden Methoden zu MyApplication und MySherlockActivity hinzufügen. Mir ist klar, dass diese Methode nicht Teil von ActivityLifecycleCallbacks von Android ist, aber onRestart _ist_ Teil des Lebenszyklus einer Aktivität. –

+1

Nützlich für ältere Geräte. HINWEIS: Wenn Sie (irgendjemand) Application.ActivityLifecycleCallbacks verwenden möchten, gehen Sie davon aus, dass Sie über eine API verfügen, die neu genug ist, und Sie können die benutzerdefinierte Schnittstelle und die Aktivitätserweiterung weglassen. Machen Sie einfach (1) den ersten Code-Abschnitt, der zeigt, wie man eine Klasse (in diesem Fall Application) erweitert, um die Schnittstelle zu implementieren, aber implementiert 'Application.ActivityLifecycleCallbacks'. Und (2) 'getApplication(). RegisterActivityLifecycleCallbacks (this);' in Ihrer Callbackklasse 'constructor oder onCreate. – ToolmakerSteve

39

Ich habe keine Erfahrung aus erster Hand, sondern von der API urteilen können Sie einfach Ihre eigene Klasse schreiben, die den Application.ActivityLifecycleCallbacks-Schnittstelle implementiert und registriere diese Klasse auf der mitgelieferten Application Klasseninstanz

getApplicaton().registerActivityLifecycleCallbacks(yourCustomClass); 

Diese Klasse erhält die gleichen Rückrufe wie Ihre individuellen Aktivitäten. Viel Glück.

PS. Dies ist API Ebene 14 BTW, so dass es auf älteren Telefonen nicht funktioniert.

+1

@ClarkXP Ja, aber der Vererbungslink ist zu stark für die Anwendungsklasse. Dies ist nicht modular genug, um in eine lib umgewandelt zu werden. – Snicolas

+0

Um die 'Register'-Zeile zu verdeutlichen: In Ihrer Callback-Klasse (die' application.ActivityLifecycleCallbacks' implementiert hat), führen Sie in ihrem Konstruktor 'getApplication(). RegisterActivityLifecycleCallbacks (this);' Wenn Ihre Klasse ein 'onCreate' oder' init hat 'oder eine ähnliche Methode, die ausgeführt wird, wenn die Instanz aktiv wird, setzen Sie diese Zeile lieber dort als im Konstruktor (weil die Klasse vermutlich keine Rückrufe empfangen soll, bis sie vollständig bereit ist). – ToolmakerSteve

+3

Das sieht perfekt für mich aus, aber ich frage mich, wo unregisterActivityLifecycleCallbacks() -Methode aufgerufen werden soll. Ist es nicht erforderlich? – Amit

3

Try this: http://engineering.meetme.com/2015/04/android-determine-when-app-is-opened-or-closed/#comment-202

Es schlägt eine AppForegroundStateManager zu dem jedes Tätigkeitsberichte über seine onStop() und onStart() Funktionen wie folgt aus:

@Override 
protected void onStart() { 
    super.onStart(); 
    AppForegroundStateManager.getInstance().onActivityVisible(this); 
} 

@Override 
protected void onStop() { 
    AppForegroundStateManager.getInstance().onActivityNotVisible(this); 
    super.onStop(); 
} 

Ihre Application Klasse implementiert ein Zuhörer wie folgt aus:

public class MyApplication extends Application { 
    @Override 
    public void onCreate() { 
     super.onCreate(); 
     AppForegroundStateManager.getInstance().addListener(this); 
    } 

    @Override 
    public void onAppForegroundStateChange(AppForegroundStateManager.AppForegroundState newState) { 
     if (AppForegroundStateManager.AppForegroundState.IN_FOREGROUND.equals(newState)) { 
      // App just entered the foreground. Do something here! 
      Log.i(TAG, "App Just Entered the Foreground with launch mechanism of: " + mLaunchMechanism); 
     } else { 
      // App just entered the background. Set our launch mode back to the default of direct. 
      mLaunchMechanism = LaunchMechanism.DIRECT; 
     } 
    } 
} 

Es enthält auch Tipps und Tricks zum Bestimmen von ho w Die App wurde geöffnet - von einer Benachrichtigung, einer URL zum Öffnen Ihrer App oder direkt aus dem Apps-Menü. Dies wird durch eine Enum in der Application-Klasse getan:

public enum LaunchMechanism { 
    DIRECT, 
    NOTIFICATION, 
    URL, 
    BACKGROUND 
} 

private LaunchMechanism mLaunchMechanism = LaunchMechanism.DIRECT; 

public void setLaunchMechanism(LaunchMechanism launchMechanism) { 
    mLaunchMechanism = launchMechanism; 
} 

In unserer Implementierung dieser, haben wir Fahnen, wenn wir eine Aktivität starten, die eine Drittanbieter-Aktivität starten, wie wenn der Benutzer einen Anruf macht aus unserer App oder wenn ein Browser gestartet wird. In der onStop() der Abschuss Aktivität, die wir tun, dann eine Prüfung wie diese nur den Tätigkeitsbericht der nicht-Sichtbarkeit, wenn diese Flags sind falsch:

if(!flag_userLaunchedThirdPartyActivity){ 
    AppForegroundStateManager.getInstance().onActivityNotVisible(this); 
    } 

Zur Überprüfung, ob die Anwendung in den Hintergrund geht - zum Beispiel, wenn die Geräte Bildschirm dunkel oder der Benutzer erhält einen Anruf - es funktioniert wie folgt:

public static boolean isApplicationGoingToBackground(final Context context) { 

    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 
    List<RunningTaskInfo> tasks = am.getRunningTasks(1); 
    if (!tasks.isEmpty()) { 
     ComponentName topActivity = tasks.get(0).topActivity; 
     if (!topActivity.getPackageName().equals(context.getPackageName())) { 
      setLaunchMechanism(LaunchMechanism.BACKGROUND); 
      return true; 
     } 
    } 

    setLaunchMechanism(LaunchMechanism.DIRECT); 
    return false; 
} 

diese Lösung nicht abhängig von einer API-Ebene ist, so sollte es den ganzen Weg zurück zu arbeiten API-Ebene 1.

0
@Override 
public void onCreate() { 
    super.onCreate(); 
    registerActivityLifecycleCallbacks(MyApplication.this/*(Your Application Name)*/); 

// registerActivityLifecycleCallbacks (MyApplication.this/(Ihr Anwendungsname)/ // nur diese Zeile auf Anwendungsklasse alles funktioniert gut

}

Verwandte Themen