BroadcastReceiver是一个响应系统范围广播公告的Android组件。
我在将应用程序推送到 Google Play 控制台时遇到问题。 广播接收器注册不正确 面向 Android 13 或更高版本的应用必须在调用时指定导出行为
android 在发布版本中添加 DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION
使用 api 级别 33 构建我的应用程序后,android 正在合并清单中添加新权限 使用 api 级别 33 构建我的应用程序后,android 正在合并清单中添加新权限 <permission android:name="com.my.package.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" android:protectionLevel="signature"/> <uses-permission android:name="com.my.package.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/> 我有一个广播接收器,这个权限与此有什么关系吗? 我应该更改任何代码吗?有谁知道添加此内容的原因吗? <receiver android:enabled="true" android:exported="true" android:name="com.my.package.EventReceiver"> <intent-filter> <action android:name="com.my.package.event"/> </intent-filter> </receiver> ``` 来自 https://developer.android.google.cn/about/versions/13/features#runtime-receivers: 更安全地导出上下文注册的接收器 为了帮助提高运行时接收器的安全性,Android 13 引入了让您的应用能够指定是否应导出“注册的广播接收器”并使其对设备上的其他应用可见的功能。在以前版本的 Android 上,设备上的任何应用程序都可以向动态注册的接收器发送不受保护的广播,除非该接收器受到签名权限的保护。 此导出配置适用于至少执行以下一项操作的应用程序: 使用 AndroidX Core 库 1.9.0 或更高版本中的 ContextCompat 类。 目标 Android 13 或更高版本。 AndroidManifest.xml 中的此节点是用于更安全地导出上下文注册接收器的配置,ContextCompat需要使用此权限来处理广播接收器。 满足必要条件后,就可以这样使用了。更多详情请参考文档 在 Gradle 中添加依赖项。 dependencies { val core_version = "1.9.0" implementation("androidx.core:core:$core_version") } 在应用程序代码中: // Create an instance of BroadcastReceiver. val br: BroadcastReceiver = MyBroadcastReceiver() // Create an instance of IntentFilter. val filter = IntentFilter(APP_SPECIFIC_BROADCAST) // Choose whether the broadcast receiver should be exported and visible to other apps on the device. If this receiver is listening for broadcasts sent from the system or from other apps—even other apps that you own—use the RECEIVER_EXPORTED flag. If instead this receiver is listening only for broadcasts sent by your app, use the RECEIVER_NOT_EXPORTED flag. val listenToBroadcastsFromOtherApps = false val receiverFlags = if (listenToBroadcastsFromOtherApps) { ContextCompat.RECEIVER_EXPORTED } else { ContextCompat.RECEIVER_NOT_EXPORTED } // Register the receiver by calling registerReceiver(): ContextCompat.registerReceiver(context, br, filter, receiverFlags) 如果不需要使用该功能,并且想在AndroidManifest.xml中删除该节点,可以这样做: <uses-permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" tools:node="remove" /> 将上述代码写入AndroidManifest.xml,DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION将会在manifest合并时被移除 如果其他人正在寻找有关 DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION 的更多信息,这是我找到的。 它与 androidx.appcompat:appcompat 库相关,似乎是他们在使用 ContextCompat.RECEIVER_EXPORTED 时实现标志 ContextCompat.RECEIVER_NOT_EXPORTED 和 ContextCompat.registerReceiver() 标志的方式 我不确定哪个版本的库引入了这些标志,但是 1.6.1 确实有它们(1.5.1 没有)。只要您的应用程序具有这些标志的库依赖性,无论是否使用 ContextCompat.registerReceiver() ,都会添加权限。 我能做出的最大努力就是在 Android 13 下的设备上尝试捕获该异常。 @JvmStatic fun safeRegisterReceiver( context: Context, receiver: BroadcastReceiver?, filter: IntentFilter, @ContextCompat.RegisterReceiverFlags flags: Int ): Intent? { try { return ContextCompat.registerReceiver(context, receiver, filter, flags) } catch (e: RuntimeException) { if (Util.hasTiramisu13()) throw e } return null } 如这里所述,它与 androidx.core:core 1.9.0 版本相关 就我而言,升级 androidx.work 2.8.1 -> 2.9.1 依赖项 将 androidx.core:core 版本升级到 1.9.0,然后 DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION 将出现在合并的清单中。 +--- androidx.work:work-gcm:2.9.0 | +--- androidx.room:room-runtime:2.5.0 -> 2.5.2 (*) | +--- androidx.work:work-runtime:2.9.0 (*) | +--- com.google.android.gms:play-services-gcm:17.0.0 | | +--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) | | +--- androidx.core:core:1.0.0 -> 1.9.0 (*) DroidServer 项目中对 DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION 有另一个很好的解释。 https://gitlab.com/fdroid/fdroidserver/-/merge_requests/1336/diffs?commit_id=71697f9c88ec73980f63be5955f36cdc3ba7a02c context.registerReceiver() 有各种行为和标志 不同的 API 版本,androidx 的 ContextCompat 试图统一 其行为与 API 33 相匹配。 在 API 33 之前,registerReceiver() 采用签名级别的名称 是否可以动态发送意图的权限 注册的广播意图接收者。如果没有指定权限, 它已出口到世界各地。 在 API 33 中,registerReceiver() 的标志参数获得了明确的 RECEIVER_EXPORTED 和 RECEIVER_NOT_EXPORTED 控件。指某东西的用途 RECEIVER_NOT_EXPORTED 没有指定的签名级别权限 意味着应用程序打算只向自身发送意图,并且 拒绝来自其他地方的他们。 为了在旧 API 上模拟 API 33 的 RECEIVER_NOT_EXPORTED 标志, androidx 的 ContextCompat 利用了签名级别的事实 没有其他应用程序使用的权限相当于 未出口。因此,AAPT 合并到清单中: <permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" android:protectionLevel="signature" /> <uses-permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/> 然后,在旧的 API 上,传递 “${applicationId}.DYNAMIC_RECEIVER_ NOT_EXPORTED_PERMISSION”至 当 RECEIVER_NOT_EXPORTED 为时,registerReceiver() 的权限参数 指定。这项技术似乎有效。但它有一个明显的缺点 从 androidx API 33 构建的项目声明了这个额外的任意 使用权限,这在 F-Droid 中看起来有点奇怪,因为它是 基本上只是内部黑客,而不是真正的许可。
Android:从广播接收器访问 ViewModel 方法的最佳方式是什么?
我有一个带有 Refresh() 方法的视图模型,它访问数据库并更新 UI。每当飞行模式发生变化时,我都需要调用此方法。 这个怎么做? 广播接收器的实现: 班级
我广泛搜索但没有找到这个问题的答案: 是否可以通过广播接收器更改 Jetpack compose 用户界面中的变量?
我是 kotlin 新手,正在尝试制作一个课程药物提醒应用程序。 当我的 AlarmReceiver 将新名称添加到 currentAlerts 流中时,我的虚拟机不会做出反应。 唯一一次‘做’
我正在我的应用程序中广播意图并使用广播接收器接收它。我可以处理广播和接收。没问题。但是,我想完全注册接收者
从 android 12 开始,不再可能从 BroadcastReceiver 和服务启动 Activity,根据文档,这称为通知蹦床限制,现在我们
我正在尝试从 Android 中的广播接收器检测 SIM 状态的变化(在双 SIM 卡场景中 - 单 SIM 卡活动/不活动,双 SIM 卡活动/不活动)。 我用谷歌搜索找到解决方案,但它们是
GeoFencing:BroadcastReceiver 无法触发
我尝试从Android开发人员运行此应用程序:https://developer.android.com/codelabs/advanced-android-kotlin-training-geofencing?authuser=2#0 正在添加地理围栏,但什么也没有
我只是想知道是否可以在应用程序清单中注册一个检测屏幕开/关的广播接收器。 我不喜欢可编程方法的原因是它需要...
我的警报管理器有问题。我的应用程序正在发送有关膳食的通知,我有 4 顿饭(早餐、午餐、晚餐、小吃)和时间选择器。如果我设定一顿饭的时间,它就会发送
由于 Android 服务和 AlarmManager 应用程序崩溃
我正在尝试创建一个将在后台运行的服务,并每 10 秒在状态栏中放置一个通知(仅用于测试)。 我在这里查看了很多帖子,但仍然找不到帮助...
BroadcastReceiver 未在 Android 中的同一可组合项中接收 Intent
我正在使用 Jetpack Compose 对 Android API 26 进行一些实验,但在同一可组合项中发送和接收广播时遇到了问题。 这是我的接收器的代码: 班级
Android Activity 未找到异常和 BroadcastReceiver
我的程序中有一些功能我想公开,但我似乎没有让接收器工作。 我尝试了清单/接收器: 我的程序中有一些功能我想公开,但我似乎没有让接收器工作。 我尝试了清单/接收器: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.nohkumado.intstringsynchro" > <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:resizeableActivity = "true"> <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".IntStringReceiver" android:exported="true" android:enabled="true"> <intent-filter> <action android:name="com.nohkumado.intstringsynchro.EDIT_STRINGXML"/> </intent-filter> <intent-filter> <action android:name="com.nohkumado.intstringsynchro.ADD_STRINGXML"/> <action android:name="com.nohkumado.intstringsynchro.DEL_STRINGXML"/> <data android:mimeType="text/plain"/> </intent-filter> </receiver> </application> </manifest> package com.nohkumado.intstringsynchro; import android.content.*; import android.widget.*; import android.util.*; public class IntStringReceiver extends BroadcastReceiver { public static final String TAG = "Receiver"; @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "Intent Detected:"+intent.getAction(), Toast.LENGTH_LONG).show(); switch (intent.getAction()) { case "com.nohkumado.intstringsynchro.EDIT_STRINGXML": { Intent intentStartMainActivity = new Intent(context, MainActivity.class); intentStartMainActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intentStartMainActivity); break; } case("com.nohkumado.intstringsynchro.ADD_STRINGXML"): { Toast.makeText(context, "add token "+intent.getExtras(), Toast.LENGTH_LONG).show(); break; } case("com.nohkumado.intstringsynchro.DEL_STRINGXML"): { Toast.makeText(context, "del token "+intent.getExtras(), Toast.LENGTH_LONG).show(); break; } default: { Toast.makeText(context, "no idea what to do with "+intent, Toast.LENGTH_LONG).show(); Log.d(TAG,"no idea what to do with "+intent); }//default }// switch (intent.getAction()) }// public void onReceive(Context context, Intent intent) }//class 正如所指出的,我错误地在接收器部分放了一个 <category android:name="android.intent.category.DEFAULT"/> 这意味着在最好的情况下,只有第一个意图过滤器被触发,而不是其他......删除了它 现在作为另一个应用程序,我创建了一个小型测试器,它只有 3 个按钮来触发我想作为意图传递的 3 个操作,因为这只是一个小测试,所以我在布局文件中绑定了 onClick 事件: package com.nohkumado.istester; import android.app.*; import android.content.*; import android.net.*; import android.os.*; import android.view.*; import android.widget.*; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }//onCreate public void callIntString() { callIntString(null); } public void callIntString(View but) { Toast.makeText(this, "call int string", Toast.LENGTH_SHORT).show(); String name="com.nohkumado.intstringsynchro.EDIT_STRINGXML"; Intent callIt = new Intent(name); try { startActivity(callIt); } catch (ActivityNotFoundException e) { Toast.makeText(this, "no available activity"+callIt, Toast.LENGTH_SHORT).show(); //callGooglePlayStore(); } } private void callGooglePlayStore() { Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.android.vending"); ComponentName comp = new ComponentName("com.android.vending", "com.google.android.finsky.activities.LaunchUrlHandlerActivity"); // package name and activity launchIntent.setComponent(comp); launchIntent.setData(Uri.parse("market://details?id=com.nohkumado.intstringsynchro")); startActivity(launchIntent); }//callIntString } 这是我的理解问题,我应该尝试 sendBroadcast(launchIntent);而不是使用 startActivity; 好的,结束这个...... 首先,我并不完全意识到清单中的活动合约为任何人调用此活动提供了一种方式。 接下来,我有一个特定的应用程序,我想向其他人开放,这意味着编辑 Android 项目的 strings.xml 文件,并且我想提出相当于 REST API 的方案,包括 LIST/EDIT、ADD、DEL。 现在,如果我们处理活动,我认为从外部处理我的活动的最简单方法是这样的: Intent call = pm.getLaunchIntentForPackage("com.nohkumado.intstringsynchro"); 随后进行一些 putExtra 调用,以插入标识特定操作的令牌以及要执行的最终值...... 由startActivity完成 这样,默认活动就会启动,无论其名称和传递的意图如何,都可以在 MainActivity 的 onCreate 方法中读取。 为了实现我的 REST API,我尝试为我的应用程序创建 3 个入口点,每个入口点对应一种类型的访问,只有 LIST/EDIT 启动 UI,另外 2 个入口点生成一系列在后台执行工作的异步任务。但这意味着最终用户必须知道要处理哪些活动。 所以我恢复使用意图的 putExtra 和令牌/值对来实现我的类似 REST 的 API...... 为了教育目的,我尝试了广播机制的方法,优点是在客户端似乎没有崩溃的风险,不需要捕获 ActivityNotFound 异常,并且,从我的代码中的拼写错误,我注意到意图活动不需要绑定到我的实际应用程序,我可以选择任何我想要的名称。 为此,在客户端我需要: String name="com.nohkumado.intstringsynchro.EDIT_STRINGXML"; Intent callIt = new Intent(name); sendBroadcast(callIt); 但在我的应用程序方面,我需要实现一个完整的 BroadCastreceiver.... 另一方面,这个机制极其缓慢,让整个操作有一种很迟缓的感觉 如果这次我做对了,请纠正我,如果有更好的方法来实现我向其他人建议这些列表/编辑、添加和删除功能的目标,我愿意接受建议? 报告返回未发现活动异常 显然,对于操作字符串 <intent-filter>,您没有包含 com.nohkumado.intstringsynchro.EDIT_STRINGXML 的活动。你的问题清单中肯定没有这样的活动。您在问题中的清单有一个 <receiver> 元素,其中有一个奇怪的 <intent-filter>,其中包括该操作。但是,<receiver> 和 <activity> 不是同一件事。 更改代码以发送广播,或更改代码以使用该操作字符串进行活动。
Android 15 Boot Completed 接收器无法启动前台服务
我正在开发一款 Android 应用程序,该应用程序之前针对 Android 14(API 级别 34),并利用 BOOT_COMPLETED 广播接收器来启动某些前台服务。 随着 Andro 的更新...
错误注册的广播接收器(play.google 发布概述,问题不断显示)
我有点困惑为什么发布概述仍然报告此错误 当所有的 registerReceiver 都已被修改以避免违规时。由于我的版本配置为, 目标:34
使用 Firebase Auth 进行身份验证时,我想自动输入通过短信接收的代码。我能够接收短信并手动完成身份验证过程,但是当我使用 SmsRetriever 时,该应用程序
无法解析声明 android.support.v4.content.LocalBroadcastManager 上的 import LocalBroadcastManager;
我在将 Eclipse 项目导入 Android Studio 时遇到此错误。它显示了一条建议将库 Gradle: com.android.support:support-core-utils-27.1.1 添加到类路径。我已经添加了图书馆...
我正在编写一个非常简单的测试Android应用程序,它可以发现蓝牙设备并将其显示在屏幕上。该应用程序在 Android 9 上正常运行,但不适用于...
在应用程序关闭时,通过通知中的操作从 RoomDB 中删除对象
所以我正在创建一个任务应用程序,用户可以在其中添加和删除任务,我提供了此选项以在 4 小时后通过通知提醒任务。该通知有一个“完成”操作,