Android10 填坑适配指南,实际经验代码,拒绝翻译,android 开发书籍 pdf 下载
} else {canvas.clipPath(path, Region.Op.XOR);// REPLACE、UNION 等}
但我们一定需要一些高级逻辑运算效果怎么办?如小说的仿真翻页阅读效果,解决方案如下,用 Path.op 代替,先运算 Path,再给 canvas.clipPath:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){Path mPathXOR = new Path();mPathXOR.moveTo(0,0);mPathXOR.lineTo(getWidth(),0);mPathXOR.lineTo(getWidth(),getHeight());mPathXOR.lineTo(0,getHeight());mPathXOR.close();//以上根据实际的 Canvas 或 View 的大小,画出相同大小的 Path 即可 mPathXOR.op(mPath0, Path.Op.XOR);canvas.clipPath(mPathXOR);}else {canvas.clipPath(mPath0, Region.Op.XOR);}
2.明文 HTTP 限制
当?targetSdkVersion >=?Build.VERSION_CODES.P 时,默认限制了 HTTP 请求,并出现相关日志:
java.net.UnknownServiceException: CLEARTEXT communication to xxx not permitted by network security policy
第一种解决方案:在 AndroidManifest.xml 中 Application 添加如下节点代码
<application android:usesCleartextTraffic="true">
第二种解决方案:在 res 目录新建 xml 目录,已建的跳过 在 xml 目录新建一个 xml 文件 network_security_config.xml,然后在 AndroidManifest.xml 中 Application 添加如下节点代码
android:networkSecurityConfig="@xml/network_config"
名字随机,内容如下:
<?xml version="1.0" encoding="utf-8"?><network-security-config><base-config cleartextTrafficPermitted="true" /></network-security-config>
3.Android Q 中的媒体资源读写
1、扫描系统相册、视频等,图片、视频选择器都是通过
ContentResolver 来提供,主要代码如下:
private static final String[] IMAGE_PROJECTION = {MediaStore.Images.Media.DATA,MediaStore.Images.Media.DISPLAY_NAME,MediaStore.Images.Media._ID,MediaStore.Images.Media.BUCKET_ID,MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
Cursor imageCursor = mContext.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,IMAGE_PROJECTION, null, null, IMAGE_PROJECTION[0] + " DESC");
String path = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));String name = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));int id = imageCursor.getInt(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));String folderPath = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[3]));String folderName = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[4]));
//Android Q 公有目录只能通过 Content Uri + id 的方式访问,以前的 File 路径全部无效,如果是 Video,记得换成 MediaStore.Videosif(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){path = MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build().toString();}
2、判断公有目录文件是否存在,自 Android Q 开始,公有目录 File API 都失效,不能直接通过 new File(path).exists();判断公有目录文件是否存在,正确方式如下:
public static boolean isAndroidQFileExists(Context context, String path){AssetFileDescriptor afd = null;ContentResolver cr = context.getContentResolver();try {Uri uri = Uri.parse(path);afd = cr.openAssetFileDescriptor(uri, "r");if (afd == null) {return false;} else {close(afd);}} catch (FileNotFoundException e) {return false;}finally {close(afd);}return true;}
3、copy 或者下载文件到公有目录,保存 Bitmap 同理,如 Download,MIME_TYPE 类型可以自行参考对应的文件类型,这里只对 APK 作出说明,从私有目录 copy 到公有目录 demo 如下(远程下载同理,只要拿到 OutputStream 即可,亦可下载到私有目录再 copy 到公有目录):
public static void copyToDownloadAndroidQ(Context context, String sourcePath, String fileName, String saveDirName){ContentValues values = new ContentValues();values.put(MediaStore.Downloads.DISPLAY_NAME, fileName);values.put(MediaStore.Downloads.MIME_TYPE, "application/vnd.android.package-archive");values.put(MediaStore.Downloads.RELATIVE_PATH, "Download/" + saveDirName.replaceAll("/","") + "/");
Uri external = MediaStore.Downloads.EXTERNAL_CONTENT_URI;ContentResolver resolver = context.getContentResolver();
Uri insertUri = resolver.insert(external, values);if(insertUri == null) {return;}
String mFilePath = insertUri.toString();
InputStream is = null;OutputStream os = null;try {os = resolver.openOutputStream(insertUri);if(os == null){return;}int read;File sourceFile = new File(sourcePath);if (sourceFile.exists()) { // 文件存在时 is = new FileInputStream(sourceFile); // 读入原文件 byte[] buffer = new byte[1444];while ((read = is.read(buffer)) != -1) {os.write(buffer, 0, read);}}} catch (Exception e) {e.printStackTrace();}finally {close(is,os);}
}
4、保存图片相关
/**
通过 MediaStore 保存,兼容 AndroidQ,保存成功自动添加到相册数据库,无需再发送广播告诉系统插入相册
@param context context
@param sourceFile 源文件
@param saveFileName 保存的文件名
@param saveDirName picture 子目录
@return 成功或者失败*/public static boolean saveImageWithAndroidQ(Context context,File sourceFile,String saveFileName,String saveDirName) {String extension = BitmapUtil.getExtension(sourceFile.getAbsolutePath());
ContentValues values = new ContentValues();values.put(MediaStore.Images.Media.DESCRIPTION, "This is an image");values.put(MediaStore.Images.Media.DISPLAY_NAME, saveFileName);values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");values.put(MediaStore.Images.Media.TITLE, "Image.png");values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/" + saveDirName);
评论