Автоматически регистрировать события жизненного цикла Android с помощью ActivityLifecycleCallbacks?

Я пытаюсь автоматически записывать и регистрировать события жизненного цикла Android с помощью ActivityLifecycleCallbacks, однако документация по этому вопросу мало, по меньшей мере:

    public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)

Я не хочу расширять класс Activity или переопределять существующие методы жизненного цикла (onCreate, onResume и т.д.). Я ищу отдельный класс, который прослушивает эти события и действует соответственно.

Есть ли у кого-нибудь опыт в этом или есть ссылки на хорошую документацию или учебники о том, как это работает? В частности, как зарегистрироваться для ActivityLifecycleCallbacks и как их обрабатывать?

Ответ 1

Я сделал свою собственную реализацию Application.ActivityLifecycleCallbacks. Я использую SherlockActivity, но для обычного класса Activity может работать.

Во-первых, я создаю интерфейс, который имеет все методы для отслеживания жизненного цикла действий:

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

Во-вторых, я реализовал этот интерфейс в своем классе Application:

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

В-третьих, я создаю класс, который расширяется от SherlockActivity:

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
        super.onResume();
        nMyApplication.onActivityResumed(this);
    }

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

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

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

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

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

В-четвертых, все классы, которые выходят из SherlockActivity, я заменил на MySherlockActivity:

public class MainActivity extends MySherlockActivity{

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

}

Теперь в logcat вы увидите логи, запрограммированные в реализации интерфейса, выполненной в MyApplication.

ОБНОВИТЬ

Эта реализация была протестирована с API Level 9 (Gingerbread), API Level 12 (Honeycomb) и API Level 17 (Jelly Bean) и работает отлично. Might работает в старых версиях Android.

Ответ 2

У меня нет опыта на собственном опыте, но, судя по API, вы можете просто написать свой собственный класс, который реализует интерфейс Application.ActivityLifecycleCallbacks и регистрирует этот класс на при условии Application экземпляра класса

getApplicaton().registerActivityLifecycleCallbacks(yourCustomClass);

Этот класс получит те же обратные вызовы, что и ваши индивидуальные действия. Удачи.

PS. Это уровень API 14 битв, поэтому он не будет работать на старых телефонах.

Ответ 3

Попробуйте следующее: http://engineering.meetme.com/2015/04/android-determine-when-app-is-opened-or-closed/#comment-202

Он предлагает AppForegroundStateManager, с которым каждый вид активности через его onStop() и onStart() работает следующим образом:

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

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

Ваш класс Application реализует прослушиватель следующим образом:

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

Он также содержит советы и рекомендации для определения того, как приложение было открыто - из уведомления, URL-адреса, открывающего ваше приложение или непосредственно из меню "Службы". Это делается с помощью Enum в классе Application:

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

private LaunchMechanism mLaunchMechanism = LaunchMechanism.DIRECT;

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

В нашей реализации этого, у нас есть флаги, когда мы начинаем действие, которое запускает действие сторонних разработчиков, например, если пользователь делает телефонный звонок из нашего приложения или запускается браузер. В стартовом действии onStop() мы делаем такую ​​проверку, чтобы сообщать только о невидимости активности, когда эти флаги ложны:

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

Для проверки того, идет ли приложение в фоновом режиме - например, когда экран устройства становится темным или пользователь получает телефонный звонок - он работает следующим образом:

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

Это решение не зависит от уровня API, поэтому он должен полностью вернуться к уровню API 1.

Ответ 4

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

//registerActivityLifecycleCallbacks (MyApplication.this/(ваше имя приложения)/ // только добавьте эту строку в класс приложения, все работает хорошо

}

Ответ 5

это решение Kotlin работает на меня

public class AppController extends Application implements
        Application.ActivityLifecycleCallbacks
{
    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(this)
    }


    @Override
    public void onActivityCreated(Activity activity, Bundle bundle) {

    }

    @Override
    public void onActivityStarted(Activity activity) {

    }

    @Override
    public void onActivityResumed(Activity activity) {

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {

    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {

    }

    @Override
    public void onActivityDestroyed(Activity activity) {

    }
}

и не забудьте добавить эту строку в приложение в AndroidManifest.xml

<application
    [...]
    android:name=".AppController"
    [...]