Android实现全局前后台监听

Posted Tobey_r1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android实现全局前后台监听相关的知识,希望对你有一定的参考价值。

关于

  前段时间工作的时候有一个小需求,做一个登出的监听功能并在任何界面弹窗提示,因为没有用到一些推送通知(后台接口没有添加这个功能)来判断是否被其他人登录,所以就没有用到广播机制。但是因为我们做的项目用到了视频服务是会有登录登出顶号的监听的,那是不是可以用这个来监听并通过registerActivityLifecycleCallbacks接口监听activity生命周期获取当前对应actiivty,来做全局弹窗的载体。此篇文章也会作为简易音乐博客系列的使用工具类之一。

第一步,编写activity堆栈式管理类

/**
 * Created by tobey on 2021/6/7.
 * activity堆栈式管理
 */
public class AppManager {

    private static final String TAG = "ActivityStackManager";
    //使用弱引用持有activity,防止内存泄露
    private static Stack<WeakReference<Activity>> activityStack;
    private static Stack<Fragment> fragmentStack;
    private static AppManager instance;

    private AppManager() {
    }

    /**
     * 单例模式
     *
     * @return AppManager
     */
    public static AppManager getAppManager() {
        if (instance == null) {
            instance = new AppManager();
        }
        return instance;
    }

    /**
     * 获取Activity栈
     * @return Activity栈
     */
    public  Stack<WeakReference<Activity>> getActivityStack() {
        return activityStack;
    }

    public static Stack<Fragment> getFragmentStack() {
        return fragmentStack;
    }


    /**
     * 添加Activity到堆栈
     */
    public void addActivity(WeakReference<Activity> activity) {
        if (activityStack == null) {
            activityStack = new Stack<>();
        }
        activityStack.add(activity);
    }



    /**
     * 移除指定的Activity
     */
    public void removeActivity(WeakReference<Activity> activity) {
        if (activity != null) {
            activityStack.remove(activity);
        }
    }


    /**
     * 是否有activity
     */
    public boolean isActivity() {
        if (activityStack != null) {
            return !activityStack.isEmpty();
        }
        return false;
    }

    /**
     * 获取当前Activity(堆栈中最后一个压入的)
     */
    public Activity currentActivity() {
        Activity activity = activityStack.lastElement().get();
        return activity;
    }

    /**
     * 结束当前Activity(堆栈中最后一个压入的)
     */
    public void finishActivity() {
        try {
        WeakReference<Activity> activity = activityStack.lastElement();
        finishActivity(activity);
        }catch (Exception e){
            Log.e(TAG, e.getMessage());
        }
    }

    /**
     * 结束指定的Activity
     */
    public void finishActivity(WeakReference<Activity> activity) {

        try {
            Iterator<WeakReference<Activity>> iterator = activityStack.iterator();
            while (iterator.hasNext()) {
                WeakReference<Activity> stackActivity = iterator.next();
                if (stackActivity.get() == null) {
                    iterator.remove();
                    continue;
                }
                if (stackActivity.get().getClass().getName().equals(activity.get().getClass().getName())) {
                    iterator.remove();
                    stackActivity.get().finish();
                    break;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }

        /*if (activity != null) {
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }*/
    }

    /**
     * 结束指定类名的Activity
     */
    public void finishActivity(Class<?> cls) {

        try {
            ListIterator<WeakReference<Activity>> listIterator = activityStack.listIterator();
            while (listIterator.hasNext()) {
                Activity activity = listIterator.next().get();
                if (activity == null) {
                    listIterator.remove();
                    continue;
                }
                if (activity.getClass() == cls) {
                    listIterator.remove();
                    if (activity != null) {
                        activity.finish();
                    }
                    break;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }

       /* for (WeakReference<Activity> activity : activityStack) {
            if (activity.getClass().equals(cls)) {
                finishActivity(activity);
                break;
            }
        }*/
    }

    /**
     * 结束所有Activity
     */
    public void finishAllActivity() {

        ListIterator<WeakReference<Activity>> listIterator = activityStack.listIterator();
        while (listIterator.hasNext()) {
            Activity activity = listIterator.next().get();
            if (activity != null) {
                activity.finish();
            }
            listIterator.remove();
        }
        activityStack.clear();
        Process.killProcess(Process.myPid());
      /*  for (int i = 0, size = activityStack.size(); i < size; i++) {
            if (null != activityStack.get(i)) {
                finishActivity(activityStack.get(i));
            }
        }
        activityStack.clear();*/
    }

    /**
     * 获取指定的Activity
     *
     * @author kymjs
     */
    public Activity getActivity(Class<?> cls) {
        if (activityStack != null)
            for (WeakReference<Activity> activity : activityStack) {
                if (activity.get().getClass().equals(cls)) {
                    return activity.get();
                }
            }
        return null;
    }


    /**
     * 添加Fragment到堆栈
     */
    public void addFragment(Fragment fragment) {
        if (fragmentStack == null) {
            fragmentStack = new Stack<Fragment>();
        }
        fragmentStack.add(fragment);
    }

    /**
     * 移除指定的Fragment
     */
    public void removeFragment(Fragment fragment) {
        if (fragment != null) {
            fragmentStack.remove(fragment);
        }
    }


    /**
     * 是否有Fragment
     */
    public boolean isFragment() {
        if (fragmentStack != null) {
            return !fragmentStack.isEmpty();
        }
        return false;
    }

    /**
     * 获取当前Activity(堆栈中最后一个压入的)
     */
    public Fragment currentFragment() {
        if (fragmentStack != null) {
            Fragment fragment = fragmentStack.lastElement();
            return fragment;
        }
        return null;
    }


    /**
     * 退出应用程序
     */
    public void AppExit() {
        try {
            finishAllActivity();
            // 杀死该应用进程
//          android.os.Process.killProcess(android.os.Process.myPid());
//            调用 System.exit(n) 实际上等效于调用:
//            Runtime.getRuntime().exit(n)
//            finish()是Activity的类方法,仅仅针对Activity,当调用finish()时,只是将活动推向后台,并没有立即释放内存,活动的资源并没有被清理;当调用System.exit(0)时,退出当前Activity并释放资源(内存),但是该方法不可以结束整个App如有多个Activty或者有其他组件service等不会结束。
//            其实android的机制决定了用户无法完全退出应用,当你的application最长时间没有被用过的时候,android自身会决定将application关闭了。
            //System.exit(0);
        } catch (Exception e) {
            activityStack.clear();
            e.printStackTrace();
        }
    }
}

第二步,编写app继承application

  我们在application提供的所有activity生命周期监听的接口registerActivityLifecycleCallbacks中添加(别忘记在androidmanifest.xml配置文件中name=".App"):

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
      
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
                //activity创建的时候添加入栈
                WeakReference<Activity> weakReference = new WeakReference<>(activity);
                AppManager.getAppManager().addActivity(weakReference);
            }

            @Override
            public void onActivityStarted(@NonNull Activity activity) {

            }

            @Override
            public void onActivityResumed(@NonNull Activity activity) {

            }

            @Override
            public void onActivityPaused(@NonNull Activity activity) {

            }

            @Override
            public void onActivityStopped(@NonNull Activity activity) {

            }

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

            }

            @Override
            public void onActivityDestroyed(@NonNull Activity activity) {
               // 销毁的时候移除
                WeakReference<Activity> weakReference = new WeakReference<>(activity);
                AppManager.getAppManager().removeActivity(weakReference);
            }
        });

    }
}

  可以通过AppManager.getAppManager().currentActivity();获取当前的activity(我测试了singletask与top模式都不影响获取当前activity实例)用于类似退出功能弹框(这里用的三方sweetdialog):

  final SweetAlertDialog MyDialog = new SweetAlertDialog(AppManager.getAppManager().currentActivity(), SweetAlertDialog.WARNING_TYPE)
                        .setTitleText("当前账号已经挤掉线")
                        .setConfirmText("确定")
                        .setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
                            @Override
                            public void onClick(SweetAlertDialog sweetAlertDialog) {
                                sweetAlertDialog.dismiss();
                                Intent intent = new Intent(mInstance, LoginOrRegisterActivity.class);
                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                startActivity(intent);
                                AppManager.getAppManager().finishAllActivity();
                            }
                        });
                MyDialog.show();
                

  如果只想全局获取当前的activity实例,而不想管理activity堆栈(显然很多人不会这样想),可以编写MyActivityManager.java:
在想要退出app的地方,比如主界面,点击返回键两次退出程序:

   @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP){
            long secondTime = System.currentTimeMillis();
            if (secondTime - firstTime > 2000){
                showToast("再按一次退出程序");
                firstTime = secondTime;
                return true;
            }else {
                //调用退出移除activity栈
                AppManager.getAppManager().AppExit();
            }
        }
        return super.onKeyUp(keyCode,event);
    }
public class MyActivityManager {
    private static MyActivityManager sInstance = new MyActivityManager();
    private WeakReference<Activity> sCurrentActivityWeakRef;


    private MyActivityManager() {

    }

    public static MyActivityManager getInstance() {
        return sInstance;
    }

    public Activity getCurrentActivity() {
        Activity currentActivity = null;
        if (sCurrentActivityWeakRef != null) {
            currentActivity = sCurrentActivityWeakRef.get();
        }
        return currentActivity;
    }

    public void setCurrentActivity(Activity activity) {
        sCurrentActivityWeakRef = new WeakReference<Activity>(activity);
    }
}

  然后在上面的app类的如下代码里面添加:

 registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
                @Override
                public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
                    
                }

                @Override
                public void onActivityStarted(@NonNull Activity activity) {

                }

                @Override
                public void onActivityResumed(@NonNull Activity activity) {
                    MyActivityManager.getInstance().setCurrentActivity(activity);
                }

                @Override
                public void onActivityPaused(@NonNull Activity activity) {

                }

                @Override
                public void onActivityStopped(@NonNull Activity activity) {

                }

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

                }

                @Override
                public void onActivityDestroyed(@NonNull Activity activity) {
                   
                }
            });

  在需要获取当前activity实例的地方调用MyActivityManager.getInstance().getCurrentActivity()即可。
  关于如何判断app前后台的问题,只需要在onActivityResumed中判断即可。

      有问题欢迎批评指正,觉得不错的可以点个赞噢

以上是关于Android实现全局前后台监听的主要内容,如果未能解决你的问题,请参考以下文章

在同一个片段中实现多个事件监听器 - Android

Android实现后台长期监听时间变化

在Google Maps android上放置点击监听器

如何在android中去listview适配器项目点击监听器片段?

Android中的全局监听方式

如何在android后台服务中监听firebase事件?