Android应用安装原理--Android是如何认定应用为未知来源

启动应用安装的第一步是启动PackageInstallerActivity,在PackageInstallerActivity会进行应用来源认证:

    private boolean isInstallRequestFromUnknownSource(Intent intent) {
        String callerPackage = getCallingPackage();
        if (callerPackage != null && intent.getBooleanExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, false)) {
            try {
                mSourceInfo = mPm.getApplicationInfo(callerPackage, 0);
                if (mSourceInfo != null) {
                    if ((mSourceInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
                        // Privileged apps are not considered an unknown source.
                        return false;
                    }
                }
            } catch (NameNotFoundException e) {
            }
        }


        return true;
    }
下面来分条梳理认证的条件:

  1. callerPackage = getCallingPackage();
    callerPackage != null
     

    public String getCallingPackage ()

    Added in API level 1

    Returnthe name of the package that invoked this activity. This is who the data in setResult() will be sent to. You can use this information to validate that the recipient is allowed to receive the data.

    Note:if the calling activity is not expecting a result (that is it did not use the startActivityForResult(Intent, int) form that includes a request code),then the callingpackage will be null.

    Note:prior to JELLY_BEAN_MR2, the result from this method was unstable. If the process hosting the calling package was no longer running, it would return null instead of the proper package name. You can use getCallingActivity() and retrieve the package namefrom that instead.

    Returns

    ·         The package of  the activity that will receive your reply, or null if none.

    从API文档介绍里可以知道:需要在拉起PackageInstallerActivity 的时候使用startActivityForResult(Intent, int) 才能在PackageInstallerActivity中通过 getCallingPackage () 获取到 packageName,否则为null,即认定应用来源为未知。                                                                                                                                               根据我的经验,拉起PackageInstallerActivity的Intent若是设置了下面的FLAG,也会导致getCallingPackage () 获取到 packageName为null(参考:startActivityForResult中的说明):
    Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    具体原因需要分析getCallingPackage(),这个坑以后再填吧   //TO DO 分析getCallingPackage()
  2.    
    intent.getBooleanExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, false) == true

这个只需在拉起PackageInstallerActivity的Intent附上Intent.EXTRA_NOT_UNKNOWN_SOURCE ,值为true 就行

3. mSourceInfo 只要callerPackage 不为null,就不会为null;

4. mSourceInfo.flags & ApplicationInfo.FLAG_PRIVILEGED

ApplicationInfo.FLAG_PRIVILEGED 表示该应用是 Privileged App, 即启动PackageInstallerActivity的应用是安装在system/priv-app/ 下的

下面是一个例子:整个测试程序只有下面一个java文件,

public class MainActivity extends Activity {

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

        Intent i = new Intent(Intent.ACTION_INSTALL_PACKAGE);
        String filePath = "/storage/emulated/0/test.apk";
        Uri uri = Uri.parse("file://" + filePath);
        i.setData(uri);
        i.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
        i.putExtra(Intent.EXTRA_RETURN_RESULT, true);
        i.setClassName("com.android.packageinstaller",
                "com.android.packageinstaller.PackageInstallerActivity");
        startActivityForResult(i, 10);

    }
}
将应用编译出来后,把apk文件push到手机/system/app/下面(需要root权限),然后在/storage/emulated/0/下放一个用于安装的软件test.apk,就可以测试了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值