Android开发-Activity中“android:exported“属性的作用,以及“Permission Denial: starting Intent“错误解决

这篇具有很好参考价值的文章主要介绍了Android开发-Activity中“android:exported“属性的作用,以及“Permission Denial: starting Intent“错误解决。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

如何在一个应用程序中,启动另外一个应用程序?最近正有这样的需求,也踩了一个小坑。本节介绍使用Activity中"android:exported"属性来实现这种访问。

Activity中"android:exported"属性说明:

在程序清单AndroidMenifest.xml文件中,可以设置这个属性。

Android中的Activity中"android:exported"属性设置为true,意味着允许让外部组件启动这个Activity;反之,则不允许让外部组件启动这个Activity;

如果设置了false,又在外部试图启动这个Activity,则会发生程序崩溃,报异常,例如:

java.lang.SecurityException: Permission Denial: starting Intent

入坑指南:

我要实现的功能是在App1中启动App2。在App1中,使用startActivity启动App2的activity,从而实现需求。只要将exported 设置为false,就入坑了。主要代码如下:

在app1中,

            //start other app
            Intent intent = mContext.getPackageManager().getLaunchIntentForPackage("com.test.app2");
            if (intent != null) {
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                mContext.startActivity(intent);
            }

 这就会启动App2中的入口Activity。

在App2中,AndroidManifest.xml文件,

<application android:icon="@drawable/icon"
        android:allowBackup="false"
        android:name=".MyApp2"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Light">
        <activity android:name="com.test.app2.activity.MainActivity"
            
            android:exported="true" //如果为false,就会发生异常
            android:finishOnTaskLaunch="false"
            android:launchMode="singleInstance"

            >

        </activity>
...
/>

 如果为exported 设置为false,就会发生异常,恭喜你,成功入坑。报错信息如下:

03-09 19:53:10.077 20340-20340/com.test.app1 D/AndroidRuntime: Shutting down VM
    
    --------- beginning of crash
03-09 19:53:10.078 20340-20340/com.test.app1 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.test.app1, PID: 20340
    java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 pkg=com.test.app2 cmp=com.test.app2/com.test.app2.activity.MainActivity } from ProcessRecord{3d6aa2d 20340:com.test.app1/u0a83} (pid=20340, uid=10083) not exported from uid 10117
        at android.os.Parcel.readException(Parcel.java:1620)
        at android.os.Parcel.readException(Parcel.java:1573)
        at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2658)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1507)
        at android.app.Activity.startActivityForResult(Activity.java:3930)
        at android.app.Activity.startActivityForResult(Activity.java:3890)
        at android.app.Activity.startActivity(Activity.java:4213)
        at android.app.Activity.startActivity(Activity.java:4181)
        at com.test.app1.ui.DemoMainActivity.onClick(DemoMainActivity.java:70)
        at android.view.View.performClick(View.java:5204)
        at android.view.View$PerformClick.run(View.java:21153)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

 当然,根据提示,也可以看出来,是“not exported”,所以,填坑也很容易:

android:exported="true"

源码阅读:

追根溯源,我们来看一下源码。搜索“not exported from uid” ,可以看到,有好几处都能搜到,而且代码文件看名字就能知道,是Android四大组件相关代码,如图:

Android开发-Activity中“android:exported“属性的作用,以及“Permission Denial: starting Intent“错误解决

 结合我们的错误信息提示,定位到错误提示的代码在ActivityStack.java的

startActivityLocked方法中:
    final int startAnyPerm = mService.checkPermission(
                START_ANY_ACTIVITY, callingPid, callingUid);
    final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
                callingUid, aInfo.applicationInfo.uid, aInfo.exported);
    if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {

        String msg;
            if (!aInfo.exported) {
                msg = "Permission Denial: starting " + intent.toString()
                        + " from " + callerApp + " (pid=" + callingPid
                        + ", uid=" + callingUid + ")"
                        + " not exported from uid " + aInfo.applicationInfo.uid;
            } else {
                msg = "Permission Denial: starting " + intent.toString()
                        + " from " + callerApp + " (pid=" + callingPid
                        + ", uid=" + callingUid + ")"
                        + " requires " + aInfo.permission;
            }
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }

哦,原来是在startActivityLocked中抛出的异常。还记得activity的启动流程么,一系列的startActivity相关函数的调用。

通过调用mService.checkPermission 和 mService.checkComponentPermission 进行获取权限。再根据返回值来判断是否有权限,如果没有权限,就会

throw new SecurityException(msg);

这个msg,就是上面我们提到的错误信息。

那么,mService是谁呢?答案就是大名鼎鼎的AMS(ActivityManagerService)的实例。

在check权限的时候,会进行进程id,用户id,是否是同一个应用,是否是系统用户以及exported是否为true......等等条件的判断。

我们直接来看到底是谁去check了exported的。答案是:ActivityManager。调用链:

ActivityStack.startActivityLocked  -->
    ActivityManagerService.checkComponentPermission -->
        ActivityManager.checkComponentPermission    -->

ActivityManager.checkComponentPermission的代码:

/** @hide */
    public static int checkComponentPermission(String permission, int uid,
            int owningUid, boolean exported) {
        // Root, system server get to do everything.
        if (uid == 0 || uid == Process.SYSTEM_UID) {
            return PackageManager.PERMISSION_GRANTED;
        }
        // Isolated processes don't get any permissions.
        if (UserId.isIsolated(uid)) {
            return PackageManager.PERMISSION_DENIED;
        }
        // If there is a uid that owns whatever is being accessed, it has
        // blanket access to it regardless of the permissions it requires.
        if (owningUid >= 0 && UserId.isSameApp(uid, owningUid)) {
            return PackageManager.PERMISSION_GRANTED;
        }
        // If the target is not exported, then nobody else can get to it.
        if (!exported) {
            Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
            return PackageManager.PERMISSION_DENIED;
        }
        if (permission == null) {
            return PackageManager.PERMISSION_GRANTED;
        }
        try {
            return AppGlobals.getPackageManager()
                    .checkUidPermission(permission, uid);
        } catch (RemoteException e) {
            // Should never happen, but if it does... deny!
            Slog.e(TAG, "PackageManager is dead?!?", e);
        }
        return PackageManager.PERMISSION_DENIED;
    }

 可以看到,

// If the target is not exported, then nobody else can get to it.
        if (!exported) {
            Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
            return PackageManager.PERMISSION_DENIED;
        }

在这里进行了exported的判断,如果exported为false,就会

return PackageManager.PERMISSION_DENIED;

终于,知道了这个异常是怎么被throw出来的了。文章来源地址https://www.toymoban.com/news/detail-459698.html


android:exported="true" 和 android:exported="false",弄明白了么?

到了这里,关于Android开发-Activity中“android:exported“属性的作用,以及“Permission Denial: starting Intent“错误解决的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java】后端开发语言Java和C#,两者对比注解和属性的区别以及作用

    欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《Java》序列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握。 温馨提示:博主能力有限,理解水平有限

    2024年01月16日
    浏览(46)
  • Android应用开发(4)视图布局基本属性

    Android应用开发学习笔记——目录索引 本章介绍视图(View)的基本概念及其用法,包括:如何设置视图的宽度和高度,如何设置视图的外部间距和内部间距,如何设置视图的外部对齐方式和内部对齐方式等。 在Android中,什么是视图(View)?View是Android中所有控件的基类,不

    2024年02月03日
    浏览(36)
  • Android Studio开发遇到爆红`@layout/activity_main` does not contain a declaration with id `xxx`

    翻译是“@layout/activity_main“不包含 ID 为”xxx“的声明”,但是我们用ctri + 鼠标左键可以跳转到所属位置,但是运行时会无法进入,或者爆红 用人话说你在MainActivity中调用的activiy_main.xml没有这个aid组件 这时候我们就要用到View提供的inflate的方法 这是我的一个item 案例 tv_del =

    2024年02月02日
    浏览(27)
  • Android NDK开发详解之编写C/C++代码中的Android SDK 版本属性)

    本部分将讨论如何使用 NDK 提供的库。 注意:有关导入预构建库(未包含在 NDK 中的库)的指南已移至各个构建系统的相关部分。请根据您的项目需求参阅 CMake 或 ndk-build 指南。 文中说明了 NDK 提供的 C ++ 运行时,并介绍了 NDK 提供的其他库(例如 OpenGL ES 和 OpenSL ES)以及支持

    2024年02月07日
    浏览(46)
  • Android Activity的启动流程(Android-10)

    在Android开发中,我们经常会用到startActivity(Intent)方法,但是你知道startActivity(Intent)后Activity的启动流程吗?今天就专门讲一下最基础的startActivity(Intent)看一下Activity的启动流程,同时由于Launcher的启动后续和这里基本类似,就记录在一起。注意本章都是基于Android-10来讲解的。

    2024年01月17日
    浏览(40)
  • Android---Android 是如何通过 Activity 进行交互的

    相信对于 Android 工程师来说,startActivity 就像初恋一般。要求低,见效快,是每一个菜鸟 Android 工程师迈向高级 Android 工程师的必经阶段。经过这么多年的发展,startActivity 在 google 的调教下已经变得愈发成熟,对工程师的要求也越来越高。、 通过设置不同的 启动模式 可以实

    2024年02月07日
    浏览(35)
  • Activity之间数据回传【Android、activity回传、结合实例】

    在Android应用中,有时需要从一个Activity向另一个Activity传递数据,并在第二个Activity处理后将结果传递回第一个Activity。 这种情况下,我们可以使用 startActivityForResult() 和 onActivityResult() 方法来实现数据回传。 创建新的Android项目: 打开Android Studio并创建一个新的Android项目,确

    2024年02月08日
    浏览(37)
  • Android --- Activity

    官方文档-activity Activity 提供窗口,供应在其中多个界面。此窗口通常会填满屏幕,但也可能小于屏幕并浮动在其他窗口之上。 大多数应用包含多个屏幕,这意味着它们包含多个 Activity。通常,应用中的一个 Activity 会被指定主 Activity,即用户启动应用时显示的第一个屏幕。然

    2024年04月23日
    浏览(62)
  • [Android 四大组件] --- Activity

    ​​Activity​​是一个Android的应用组件,它提供屏幕进行交互。每个Activity都会获得一个用于绘制其用户界面的窗口,窗口可以充满哦屏幕也可以小于屏幕并浮动在其他窗口之上。 一个应用通常是由多个彼此松散联系的Activity组成,一般会指定应用中的某个Activity为主活动,也

    2024年02月10日
    浏览(37)
  • Android复习(Android基础-四大组件)——Service与Activity通信

    我们前面学会了启动和停止服务的方法,但是服务虽然是在活动里启动的,但是启动服务之后,活动与服务之间基本没什么关系了。 正常情况,我们在Activity里调用startService()方法启动MyService这个服务,然后MyService的onCreate()和onStartCommand()方法就会得到执行。之后服务会一直处

    2024年02月13日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包