权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
1、android本地图片都是通过相册数据库获取对应数据
private static final String[] IMAGES = {
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media.LATITUDE,
MediaStore.Images.Media.LONGITUDE,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media._ID
};
@WorkerThread
public void scanImageFile(Map<String, AlbumFolder> albumFolderMap, AlbumFolder allFileFolder) {
ContentResolver contentResolver = mContext.getContentResolver();
Cursor cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGES,
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
String path = cursor.getString(0);
String folderName = cursor.getString(1);
String mimeType = cursor.getString(2);
long addDate = cursor.getLong(3);
float latitude = cursor.getFloat(4);
float longitude = cursor.getFloat(5);
long size = cursor.getLong(6);
String imageId = cursor.getString(7);
//添加方法判断文件是否存在,如果不存在则不需要add
if (path != null && new File(path).exists()) {
AlbumFile imageFile = new AlbumFile();
imageFile.setMediaType(AlbumFile.TYPE_IMAGE);
imageFile.setPath(path);
imageFile.setFolderName(folderName);
imageFile.setMimeType(mimeType);
imageFile.setAddDate(addDate);
imageFile.setLatitude(latitude);
imageFile.setLongitude(longitude);
imageFile.setSize(size);
//通过数据id,获取的图片对应uri
imageFile.setUri(Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageId));
allFileFolder.addAlbumFile(imageFile);
AlbumFolder albumFolder = albumFolderMap.get(folderName);
if (albumFolder != null)
albumFolder.addAlbumFile(imageFile);
else {
albumFolder = new AlbumFolder();
albumFolder.setName(folderName);
albumFolder.addAlbumFile(imageFile);
albumFolderMap.put(folderName, albumFolder);
}
}
}
cursor.close();
}
}
这里,我们需要注意,因为android10以后版本不能通过File来获取图片文件,所以我们需要通过Uri来讲图片文件转到沙箱文件中,来压缩等操作。
/**
* uri 转 File 兼容Android Q
*
* @param context
* @param uri
* @return
*/
public static File fileByUri(Context context, Uri uri) {
File file = null;
if (androidQ()) {
file = saveFileFromInputByAndroidBox(context, uri, fileSuffixName(filePathByUri(context, uri)));
} else {
file = new File(filePathByUri(context, uri));
}
return file;
}
/**
* Android Q 保存uri文件到沙箱内
*
* @param context
* @param uri
* @param suffixName
* @return
*/
public static File saveFileFromInputByAndroidBox(Context context, Uri uri, String suffixName) {
BufferedInputStream bis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
File file = null;
try {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
file = createFilePathByBox(context, "file", randomName() + suffixName);
bis = new BufferedInputStream(inputStream);
fos = new FileOutputStream(file);
if (fos != null) {
bos = new BufferedOutputStream(fos);
byte[] buf = new byte[BYTE];
int bytes = bis.read(buf);
while (bytes >= 0) {
bos.write(buf, 0, bytes);
bos.flush();
bytes = bis.read(buf);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeSilently(bis);
closeSilently(bos);
closeSilently(fos);
}
return file;
}
/**
* 通过uri 获取文件真实路径 (AndroidQ以下版本)
*
* @param context
* @param uri
* @return
*/
public static String filePathByUri(Context context, Uri uri) {
String imagePath = null;
if (context != null && uri != null) {
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
if (cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
imagePath = cursor.getString(column_index);
}
cursor.close();
}
return imagePath;
}
如果是AndroidQ一下,其实我们再获取图片封装对象里面,就已经得到Path,可以直接使用。
2、视频 其实,视频跟图片获取逻辑也是一样,主要查询字段不一样来区分,获取视频还是图片
/**
* 视频
*/
private static final String[] VIDEOS = {
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.MIME_TYPE,
MediaStore.Video.Media.DATE_ADDED,
MediaStore.Video.Media.LATITUDE,
MediaStore.Video.Media.LONGITUDE,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media._ID
};
/**
* 获取视频数据(按照全部、文件夹区分)
*
* @param albumFolderMap 所有文件夹
* @param allFileFolder 全部内容单独文件夹
*/
@WorkerThread
private void scanVideoFile(Map<String, AlbumFolder> albumFolderMap, AlbumFolder allFileFolder) {
ContentResolver contentResolver = mContext.getContentResolver();
Cursor cursor = contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
VIDEOS,
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
String path = cursor.getString(0);
String folderName = cursor.getString(1);
String mimeType = cursor.getString(2);
long addDate = cursor.getLong(3);
float latitude = cursor.getFloat(4);
float longitude = cursor.getFloat(5);
long size = cursor.getLong(6);
long duration = cursor.getLong(7);
long videoId = cursor.getLong(8);
if (duration <= 0) {
continue;
}
AlbumFile videoFile = new AlbumFile();
videoFile.setMediaType(AlbumFile.TYPE_VIDEO);
videoFile.setPath(path);
videoFile.setFolderName(folderName);
videoFile.setMimeType(mimeType);
videoFile.setAddDate(addDate);
videoFile.setLatitude(latitude);
videoFile.setLongitude(longitude);
videoFile.setSize(size);
videoFile.setDuration(duration);
videoFile.setDurationStr(AlbumUtils.convertDuration(duration));
videoFile.setUri(Uri.withAppendedPath(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, videoId + ""));
allFileFolder.addAlbumFile(videoFile);
AlbumFolder albumFolder = albumFolderMap.get(folderName);
if (albumFolder != null)
albumFolder.addAlbumFile(videoFile);
else {
albumFolder = new AlbumFolder();
albumFolder.setName(folderName);
albumFolder.addAlbumFile(videoFile);
albumFolderMap.put(folderName, albumFolder);
}
}
cursor.close();
}
}
其实视频,我们会涉及到一个问题,就是封面展示的问题。
第一种:直接通过Gilde做展示
Glide.with(getContext()).load(uri).into(imageView);
第二种:获取视频文件第一帧,作为封面(需要保存图片封面到本地)
第三种:获取数据库中视频的封面。
3.拍照
Uri uri = FileUtils.getImageUriByMediaStore(activity);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); //uri传递户自己生成
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
activity.startActivityForResult(intent, requestCode);
4.录像
Uri uri = FileUtils.getVideoUriByMediaStore(activity);
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // MediaStore.EXTRA_VIDEO_QUALITY 表示录制视频的质量,从 0-1,越大表示质量越好,同时视频也越大
//允许记录的最长时间(以 秒 为单位) 例如:限制为60S
//intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 60);
//允许的最大大小(以 B 为单位) 例如:限制大小为100M
//intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 1024L * 1024 * 100);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
activity.startActivityForResult(intent, requestCode);