//Android Q 公有目录只能通过Content Uri + id的方式访问,以前的File路径全部无效,如果是Video,记得换成MediaStore.Videos if(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);
Uri external = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver resolver = context.getContentResolver();
Uri insertUri = resolver.insert(external, values);
BufferedInputStream inputStream = null;
OutputStream os = null;
boolean result = false;
try {
inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
if (insertUri != null) {
os = resolver.openOutputStream(insertUri);
}
if (os != null) {
byte[] buffer = new byte[1024 * 4];
int len;
while ((len = inputStream.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
os.flush();
}
result = true;
} catch (IOException e) {
result = false;
} finally {
close(os, inputStream);
}
return result;
}
### **4.EditText默认不获取焦点,不自动弹出键盘**
该问题出现在?**targetSdkVersion >=?Build.VERSION\_CODES.P** 情况下,且设备版本为Android P以上版本,解决方法在onCreate中加入如下代码,可获得焦点,如需要弹出键盘可延迟一下:
mEditText.post(() -> { mEditText.requestFocus(); mEditText.setFocusable(true); mEditText.setFocusableInTouchMode(true); });
### **5.安装APK Intent及其它共享文件相关Intent**
/*
-
自Android N开始,是通过FileProvider共享相关文件,但是Android Q对公有目录 File API进行了限制,只能通过Uri来操作, -
从代码上看,又变得和以前低版本一样了,只是必须加上权限代码Intent.FLAG_GRANT_READ_URI_PERMISSION */ private void installApk() { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ //适配Android Q,注意mFilePath是通过ContentResolver得到的,上述有相关代码 Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse(mFilePath) ,“application/vnd.android.package-archive”); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(intent); return ; } File file = new File(saveFileName + "demo.apk");
if (!file.exists())
return;
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "net.oschina.app.provider", file);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
startActivity(intent);
|