NativeScript项目Android 12兼容性报错:已加android:exported仍无效
NativeScript项目Android 12兼容性上传报错解决
问题
开发NativeScript项目时,本地开发运行正常,但生成.aab文件上传Google Play时触发Android 12兼容性报错:
您上传的APK或Android App Bundle中存在带intent-filter但未设置‘android:exported’属性的activity、activity alias、service或broadcast receiver,无法在Android 12及以上版本安装。
已手动给所有带intent-filter的activity、service、receiver添加android:exported属性,问题依旧。
解决步骤
1. 检查最终合并的AndroidManifest
NativeScript编译时会合并项目自身和第三方插件的AndroidManifest配置,你手动添加的配置可能被插件覆盖,或者插件自带的组件未设置android:exported。
- 执行
ns build android --release --bundle完成编译 - 找到
platforms/android/app/src/main/AndroidManifest.xml文件,搜索所有带<intent-filter>的组件,检查是否有遗漏android:exported的项 - 如果发现插件引入的组件未设置该属性:
- 优先升级对应插件到支持Android 12的版本
- 也可以在项目的AndroidManifest.xml中用
tools:replace或tools:node="merge"手动覆盖插件配置,补上android:exported
2. 升级NativeScript Android运行时
当前项目使用的@nativescript/android版本为8.1.1,该版本对Android 12的android:exported适配不完善,建议升级到8.2.0及以上版本,新版本已处理Manifest合并的兼容性问题。
升级命令:
npm install @nativescript/android@latest --save-dev
3. 验证Firebase插件适配
项目中@nativescript/firebase版本为11.1.3,确认该版本是否支持Android 12。如果合并后的Manifest里Firebase相关组件仍有问题,要么升级到最新版,要么在项目Manifest里明确给这些组件加上android:exported。
项目配置
package.json
{ "version": "2.10.1", "description": "NativeScript Application", "license": "SEE LICENSE IN <your-license-filename>", "repository": "<fill-your-repository-here>", "scripts": { "lint": "tslint \"src/**/*.ts\"", "code-clean": "prettier --write \"src\"", "ngcc": "ngcc", "postinstall": "patch-package" }, "dependencies": { "@angular/animations": "~12.2.5", "@angular/common": "~12.2.5", "@angular/compiler": "~12.2.5", "@angular/core": "~12.2.5", "@angular/forms": "~12.2.5", "@angular/platform-browser": "~12.2.5", "@angular/platform-browser-dynamic": "~12.2.5", "@angular/router": "~12.2.5", "@mapo80/nativescript-ngx-shadow": "file:packages/mapo80-nativescript-ngx-shadow-7.0.1.tgz", "@nativescript-community/ui-image": "4.0.20", "@nativescript-community/ui-material-bottom-navigation": "^7.0.25", "@nativescript-community/ui-material-bottomsheet": "^7.0.28", "@nativescript-community/ui-pager": "13.0.31", "@nativescript/angular": "^12.2.0", "@nativescript/appversion": "~2.0.0", "@nativescript/camera": "^5.0.13", "@nativescript/core": "~8.1.1", "@nativescript/fingerprint-auth": "^8.1.0", "@nativescript/firebase": "^11.1.3", "@nativescript/geolocation": "8.0.2", "@nativescript/imagepicker": "~1.0.0", "@nativescript/iqkeyboardmanager": "~2.0.0", "@nativescript/social-share": "^2.0.4", "@nativescript/theme": "^3.0.2", "@ngrx/effects": "^9.2.0", "@ngrx/entity": "^12.2.0", "@ngrx/store": "^9.2.0", "@nstudio/nativescript-exoplayer": "~5.0.0", "@nstudio/nativescript-pulltorefresh": "^3.0.2", "@sergeymell/nativescript-svg": "^1.1.2", "@sonnytrujillojr/tokenizerjs": "^1.0.1", "ALAssetsLibrary-CustomPhotoAlbum": "file:packages/ALAssetsLibrary-CustomPhotoAlbum", "deep-diff": "^1.0.2", "immer": "^7.0.9", "lodash": "^4.17.20", "moment-timezone": "^0.5.31", "nativescript-drop-down": "^6.0.2", "nativescript-google-maps-sdk": "^3.0.2", "nativescript-gradient": "^2.0.1", "nativescript-image-swipe": "^5.0.1", "nativescript-masked-text-field": "file:packages/nativescript-masked-text-field-4.0.3.tgz", "nativescript-mediafilepicker": "4.0.2", "nativescript-push-notifications": "^1.1.6", "nativescript-status-bar": "file:nativescript-status-bar", "nativescript-ui-listview": "^9.1.0", "ngrx-store-logger": "^0.2.4", "normalizr": "^3.6.1", "reflect-metadata": "^0.1.13", "rxjs": "^7.4.0", "zone.js": "^0.11.4" }, "devDependencies": { "@angular-devkit/build-angular": "^12.2.18", "@angular/compiler-cli": "^12.2.5", "@nativescript/android": "8.1.1", "@nativescript/ios": "8.1.0", "@nativescript/types": "~8.1.0", "@nativescript/webpack": "^5.0.8", "@ngtools/webpack": "^12.2.5", "@types/lodash": "^4.14.161", "babel-traverse": "6.26.0", "babel-types": "6.26.0", "babylon": "6.18.0", "codelyzer": "~4.0.2", "commitizen": "^4.2.3", "cz-conventional-changelog": "^3.3.0", "patch-package": "^6.4.7", "prettier": "2.0.5", "prettier-tslint": "^0.4.2", "tslint": "~5.8.0", "typescript": "~4.3.5" }, "readme": "NativeScript Application", "config": { "commitizen": { "path": "./node_modules/cz-conventional-changelog" } }, "main": "./src/main.ts" }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="__PACKAGE__" android:versionCode="1" android:versionName="1.0.0"> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.location.gps" android:required="false" /> <application android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/AppTheme" android:requestLegacyExternalStorage="true" android:exported="true"> <activity android:name="net.demo.Activity" android:label="@string/title_activity_kimera" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode" android:theme="@style/LaunchScreenTheme" android:screenOrientation="portrait" android:windowSoftInputMode="stateHidden | adjustPan" android:exported="true"> <meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="http" android:host="link.demo.com" /> <data android:scheme="https" android:host="link.demo.com" /> <data android:scheme="net.demo" android:host="demo.com" /> </intent-filter> </activity> <activity android:name="com.tns.ErrorReportActivity" android:exported="true"/> <service android:name="org.nativescript.plugins.firebase.MyFirebaseInstanceIDService" android:exported="true"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> </intent-filter> </service> <service android:name="org.nativescript.plugins.firebase.MyFirebaseMessagingService" android:exported="true"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service> <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/nativescript_google_maps_api_key"/> </application> </manifest>
内容的提问来源于stack exchange,提问作者Kanika Agrawal
相关产品推荐
相关产品推荐

