英文:
Android 11 Package Visibilty issue
问题
我有一个从服务器下载APK文件的应用程序,但是即使我在Android清单中使用了查询标签,我仍然无法像其他Android版本那样启动它。
这是启动代码:-
private void callInstallProcess() {
try
{
Intent intent = new Intent(Intent.ACTION_VIEW);
File file = new File(pathname);
Uri fileUri = Uri.fromFile(file);
if(Build.VERSION.SDK_INT >= 24){
try{
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
}catch(Exception e){
e.printStackTrace();
}
}
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
startActivityForResult(intent, PERMISSIONS_REQUEST);
}
catch (Exception e)
{
e.printStackTrace();
}
}
这是我的清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="x.x.x">
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:mimeType="application/vnd.android.package-archive" />
</intent>
</queries>
<application
android:allowBackup="false"
android:icon="@mipmap/appicon"
android:label="@string/app_name"
android:roundIcon="@mipmap/appicon"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Gradle文件:-
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "30.0.0-rc4"
defaultConfig {
applicationId "x.x.x"
minSdkVersion 22
targetSdkVersion 'R'
versionCode 3
versionName "1.11"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
我已经允许我的应用程序在Android R预览4模拟器上安装未知应用程序。
日志:-
W/System.err: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=file:///storage/emulated/0/Android/data/x.x.x/files/ApkDownload/x.x.x.apk typ=application/vnd.android.package-archive flg=0x3 }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2067)
W/System.err: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1727)
at android.app.Activity.startActivityForResult(Activity.java:5323)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:676)
at android.app.Activity.startActivityForResult(Activity.java:5281)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:663)
at x.x.x.MainActivity.callInstallProcess(MainActivity.java:126)
at x.x.x.MainActivity.askPerm(MainActivity.java:98)
W/System.err: at x.x.x.MainActivity.access$000(MainActivity.java:42)
at x.x.x.MainActivity$1.onClick(MainActivity.java:79)
at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7478)
at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
D/EGL_emulation: eglMakeCurrent: 0xe8ae0220: ver 2 0 (tinfo 0xe8e31210)
我正在使用Android Studio 4和Gradle版本为4.0.0。这只是一个错误,还是我做错了什么,因为Chrome可以管理APK安装。
英文:
I have a app that downloads an apk from server, but I am unable to launch it like other android versions even though I have queries tag in android manifest
Here is the intent code:-
private void callInstallProcess() {
try
{
Intent intent = new Intent(Intent.ACTION_VIEW);
File file = new File(pathname);
Uri fileUri = Uri.fromFile(file);
// if (Build.VERSION.SDK_INT >= 24) {
// fileUri = FileProvider.getUriForFile(this, getPackageName(),
// file);
// }
if(Build.VERSION.SDK_INT>=24){
try{
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
}catch(Exception e){
e.printStackTrace();
}
}
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setDataAndType(fileUri , "application/vnd.android.package-archive");
startActivityForResult(intent, PERMISSIONS_REQUEST);
}
catch (Exception e)
{
e.printStackTrace();
}
}
Here is my manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="x.x.x">
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:mimeType="application/vnd.android.package-archive" />
</intent>
</queries>
<application
android:allowBackup="false"
android:icon="@mipmap/appicon"
android:label="@string/app_name"
android:roundIcon="@mipmap/appicon"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Gradle file:-
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "30.0.0-rc4"
defaultConfig {
applicationId "x.x.x"
minSdkVersion 22
targetSdkVersion 'R'
versionCode 3
versionName "1.11"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
I have allowed to my app the permission to install unknown apps on android R preview 4 emulator.
Log:-
W/System.err: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=file:///storage/emulated/0/Android/data/x.x.x/files/ApkDownload/x.x.x.apk typ=application/vnd.android.package-archive flg=0x3 }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2067)
W/System.err: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1727)
at android.app.Activity.startActivityForResult(Activity.java:5323)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:676)
at android.app.Activity.startActivityForResult(Activity.java:5281)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:663)
at x.x.x.MainActivity.callInstallProcess(MainActivity.java:126)
at x.x.x.MainActivity.askPerm(MainActivity.java:98)
W/System.err: at x.x.x.MainActivity.access$000(MainActivity.java:42)
at x.x.x.MainActivity$1.onClick(MainActivity.java:79)
at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7478)
at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
D/EGL_emulation: eglMakeCurrent: 0xe8ae0220: ver 2 0 (tinfo 0xe8e31210)
I am using android studio 4 and gradleversion is 4.0.0
Is it just a bug or am I doing something wrong as chrome manages to intent apk install.
答案1
得分: 1
> 这只是一个错误还是我做错了什么
你做错了某些事情。
Uri.fromFile()
自 Android 7.0 起已被禁止使用。通常情况下,如果你尝试在 Intent
中使用它,会导致应用崩溃并抛出 FileUriExposedException
。但你并没有修复这个问题,而是选择尝试绕过检查,通过你的 disableDeathOnFileUriExposure
hack。然而,没有其他人需要遵循你的 file:///
的 Uri
,因为这个用法已经被禁止多年。显然,Android R 的安装程序不再支持 file:///
。
所以,至少在 Android 7.0+ 上你需要切换到使用 FileProvider
。Uri.fromFile()
在 Android 6.0 及更早版本是可以的,而且特别针对你尝试做的事情(安装 APK),在这些旧设备上你别无选择,只能使用 Uri.fromFile()
。
此外,值得注意的是,在 Android 10+ 上使用 ACTION_VIEW
来安装 APK 已经被弃用。虽然目前它还能临时工作,但 Google 希望你改用 PackageInstaller
API。
英文:
> Is it just a bug or am I doing something wrong
You are doing something wrong.
Uri.fromFile()
has been banned, in effect, since Android 7.0. Normally, your attempt to us it with an Intent
would crash with a FileUriExposedException
. Rather than fixing the problem, you decided to try to bypass the check, through your disableDeathOnFileUriExposure
hack. However, nobody else has to honor your file:///
Uri
, because, again, that has been banned for years. Apparently, Android R's installer no longer supports file:///
.
So, at minimum, you need to switch to using FileProvider
on Android 7.0+. Uri.fromFile()
is fine for Android 6.0 and older, and specifically for what you are trying to do (install an APK), you have no choice but to use Uri.fromFile()
for those older devices.
Also note that using ACTION_VIEW
for installing an APK has been deprecated on Android 10+. Temporarily it still works, but Google would like you to switch to the PackageInstaller
API instead.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论