首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法启动任意活动,因为Android 13

无法启动任意活动,因为Android 13
EN

Stack Overflow用户
提问于 2022-08-26 02:49:25
回答 2查看 1.1K关注 0票数 3

我有一个小小的个人应用程序,我可以为不同的URL指定不同的浏览器。直到Android 13之前,它运行良好,但在Android 13之后的某一时刻,它开始失败。我怀疑这与该应用程序发起任意活动的权限(或缺乏)有关,但在文档中涉水已经产生了zilch。

这个过程是这样的:

我查询以URI作为其数据属性的Intent的所有活动。

代码语言:javascript
复制
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri); // uri is some location like 'https://www.google.com'
PackageManager pm = context.getPackageManager();
List<ResolveInfo> allTargets = pm.queryIntentActivities(intent, PackageManager.MATCH_ALL);

我循环遍历allTargets,根据它的名称查找我想要的浏览器:

代码语言:javascript
复制
ResolveInfo target = null;
for (ResolveInfo b : allTargets) {
    String appName = b.loadLabel(pm).toString();

    // targetBrowserName will be something like "Chrome"
    if(appName.equalsIgnoreCase(targetBrowserName)) {
        target = b;
        break;
    }
}

然后,我尝试用url启动这个浏览器。

代码语言:javascript
复制
ActivityInfo activity = target.activityInfo;

ComponentName name = new ComponentName(activity.applicationInfo.packageName, activity.name);
targetIntent = new Intent(Intent.ACTION_MAIN);
targetIntent.addCategory(Intent.CATEGORY_LAUNCHER);
targetIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
targetIntent.setComponent(name);
targetIntent.setData(uri);
startActivity(targetIntent);

这现在失败了,错误如下:

代码语言:javascript
复制
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.android.chrome/com.google.android.apps.chrome.IntentDispatcher}; have you declared this activity in your AndroidManifest.xml, or does your intent not match its declared <intent-filter>?
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4803)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4836)
        at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:54)
        at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2308)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7898)
        at java.lang.reflect.Method.invoke(Native Method)

我尝试过各种启动代码的排列(提醒您,这些代码运行得很好)。例如。

代码语言:javascript
复制
targetIntent = pm.getLaunchIntentForPackage(activity.applicationInfo.packageName);
targetIntent.setAction(Intent.ACTION_VIEW);
targetIntent.addCategory(Intent.CATEGORY_BROWSABLE);
targetIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

但是,我仍然得到相同的错误(尽管在上面的例子中,有一个不同的活动类仍然无法找到)

我理解应用程序可见性有一些限制,但我认为我在AndroidManifest.xml中包含了这些限制。

代码语言:javascript
复制
    <!-- As per guidelines, QUERY_ALL_PACKAGES is required to list all browsers -->
    <uses-permission
        android:name="android.permission.QUERY_ALL_PACKAGES"
        tools:ignore="QueryAllPackagesPermission" />

在阅读文档时,我注意到清单中没有<queries>元素(这是新的吗?),所以我添加了以下内容:

代码语言:javascript
复制
    <queries>
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" />
        </intent>
    </queries>

不是joy。

有人知道以编程方式启动已知/特定浏览器应用程序的正确方法吗?或者是在Android 13中做了什么改变才能使代码再次工作呢?

谢谢!

编辑下面的正确答案

下文答复中提供的指导意见行之有效。这是最后代码的摘要版本:

代码语言:javascript
复制
// Create an intent with the destination URL
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);

// List all activities that support this intent, and choose one:
PackageManager pm = context.getPackageManager();
List<ResolveInfo> allTargets = pm.queryIntentActivities(intent, PackageManager.MATCH_ALL);
ResolveInfo target = null;
for (ResolveInfo b : allTargets) {
    String appName = b.loadLabel(pm).toString();

    // targetBrowserName is something like "Chrome"
    if(appName.equalsIgnoreCase(targetBrowserName)) {
        target = b;
        break;
    }
}

// Set the specific component to be launched
ActivityInfo activity = target.activityInfo;
ComponentName name = new ComponentName(activity.applicationInfo.packageName, activity.name);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
intent.setComponent(name);

// Start
startActivity(intent);
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-26 16:33:32

似乎与这种行为改变有关,https://developer.android.com/about/versions/13/behavior-changes-13#intent-filters

当您的应用程序向另一个应用程序的导出组件发送意图,而该应用程序的目标是Android13或更高版本时,只有当它与接收应用程序中的某个元素匹配时,才能传递该意图。不匹配的意图被阻塞。

要确保这确实是您的问题,请检查标记PackageManager的logcat。像W/PackageManager( 1828): Access blocked: ComponentInfo{com.android.chrome/com.google.android.apps.chrome.Main}这样的东西应该出现在那里

我还没有仔细研究它是如何工作的,但现在我们似乎需要在使用外部活动之前查询它们,除非它们没有意图过滤器。这将“激活”组件,然后您使用的意图需要“匹配”其他应用程序意图过滤器:

意图与意图过滤器相匹配,不仅可以发现要激活的目标组件,而且还可以发现设备上的组件集。例如,Home应用程序通过使用意图筛选器查找指定ACTION_MAIN操作和CATEGORY_LAUNCHER类别的所有活动来填充应用程序启动程序。只有当意图中的操作和类别与筛选器匹配时,匹配才会成功,正如IntentFilter类的文档所描述的那样。

https://developer.android.com/guide/components/intents-filters#imatch

我也有类似的问题。它不能工作的原因是,在调用intent.setData之后,我通过调用queryIntentActivities修改了Uri。这似乎使组件的激活无效。

摘要:在intent.setData使意图生效后,不调用queryIntentActivities

票数 1
EN

Stack Overflow用户

发布于 2022-09-15 10:27:37

有个错误

代码语言:javascript
复制
Unable to find explicit activity class {com.google.android.apps.translate/com.google.android.apps.translate.TranslateActivity}; have you declared this activity in your AndroidManifest.xml, or does your intent not match its declared <intent-filter>?

在我的例子中,帮助删除了用于Android 13的intent.addCategory(Intent.CATEGORY_LAUNCHER)

代码语言:javascript
复制
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_PROCESS_TEXT);
intent.setType("text/plain");


//Fix for Android 13
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
}

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
intent.setComponent(name);

intent.putExtra(Intent.EXTRA_TEXT, selecteText);
intent.putExtra(Intent.EXTRA_PROCESS_TEXT, selecteText);
intent.putExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, selecteText);

a.startActivity(intent);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73495596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档