Loading...

Android7.0特性及适配

1、SharedPreferences废弃共享模式,详见

2、文件共享(拍照、截图、分享、安装等),禁用file://URL格式共享文件,即无法通过Uri.fromFile(File file)获取的url进行文件共享,会发生FileUriExposedException,适配方案如下:

(1)manifest中声明FilProvider

<provider     android:name="androidx.core.content.FileProvider"     android:authorities="${applicationId}.fileProvider"     android:exported="false"     android:grantUriPermissions="true">     <meta-data          android:name="android.support.FILE_PROVIDER_PATHS"          android:resource="@xml/provider_paths" /> </provider>

(2)res/xml/定义共享文件路径

<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android">     <files-path name="file" path=""/> 	<cache-path name="file" path=""/>     <external-path name="external" path=""/>     <external-files-path name="external-files" path=""/> 	<external-cache-path name="external-cache" path=""/> </paths>

注:
a、files-path:内部存储空间应用私有目录下的files目录,等同Context.getFilesDis()路径
b、cache-path:内部存储空间应用私有目录下的cache目录,等同Context.getCacheDir()路径
c、external-path:外部存储空间根目录,等同Environment.getExternalStorageDirectory()路径
d、external-files-path:外部存储空间应用私有目录下的files目录,等同Context.getExternalFilesDir()路径
e、external-cache-path:外部存储空间应用私有目录下的cache目录,等同Context.getExternalCacheDir()路径
f、name为自定义名称
g、path为相应根目录下的子路径,为空表示所有子目录
h、files-path、cache-path、external-path、external-files-path、external-cache-path同一类型可以包含多个

(3)生成content://类型Uri

FileProvider.getUriForFile(Context context, String authority, File file)

(4)给Uri授予临时权限

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

(5)实例:

//拍照     private fun camera(){         val intent = Intent("android.media.action.IMAGE_CAPTURE")         val file = File(Environment.getExternalStorageDirectory(), "demo.png")         val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){             FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileProvider", file)         }else{             Uri.fromFile(file)         }         intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)         startActivityForResult(intent, REQUEST_CODE_CAMERA)     }      //裁剪图片     private fun cropImage(fromFile: File, toFile: File, aspectX: Int, aspectY: Int, width: Int, height: Int){         val intent = Intent("com.android.camera.action.CROP")         val fromUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)             FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileProvider", fromFile)         }else{             Uri.fromFile(fromFile)         }         intent.setDataAndType(fromUri, "image/*")         intent.putExtra("crop", "true")         intent.putExtra("aspectX", aspectX)         intent.putExtra("aspectY", aspectY)         intent.putExtra("outputX", width)         intent.putExtra("outPutY", height)         intent.putExtra("scale", true)         val toUri = Uri.fromFile(toFile)         intent.putExtra(MediaStore.EXTRA_OUTPUT, toUri)         intent.putExtra("return-data", true)         startActivityForResult(intent, REQUEST_CODE_CROP)     }      //分享文件     private fun shareFiles(fileList: Array<File>){         val intent = Intent(Intent.ACTION_SEND_MULTIPLE)         val uriList = arrayListOf<Uri>()         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)             fileList.forEach {                 val uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileProvider", it)                 grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)                 uriList.add(uri)             }         }else{             fileList.forEach {                 uriList.add(Uri.fromFile(it))             }         }         intent.putExtra(Intent.EXTRA_STREAM, uriList)         intent.type = "*/*"         startActivityForResult(Intent.createChooser(intent, ""), REQUEST_CODE_SHARE_FILES)     }      private fun install(file: File){         val intent = Intent(Intent.ACTION_VIEW)         val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)             FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileProvider", file)         }else{             Uri.fromFile(file)         }         intent.setDataAndType(uri, "application/vnd.android.package-archive")         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)         startActivityForResult(intent, REQUEST_CODE_INSTALL)     }

(6)其他方案,如下则仍可以使用Uri.fromFile(File file)共享文件(不建议)

//在Application的onCreat()方法中添加 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {     StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();     StrictMode.setVmPolicy(builder.build());     builder.detectFileUriExposure(); }

3、系统广播限制

静态注册网络状态变更广播、拍照广播、录像广播无效,需要动态注册方式

4、支持使用V2签名