【Android】记录一次安卓10的图片读取
非常的难受,这个读写内容。因为Android 10没有读取sd的权限了,Android 11都恢复了部分读写权限,但是Android 10的适配是真的难受。
好在有内容提供者
这个组件,通过这个中介可以获取Uri,再从Uri转为InputSteam,之后转为byte[]
从Uri到InputSteam再到byte[]
在学okhttp post上传图片文件的时候,因为读取不了文件,所以File对象无法生成,导致RequestBody fileBody = RequestBody.create(mediaType,content);
方法中,content无法成为file对象,如何解决上传图片的问题?
查看create方法的传参:
发现可以用byte[]数组进行上传,ok那就换一种方式——从Uri到InputSteam到byte[]
我编写了一个工具类,其中的方法可以看看注释:
import ...;
public class QStorageUtils {
// 从图片路径转为Uri
public static Uri imagePath2Uri(Context context, String path) {
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.Media._ID}, MediaStore.Images.Media.DATA + "=? ",
new String[]{path}, null);
if (cursor != null && cursor.moveToFirst()) {
@SuppressLint("Range") int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
return Uri.withAppendedPath(baseUri, "" + id);
} else {
// 如果图片不在手机的共享图片数据库,就先把它插入。
if (new File(path).exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, path);
return context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeSteam(cursor);
}
return null;
}
// Uri转为Bytes数组
public static byte[] Uri2Bytes(Context context, Uri uri) {
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
is = context.getContentResolver().openInputStream(uri);
byte[] buf = new byte[1024];
int len = 0;
String content = null;
while ((len=is.read(buf)) != -1) {
baos.write(buf,0,len);
}
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeSteam(is);
closeSteam(baos);
}
return new byte[0];
}
// 关闭流
public static void closeSteam(Closeable stream) {
try {
if (stream != null) {
stream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
okhttp使用post上传文件的方法如下:
@SuppressLint("Range")
private void btnDoUploadFile() {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10000,TimeUnit.MILLISECONDS)
.build();
Uri imageContentUri = QStorageUtils.imagePath2Uri(this, "/storage/emulated/0/Download/1195405.jpg");
Log.d(TAG,"pic uri --> " + imageContentUri);
byte[] content = QStorageUtils.Uri2Bytes(this,imageContentUri);
MediaType mediaType = MediaType.parse("image/jpeg");
RequestBody fileBody = RequestBody.create(mediaType,content);
RequestBody requestBody = new MultipartBody.Builder()
.addFormDataPart("file","1.jpg",fileBody)
.build();
Request request = new Request.Builder()
.url(BASE_URL + "file/upload")
.post(requestBody)
.build();
Call task = client.newCall(request);
task.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG,"onFailure --> " + e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
Log.d(TAG,"response code --> " + response.code());
ResponseBody body = response.body();
assert body != null;
Log.d(TAG,"response body --> " + body.string());
}
}
});
}
测试上传成功: