一个BUG引起的思考

问题来源于2个应用的相互跳转,代码如下.

        Intent intent = new Intent();
        intent.setAction("com.qylk.call.main");
        startActivity(intent);

相当的简单,看似没有任何问题,其实是有一点问题的.我们假如是A应用跳转到B应用,当A应用跳转到B应用时,按下HOME键,然后在点击A应用,问题就出来了,我的天,出现在我们面前居然是B应用.出了鬼了,我明明点的是A应用,怎么会出现B应用.其实这个问题也非常简单,加上一个独立的栈就完事了.

        Intent intent = new Intent();
        intent.setAction("com.qylk.call.main");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

这样就完事.其实我今天讲的重点不在这.看下面代码.

Intent intent = getPackageManager().getLaunchIntentForPackage("com.tcl.navigator.b");
startActivity(intent);

用包名跳转是完全没的问题的,也不会出现上面的那种BUG.奇怪的是,我们这没有加上独立的栈,为什么也不会出现问题呢?Android手机的Launcher都是用的包名跳转的.下面就去看看,到底它把Intent怎么了.

getLaunchIntentForPackage()方法在PackageMnaager里面,我们看看它到底做了什么.

这里写图片描述

fuck!居然是抽象的,坑死人…没得办法了,继续找.
看看PackageManager的子类.

这里写图片描述

ok,找到了,赶快进去看看.

这里写图片描述

日了狗,明显不对.其实这个是工具的一个小bug,没有把它的子类全部列举出来,大写的坑…
直接告诉你们算了,免得找半天.ApplicationPackageManager也实现了PackageManager,我们进去看看这个对不对.

这里写图片描述

我去,怪不得没有列举出来,原来是隐藏起来了.再看看它怎么重写的getLaunchIntentForPackage()方法

 @Override
    public Intent getLaunchIntentForPackage(String packageName) {
        // First see if the package has an INFO activity; the existence of
        // such an activity is implied to be the desired front-door for the
        // overall package (such as if it has multiple launcher entries).
        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
        intentToResolve.addCategory(Intent.CATEGORY_INFO);
        intentToResolve.setPackage(packageName);
        List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0);

        // Otherwise, try to find a main launcher activity.
        if (ris == null || ris.size() <= 0) {
            // reuse the intent instance
            intentToResolve.removeCategory(Intent.CATEGORY_INFO);
            intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
            intentToResolve.setPackage(packageName);
            ris = queryIntentActivities(intentToResolve, 0);
        }
        if (ris == null || ris.size() <= 0) {
            return null;
        }
        Intent intent = new Intent(intentToResolve);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setClassName(ris.get(0).activityInfo.packageName,
                ris.get(0).activityInfo.name);
        return intent;
    }

看返回值,返回一个intent.

Intent intent = getPackageManager().getLaunchIntentForPackage("com.tcl.navigator.b");
startActivity(intent);

我们调用这个方法也是得到一个intent,然后用这个intent跳转.在看看它对这个intent做了什么.看倒数第4行,看到了吧

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

那就对上了,其实它内部早就跟你加上了独立的栈.

所以以后希望大家不要写类似这样的代码

Intent intent = getPackageManager().getLaunchIntentForPackage("com.tcl.navigator.b");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

当然,这样写也没得错,但是总感觉哪里不对.赶快看看自己的项目有没有这样的写的,快去改过来吧.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值