SecurityException: открытие провайдера, который не экспортируется из uid
У меня есть приложение, которого нет в Play Store. Ранее я мог запустить установщик приложения с помощью следующего кода:
В деятельности:
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: Произошла ошибка при выполнении doInBackground() в android.os.AsyncTask$3.done(AsyncTask.java:326) в Java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354) в java.util.concurrent.FutureTask.setException(FutureTask.java:223) в java.util.concurrent.FutureTask.run(FutureTask.java:24).os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244) в java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) в java.util.concurrent.ThreadPoolExcecutor: $ 607) at java.lang.Thread.run(Thread.java:761) Причина: java.lang.SecurityException: Отказ в разрешении: открытие провайдера in.namespace.appname.comp.GenericFileProvider из ProcessRecord{ba35e80 6499:com.android.packageinstaller/u0a17} (pid=6499, uid=10017), который не экспортируется из uid 10076 на android.os.Parcel.readException(Parcel.java:1684) на android.os.Parcel.readException(Parcel.java:1637) по адресу android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4213) по адресу android.app.ActivityThread.acquireProvider(ActivityThread.java:5535) по адресу android.app.ContextImplver.ConvertSign (ContextImpl.java:2239) в android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1517) в android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:11es.escriptForex.Confile.Confile.Rent). 984) в android.content.ContentResolver.openInputStream(ContentResolver.java:704) по адресу com.android.packageinstaller.PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:804ctivity)AnackInstalInstalAndInstalInstallerstallerstaller.java:795) на android.os.AsyncTask$2.call(AsyncTask.java:306) на java.util.concurrent.FutureTask.run(FutureTask.java:237) на ndroid.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:244) в java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) в java.util.concurrent.ThreadPoolExecutor: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>
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);
Удалить android:readPermission="in.namespace.appname.fp.READ"
,
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)