Android 启动模式之 FLAG_ACTIVITY_CLEAR_TOP

以前对于activity的启动模式没有特别在意,最近在项目中遇到了麻烦事,对于启动模式又去了解一遍,除了常用的4种启动模式,还有一些特别的启动flag,用处也特别大

FLAG_ACTIVITY_CLEAR_TOP 谷歌文档:

If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.

For example, consider a task consisting of the activities: A, B, C, D.
If D calls startActivity() with an Intent that resolves to the
component of activity B, then C and D will be finished and B receive
the given Intent, resulting in the stack now being: A, B.

  1. 最近项目遇到一个麻烦的事情,做Android自定义锁屏的时候,我们有个功能是在锁屏的时候,提供一个快捷入口,让用户使用我们的锁屏,能够快速的打开相机,拍照使用,当用户使用完了之后,按返回键的时候,我们要重新把我们自己的锁屏给锁上;
  2. 实现流程是这样的,用rxjava每隔1s,去检测栈顶的应用的包名与我们启动的应用的包名是否一致,如果一致,说明用户还在当前的应用中,我们不必锁屏,当用户按返回按钮,说明当前栈顶的包名改变了,需要我们去执行锁屏操作,这些实现逻辑,都是没有问题的;
  3. 但是问题来了,用户跳转到相机里面,然后点击相册时候的,包名改变了,我们的锁屏检测到与起初跳转intent的包名不一致,于是就锁屏了,当用户再次在我们锁屏点击相机的时候,发现相机变成相册了,锁屏就锁起来了,相机进不去了,导致这个问题的原因是:Android 系统里面的相机和相册他们的包名是不一致的,但是却在同一个应用的进程里面,所以对外看来,他们是一个应用。
  4. 怎么解决这个问题?有两个思路:1、不给用户点击进去相册(这个有点不太妥当);2、每次进入相机都保证他是唯一的activity,并且在栈顶显示。
  5. 可见方案一不是特别好的解决方法,用MediaStore.ACTION_IMAGE_CAPTURE 可以让用户没有进入相册的入口
  6. 方案二,就是使用我们的FLAG_ACTIVITY_CLEAR_TOP作为flag,保证我们的相机在栈顶上,这样就会把相机上面的相册给清理掉;
     Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                if (Build.VERSION.SDK_INT > 17) {
                    intent.setAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
                    List<ResolveInfo> info = getContext().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                    if (info == null || info.size() == 0) {
                        intent.setAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
                    }
                }

7.附上检测栈顶的代码:

```
 mCheckSubscription = Observable
                .interval(1000, TimeUnit.MILLISECONDS)
                .map(new Func1<Long, Boolean>() {
                         @Override
                         public Boolean call(Long aLong) {

                             Log.v("LockScreenManager", "checking top activity: " + validPackageName);
                             if (Build.VERSION.SDK_INT >= 21) {
                                 @SuppressWarnings("WrongConstant")
                                 UsageStatsManager usm = (UsageStatsManager) BaseApplication.getDefaultApplication().getSystemService("usagestats");
                                 long time = System.currentTimeMillis();
                                 List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 1000, time);
                                 if (appList != null && appList.size() > 0) {
                                     SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
                                     for (UsageStats usageStats : appList) {
                                         mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
                                     }
                                     if (!mySortedMap.isEmpty()) {
                                         String foregroundPackageName = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
                                         Log.v("LockScreenManager", "last top activity: " + foregroundPackageName);
                                         if (foregroundPackageName.equals(validPackageName)) {
                                             return false;
                                         }
                                     }
                                 }
                                 return true;
                             } else {
                                 ActivityManager am = (ActivityManager) BaseApplication.getDefaultApplication().getSystemService(Context.ACTIVITY_SERVICE);
                                 List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
                                 ComponentName componentName = taskInfo.get(0).topActivity;
                                 if (componentName.getPackageName().equals(validPackageName)) {
                                     return false;
                                 }
                                 return true;
                             }
                         }
                     }
                )
                .filter(new Func1<Boolean, Boolean>() {
                    @Override
                    public Boolean call(Boolean aBoolean) {
                        return aBoolean;
                    }
                })
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Boolean>() {
                    @Override
                    public void call(Boolean b) {
                        Log.v("LockScreenManager", "showLockScreen");
                        showLockScreen();
                        stopCheckTopActivity();
                    }
                });

“`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值