During APP installation in the project, the “package parsing error” error occurs, and there is no obvious fatal information in the log. Therefore, the system should report an error.
Android development, catch the log is a necessary skill, no error log, then catch the full amount of logcat log, started crazy to see the log, found an error.
Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{ca55219 13782:com.android.packageinstaller/u0a32} (pid=13782, uid=10032) that is not exported from UID 10076
Ha, ha, ha, there is an error log, you can search, the problem is close at hand. FLAG_GRANT_WRITE_URI_PERMISSION in addition to intent. FLAG_GRANT_WRITE_URI_PERMISSION. If you think about it, I this is just a simple installation of an App, did not write data ah, in order to be afraid of the pit left by predecessors, or add this permission, run the program, and sure enough is useless, or need to continue.
I wonder if the FileProvider has permissions. Check if the FileProvider has permissions
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationid}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
Copy the code
From the configuration file, all the permissions have been given to the Filepaths, so I checked the filepaths configuration file.
<external-path
name="external_storage_root"
path="." />
Copy the code
To briefly describe the profile, what each field represents.
Path: Paths that require temporary authorization (. Represents all paths)
Name: You give the access path a name
So what does the tag external-path mean? Represents external storage. The details are as follows:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="root" path="" />// represents the root directory of the device new File("/");<files-path name="files" path="" /> //context.getFilesDir()
<cache-path name="cache" path="" /> //context.getCacheDir()
<external-path name="external" path="" /> //Environment.getExternalStorageDirectory()
<external-files-path name="name" path="path" /> //context.getExternalFilesDirs()
<external-cache-path name="name" path="path" /> //getExternalCacheDirs()
</paths>
Copy the code
Now that I understand, what I specified is not wrong, but it still does not work, I re-read the error message, found in the error message
that is not exported
Copy the code
If you want to set the parameters specified on the provider exported, you can see that it is not a problem. What the hell is this? Take a look at the log:
java.lang.SecurityException: Provider must not be exported
Copy the code
You cannot set the value of exported to true.
Let me reframe the adaptation of the APP installation. The FileProvider adaptation actually has three stages.
There are before 6.0, 7.0, and after 7.0, which means you don’t need to use the FileProvider at all before 7.0, just before 6.0
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri.fromFile(new File(installPath)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Copy the code
In 7.0, however, Google changed its policy and needed to use FileProvider,
Intent intent = new Intent();
Uri uri = null;
uri = FileProvider.getUriForFile(context, context.getPackageName()+".fileprovider".new File(filesPath));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW);
Copy the code
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${APPLICATIONID}.FileProvider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
Copy the code
Authorities: App package name. fileProvider
GrantUriPermissions: Must be true to grant temporary access to the URI
Google has changed again at 8.0 and above, damn it. When installing the APP, you also need to copy the APP to the context.getFilesdir () directory, but you still need the FileProvider as follows:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addCategory("android.intent.category.DEFAULT");
Uri contentUri = FileProvider.getUriForFile(context, "com.iflytek.appstroe2.fileprovider".new File(dstPath));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(contentUri, context.getContentResolver().getType(contentUri));
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
context.grantUriPermission(resolveInfo.activityInfo.packageName, contentUri,Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
context.startActivity(intent);
Copy the code
Here is a clear comb, but MY problem is still not solved. I looked at my system version, found that the nima is Android8.0, but I have been working on Android7.0, I according to the method of Android8.0 tried, found that it can.
Conclusion: From the process of solving this problem, we can see that even if there is no solution for a small problem, we still need to return to the essence of the problem, so that we can give a targeted solution.