1

我有一个不在 Play 商店中的应用程序。我之前能够通过以下代码启动应用程序安装程序:

在活动中:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/app_path/app_name.apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);

现在,我将其更改targetSdkVersion为 25,并对代码进行了一些更改,但出现以下错误:

致命异常:AsyncTask #1 进程:com.android.packageinstaller,PID:6499 java.lang.RuntimeException:在 java.os.AsyncTask$3.done(AsyncTask.java:326) 处执行 doInBackground() 时出错。 util.concurrent.FutureTask.finishCompletion(FutureTask.java:354) 在 java.util.concurrent.FutureTask.setException(FutureTask.java:223) 在 java.util.concurrent.FutureTask.run(FutureTask.java:242) 在 android .os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java: 607) 在 java.lang.Thread.run(Thread.java:761) 引起:java.lang.SecurityException:权限被拒绝:在.namespace.appname.comp 中打开提供程序。ProcessRecord{ba35e80 6499:com.android.packageinstaller/u0a17} (pid=6499, uid=10017) 的 GenericFileProvider 不是从 android.os.Parcel.readException(Parcel.java:1684) 的 android.os 的 uid 10076 导出的.Parcel.readException(Parcel.java:1637) 在 android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4213) 在 android.app.ActivityThread.acquireProvider(ActivityThread.java:5535) 在 android.app.ContextImpl$ApplicationContentResolver。在 android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1131) 在 android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java) 的 android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1517) 获取UnstableProvider(ContextImpl.java:2239) :984) 在 android.content。ContentResolver.openInputStream(ContentResolver.java:704) 在 com.android.packageinstaller.PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:804) 在 com.android.packageinstaller.PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:795) 在 android .os.AsyncTask$2.call(AsyncTask.java:306) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 在 java.lang.Thread.run(Thread.java:761)PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:804) at com.android.packageinstaller.PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:795) at android.os.AsyncTask$2.call(AsyncTask.java:306) at java。 util.concurrent.FutureTask.run(FutureTask.java:237) 在 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 在java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 在 java.lang.Thread.run(Thread.java:761)PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:804) at com.android.packageinstaller.PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:795) at android.os.AsyncTask$2.call(AsyncTask.java:306) at java。 util.concurrent.FutureTask.run(FutureTask.java:237) 在 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 在java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 在 java.lang.Thread.run(Thread.java:761)AsyncTask$2.call(AsyncTask.java:306) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244) at java.util .concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 在 java.lang.Thread.run(Thread.java:761)AsyncTask$2.call(AsyncTask.java:306) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244) at java.util .concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 在 java.lang.Thread.run(Thread.java:761) 

这些是我在代码中所做的更改:

在清单中:

<permission
    android:name="in.namespace.appname.fp.READ"
    android:description="@string/file_provider_permission_description"
    android:label="in.namespace.appname.READ_FILE"/>

<uses-permission android:name="in.namespace.appname.fp.READ"/>

<application
    ...
    ...
    <provider
        android:name=".comp.GenericFileProvider"
        android:authorities="in.namespace.appname.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true"
        android:readPermission="in.namespace.appname.fp.READ">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>
    .
    .
</application>

GenericFileProvider在目录中创建一个空类comp

public class GenericFileProvider extends FileProvider { }

将活动代码更改为:

File updatedApk = new File(Environment.getExternalStorageDirectory() + "/file_path/appname.apk");
Uri updatedApkUri =  GenericFileProvider.getUriForFile(
     AppUpdateActivity.this,
     "in.namespace.appname.fileprovider",
     updatedApk);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(updatedApkUri, "application/vnd.android.package-archive");

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);

是什么导致了这个错误,我该如何解决这个问题?

编辑#1

改变了我的清单:

<provider
        android:name=".comp.GenericFileProvider"
        android:authorities="in.namespace.appname.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>
4

3 回答 3

2

在我的情况下,启动 Intent 有这个标志Intent.FLAG_ACTIVITY_NEW_TASK,它导致了问题。所以我从意图中删除了那个标志,它开始工作了。

工作示例代码

String myPackageName = getApplicationContext().getPackageName();
File f = new File(Environment.getExternalStorageDirectory() + "/Download/" + downloadName);
Uri mediaUri = FileProvider.getUriForFile(getApplicationContext(), myPackageName + ".provider", f);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(mediaUri, "application/vnd.android.package-archive");
startActivity(intent);
于 2019-10-20T17:50:17.720 回答
0
 Uri updatedApkUri =  GenericFileProvider.getUriForFile(
 AppUpdateActivity.this,
 "in.namespace.appname.fileprovider",
 updatedApk);

请将您的代码更改为此

 Uri updatedApkUri =  GenericFileProvider.getUriForFile(
 AppUpdateActivity.this,
 BuildConfig.APPLICATION_ID + ".provider",
 updatedApk);

并像这样管理权限

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                } else if (Build.VERSION.SDK_INT >= 
Build.VERSION_CODES.JELLY_BEAN) {
                    val clip = ClipData.newUri(contentResolver, "A photo", 
mImageCaptureUri)
                    intent.clipData = clip
                    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                } else {
                    val resInfoList = 
 packageManager.queryIntentActivities(intent, 
 PackageManager.MATCH_DEFAULT_ONLY)
                    for (resolveInfo in resInfoList) {
                        val packageName = 
 resolveInfo.activityInfo.packageName
                        grantUriPermission(packageName, mImageCaptureUri, 
 Intent.FLAG_GRANT_WRITE_URI_PERMISSION or 
 Intent.FLAG_GRANT_READ_URI_PERMISSION)
                    }
                }
            }
            intent.putExtra("return-data", true)
于 2017-11-17T12:53:18.183 回答
0

删除android:readPermission="in.namespace.appname.fp.READ".

于 2017-11-17T12:09:31.477 回答