原来 release 能联网是靠 com.squareup.okhttp3:okhttp-android:5.5.0 的清单把 INTERNET 合并进来的; 换掉/排除那个依赖,release 会静默失去网络权限(debug 侧 AGP 也注入同一份,所以本地怎么试都看不出来)。 现在显式写进源码。验收::app:processReleaseMainManifest 的 merger 报告里该权限已是 ADDED from app/src/main/AndroidManifest.xml(并 MERGED from okhttp-android)⇒ 来源是源码。
110 lines
5.7 KiB
XML
110 lines
5.7 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||
|
||
<!--
|
||
「后台保持连接」用到的三个权限(设置页那个开关,默认关):
|
||
|
||
- FOREGROUND_SERVICE:起前台服务本身。
|
||
- FOREGROUND_SERVICE_DATA_SYNC:前台服务的类型权限(API 34+ 与 android:foregroundServiceType
|
||
配合)。选 dataSync 是因为这条服务保的是一条**长连接**——保持与后端的实时同步,
|
||
既不是 mediaPlayback 也不是 location,声明成别的类型才是说谎。
|
||
- POST_NOTIFICATIONS:前台服务必须有一条通知,而 minSdk 33 ⇒ 它恒是运行时权限。
|
||
用户拒绝时开关**打不开**(判据见 core.keepalive.shouldKeepAliveRun),本端不偷偷跑。
|
||
-->
|
||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||
|
||
<!--
|
||
联网权限**显式**声明,不靠任何传递依赖。
|
||
|
||
事实(W52K 跑 `:app:processReleaseMainManifest` 核过):本端一直能联网,是靠
|
||
`com.squareup.okhttp3:okhttp-android:5.5.0` 的清单把 `INTERNET` 合并进来的;而 debug 那边
|
||
AGP 也注入同一份 ⇒ **本地怎么试都看不出来**。一旦换掉/排除那个依赖,release 会**静默失去**
|
||
网络权限(不报错、只是所有请求都失败)。显式写在这里,从此与第三方清单无关。
|
||
-->
|
||
<uses-permission android:name="android.permission.INTERNET" />
|
||
|
||
<application
|
||
android:name=".app.CyreneApplication"
|
||
android:allowBackup="false"
|
||
android:icon="@mipmap/ic_launcher"
|
||
android:label="@string/app_name"
|
||
android:networkSecurityConfig="@xml/network_security_config"
|
||
android:roundIcon="@mipmap/ic_launcher_round"
|
||
android:supportsRtl="true"
|
||
android:theme="@style/Theme.Cyrene">
|
||
|
||
<!--
|
||
launchMode="singleTop":App 已经开着时从别的 App 分享过来,系统不再新建一个实例,
|
||
改成回调 onNewIntent(见 MainActivity)。不写它就会起第二个 Activity 实例、
|
||
两个实例各持一套 ViewModel / socket。
|
||
-->
|
||
<activity
|
||
android:name=".app.MainActivity"
|
||
android:exported="true"
|
||
android:label="@string/app_name"
|
||
android:launchMode="singleTop"
|
||
android:windowSoftInputMode="adjustResize">
|
||
<intent-filter>
|
||
<action android:name="android.intent.action.MAIN" />
|
||
<category android:name="android.intent.category.LAUNCHER" />
|
||
</intent-filter>
|
||
|
||
<!--
|
||
分享入口:只声明本端真能落地的两类 MIME(纯文本 / 图片)。
|
||
刻意不声明 */*——对话路径上今天没有「文件」这个表示(协同文档 02/F1 的三缺),
|
||
声明了就等于给出一个点进去必然失败的入口。标签沿用应用名(活动不设自己的
|
||
label / icon 时,分享菜单取的就是 Cyrene 的名字与启动图标)。
|
||
-->
|
||
<intent-filter>
|
||
<action android:name="android.intent.action.SEND" />
|
||
<category android:name="android.intent.category.DEFAULT" />
|
||
<data android:mimeType="text/plain" />
|
||
<data android:mimeType="image/*" />
|
||
</intent-filter>
|
||
|
||
<!-- 多图分享只收图片:多条纯文本的 EXTRA_TEXT(SEND_MULTIPLE + text/plain)本端不接。 -->
|
||
<intent-filter>
|
||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||
<category android:name="android.intent.category.DEFAULT" />
|
||
<data android:mimeType="image/*" />
|
||
</intent-filter>
|
||
</activity>
|
||
|
||
<!--
|
||
附件预览的「用其它应用打开 / 保存」出口:`cacheDir/documents/` 下的文件要交给
|
||
系统里别的 App 读,就必须是 content:// 而不是 file://——API 24 起把 file:// 交出去
|
||
会直接抛 FileUriExposedException(且 StrictMode 下同样致命)。
|
||
路径范围见 res/xml/file_paths.xml:只暴露 cacheDir/documents/ 这一层,
|
||
exported="false" + 按次授权(grantUriPermissions)保证这份缓存不对外常开。
|
||
-->
|
||
<provider
|
||
android:name="androidx.core.content.FileProvider"
|
||
android:authorities="${applicationId}.fileprovider"
|
||
android:exported="false"
|
||
android:grantUriPermissions="true">
|
||
<meta-data
|
||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||
android:resource="@xml/file_paths" />
|
||
</provider>
|
||
|
||
<!--
|
||
「后台保持连接」的前台服务(设置页开关控制,默认关)。
|
||
|
||
exported="false":它没有任何对外接口(onBind 返回 null),只由本进程 start/stop。
|
||
|
||
foregroundServiceType="dataSync":这条服务的职责是让进程活着,从而让那条**进程级共享**
|
||
的实时连接(AppContainer.chatSocket)不被 Android 12+ 的 cached 进程冻结掐断——
|
||
语义上就是「后台数据同步」。它不自己去建立 / 关闭任何连接,连接的主人是
|
||
SessionsViewModel(见 KeepAliveService 的类注释)。
|
||
-->
|
||
<service
|
||
android:name=".core.keepalive.KeepAliveService"
|
||
android:exported="false"
|
||
android:foregroundServiceType="dataSync" />
|
||
|
||
</application>
|
||
|
||
</manifest>
|