Today, when I reused the code related to installing the APK that I wrote before, an error occurred. That is because the higher version of Android requires a new FileProvider.
New file_paths
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- <root-path name="root" path="" />--> <files-path name="files" path="files" /> <cache-path name="cache" path="files" /> <!-- <external-path name="external" path="files" />--> <external-files-path name="externalfiles" path="files" /> <!-- This tag requires support 25.0.0 or above to be used --> <external-cache-path name="externalcache" path="files" /> <external-path name="external_storage_root" path="." /> </paths>
Other writing methods
The address corresponding to the tag
The physical path is equivalent to Environment.getExternalStorageDirectory() + /path/
The physical path is equivalent to **Context.getExternalFilesDir(String) ** + /path/
The physical path is equivalent to Context.getExternalCacheDir() + /path/
Example:
<?xml version="1.0" encoding="utf-8"?> <paths> <!-- /storage/emulated/0/Android/data/com.test.dust/files/resources/map/tiles/1.0.8.rar ===> content://com.test.dust.provider/map_tiles/1.0.8.rar--> <external-files-path name="map_tiles" path="resources/map/tiles" /> </paths>
The file path corresponding to external-files-path is /storage/emulated/0/Android/data/[packageName]/files
The entire external-files-path tag is equivalent to formatting the absolute path /storage/emulated/0/Android/data/[packageName]/files/[path]/filename into content://[authorities]/[name] /filename form.
New provider
Add the following code in of Manifest.xml
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.utilcode.fileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
Quote
APK installation
public static void installApk(Context context,String downloadApk) { Intent intent = new Intent(Intent.ACTION_VIEW); File file = new File(downloadApk); //L.i("Installation path==" + downloadApk); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { Uri apkUri = FileProvider.getUriForFile (Objects.requireNonNull(context), BuildConfig.APPLICATION_ID + BuildConfig.APPLICATION_ID + ".utilcode.fileProvider", file);//This sentence is very important intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setDataAndType(apkUri, "application/vnd.android.package-archive"); } else { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Uri uri = Uri.fromFile(file); intent.setDataAndType(uri, "application/vnd.android.package-archive"); } context.startActivity(intent); }
Adaptation
private void installApp() { Intent intent = new Intent(Intent.ACTION_VIEW); File file = new File(FileUtils.mkdirs(DirKeys.DIR_APP_UPDATE) + "/test.apk"); Uri apkUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".utilcode.fileProvider", file);//This sentence is very important if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { LogUtils.e("lcb", "sdk:" + Build.VERSION.SDK_INT + "Go here"); intent.setAction(Intent.ACTION_INSTALL_PACKAGE); intent.setData(apkUri); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra(Intent.EXTRA_RETURN_RESULT, true); intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); intent.putExtra(Intent.EXTRA_ALLOW_REPLACE, true); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setDataAndType(apkUri, "application/vnd.android.package-archive"); } else { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Uri uri = Uri.fromFile(file); intent.setDataAndType(uri, "application/vnd.android.package-archive"); } startActivity(intent); }
android11 calls camera
The camera code that needs to be used in the project is as follows:
public static void startCarmera(Fragment fragment) { Uri uri; Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); uri = FileProvider.getUriForFile(fragment.getActivity(), BuildConfig.APPLICATION_ID + ".utilcode.fileProvider", getFile()); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } else { intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getFile())); } fragment.startActivityForResult(intent, RESULT_CAMERA); }
File newFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ “/images/” + System.currentTimeMillis() + “.jpg”);
if (!newFile.exists()) {
newFile.getParentFile().mkdirs();
}
mCurrentPhotoPath = newFile.getAbsolutePath();
return newFile;
}
The album code that needs to be used in the project is as follows:
public static void startGallery(Activity activity) { Intent intentGallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); activity.startActivityForResult(intentGallery, RESULT_GALLERY); }
Processing the returned image in onActivityResult():
protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { if (requestCode == RESULT_CAMERA) { upload(CarmeraUtil.mCurrentPhotoPath); } else if (requestCode == RESULT_GALLERY & amp; & amp; data != null) { //Process photos from the gallery Uri selectedImage = data.getData(); String[] filePathColumn = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String picturePath = cursor.getString(columnIndex); cursor.close(); upload(picturePath); } } }