文章摘要
本文详细介绍了Android应用配置中的权限声明与Activity注册要点,包括权限声明位置、动态权限申请、Manifest合并规则及Activity的进程配置。特别针对Unity集成和支付模块,提供了回调Activity的配置示例。文章强调了敏感权限的安全处理、兼容性注意事项,并给出了常见问题排查方法,如Manifest合并冲突和支付回调无响应等。适用于Android原生及Unity混合开发场景,兼顾功能实现与安全规范。
一、权限声明与配置
1. 权限声明位置
-
所有
<uses-permission>
必须直接写在<manifest>
根节点下,不能嵌套在<application>
内。 -
示例(常见支付/网络相关权限):
<manifest ...> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 支付宝/微信可能还需 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/> ... <application ...> ... </application> </manifest>
2. 权限合并与冲突
- Unity打包时,
Assets/Plugins/Android/AndroidManifest.xml
会与主工程Manifest合并。 - 若多个库声明同一权限,最终Manifest只保留一份。
- 若权限属性冲突(如
maxSdkVersion
),以主工程或优先级高的库为准。
3. 动态权限申请
-
Android 6.0+(API 23+)部分权限(如存储、相机、定位)需运行时申请。
-
示例代码:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1001); }
4. 权限扫描与优化
- 检查最终合并Manifest:
build/intermediates/merged_manifests/<variant>/AndroidManifest.xml
- 使用
android:maxSdkVersion
限制权限生效范围,避免高版本冗余警告。
二、Activity 配置要点
1. Activity 注册与启动
-
每个Activity都需在Manifest中注册,否则启动时报
ActivityNotFoundException
。 -
示例:
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
-
android:exported
:true
:允许外部应用通过Intent启动(如支付回调、分享等)。false
:仅限本应用内部调用,敏感Activity建议设为false
。
2. 进程与多模块协作
android:process=":remote"
可让Activity运行在独立进程,常用于插件化、WebView隔离等。- 插件化场景下,声明proxyActivity作为占位,动态加载插件Activity。
3. Unity集成相关
-
Unity主入口Activity需继承自
UnityPlayerActivity
,如需扩展原生功能可自定义Activity:<activity android:name="com.yourcompany.CustomUnityActivity" android:launchMode="singleTask" android:configChanges="orientation|screenSize|keyboardHidden" android:screenOrientation="landscape" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
-
支付宝/微信等SDK要求的回调Activity(如
WXPayEntryActivity
)必须exported="true"
,且包名、类名与SDK文档一致。<activity android:name="com.yourcompany.wxapi.WXPayEntryActivity" android:exported="true" android:launchMode="singleTop" android:taskAffinity="${applicationId}.wxapi" />
三、注意事项
1. 敏感权限处理
- 仅在确实需要时声明敏感权限,避免被应用市场拒审。
- 运行时动态申请,处理用户拒绝(如弹窗解释用途、引导到设置页)。
2. 兼容性问题
- 某些属性(如
android:foregroundServiceType
)仅高API支持,低版本需加tools:targetApi="xx"
避免崩溃。 - 使用
tools:ignore
可临时忽略Lint警告,但不建议长期依赖。
3. 安全风险
- 不要随意将
android:exported
设为true
,防止被第三方应用利用。 - 支付、登录等敏感Activity建议
exported="false"
,仅回调Activity(如微信支付)需开放。
四、实际案例参考
1. 插件化架构
- 声明多个proxyActivity,动态加载插件APK的Activity,实现热更新、功能解耦。
2. Unity混合开发
-
自定义Activity继承
UnityPlayerActivity
,在onCreate
、onNewIntent
等生命周期方法中处理原生与Unity的交互。 -
示例:
public class CustomUnityActivity extends UnityPlayerActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 初始化原生SDK } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); // 处理支付/分享回调 } }
五、常见问题排查
- Manifest合并冲突:检查
merged_manifests
目录下最终Manifest,确认权限、Activity未被覆盖或遗漏。 - ActivityNotFoundException:确认Activity已注册,包名、类名拼写无误。
- 权限未生效:确认权限声明在正确位置,未被合并覆盖,且运行时已动态申请。
- 支付/分享回调无响应:确认回调Activity已
exported="true"
,包名路径与SDK要求一致,onNewIntent
已正确实现。