Q:Android10开始应用将不可直接访问外部存储(/sdcard)文件,否则抛异常。
1.方案一:停用过滤视图,使用旧版存储模式
<manifest ... >
<!-- This attribute is "false" by default on apps targeting Android Q. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
【风险点】该方案是采用android Q以下SDK原有的存储策略,是一个过度兼容方案,官方不建议使用。所有应用的主要平台版本都需要分区存储,无论其采用哪种目标 SDK 级别。
2.方案二:使用androidQ的存储方案---SAF
【example以图片保存为例子】
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources res = MainActivity.this.getResources();
Bitmap bmp= BitmapFactory.decodeResource(res, R.drawable.a);
saveSignImage("wxa",bmp);
}
//将文件保存到公共的媒体文件夹
//这里的filepath不是绝对路径,而是某个媒体文件夹下的子路径,和沙盒子文件夹类似
//这里的filename单纯的指文件名,不包含路径
public void saveSignImage(String fileName, Bitmap bitmap) {
try {
//设置保存参数到ContentValues中
ContentValues contentValues = new ContentValues();
//设置文件名
contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
//兼容Android Q和以下版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//android Q中不再使用DATA字段,而用RELATIVE_PATH代替
//RELATIVE_PATH是相对路径不是绝对路径
//DCIM是系统文件夹,关于系统文件夹可以到系统自带的文件管理器中查看,不可以写没存在的名字
contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/Camera");
//contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, "Music/signImage");
} else {
contentValues.put(MediaStore.Images.Media.DATA, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
}
//设置文件类型
contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/JPEG");
//执行insert操作,向系统文件夹中添加文件
//EXTERNAL_CONTENT_URI代表外部存储器,该值不变
Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
if (uri != null) {
//若生成了uri,则表示该文件添加成功
//使用流将内容写入该uri中即可
OutputStream outputStream = getContentResolver().openOutputStream(uri);
if (outputStream != null) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
outputStream.flush();
outputStream.close();
}
}
} catch (Exception e) {
}
}
}
存储图片
String fileName = "xiaoan.jpg";
Log.d("wxa", "---mimeType----->>>" + mimeType);
ContentValues contentValues = new ContentValues();
Uri fileUri=null;
contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//android Q中不再使用DATA字段,而用RELATIVE_PATH代替
//RELATIVE_PATH是相对路径不是绝对路径
//DCIM是系统文件夹,关于系统文件夹可以到系统自带的文件管理器中查看,不可以写没存在的名
contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/Camera");
contentValues.put(MediaStore.Images.Media.MIME_TYPE, mimeType);
fileUri = SaveManager.getApplicationContext().getContentResolver()
.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
}
存储视频
String fileName = "xiaoan.mp4";
ContentValues contentValues = new ContentValues();
Uri fileUri=null;
contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//android Q中不再使用DATA字段,而用RELATIVE_PATH代替
//RELATIVE_PATH是相对路径不是绝对路径
//DCIM是系统文件夹,关于系统文件夹可以到系统自带的文件管理器中查看,不可以写没存在的名字
contentValues.put(MediaStore.Video.Media.RELATIVE_PATH, "DCIM/Camera");
contentValues.put(MediaStore.Video.Media.MIME_TYPE, mimeType);
fileUri = SaveManager.getApplicationContext().getContentResolver()
.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
}