Android:简单的拍照/相册截图功能
因为以前做一些项目偶尔会用到拍照截图或者相册截取图做头像的功能,在这里整理一下以免重复踩坑。
1.权限申请
首先我们需要获取相册以及读写内存权限。
AndroidManifest.xml声明
因为申请了WRITE_EXTERNAL_STORAGE就能进行读写操作,我就不再重复申请读取的权限了。
<!-- 允许程序设置内置sd卡的写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 运行程序使用相机权限-->
<uses-permission android:name="android.permission.CAMERA" />
动态申请权限
权限并不是xml申请就完事,targetSdkVersion为23或者以上我们还需要在运行时请求这些所需的权限。
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED||
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
//申请WRITE_EXTERNAL_STORAGE权限
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);
}else {
have_permission = true;
}
然后我们需要处理权限申请的回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(requestCode==123){
boolean isAllGranted = true;
for (int grant : grantResults) {
if (grant != PackageManager.PERMISSION_GRANTED) {
isAllGranted = false;
have_permission = false;
break;
}
}
if (isAllGranted) {
have_permission = true;
}
}
}
2.拍照截图
权限申请完毕之后下来的就是正戏。
确认存储路径是否存在
我这里是在系统相册的目录下新建一个独立文件夹做存储,比较不环保(程序卸载依旧保留文件),大家可以自行修改。
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath();
final File file = new File(path + "/plants");
if (!file.exists()) {
try {
//按照指定的路径创建文件夹
file.mkdirs();
} catch (Exception e) {
// TODO: handle exception
}
}
拍照/相册截图操作
逻辑流程:
下面开始码代码:
private Uri imageUri;
private Uri imageCropUri;
private File cropFile;
private static final int RESULT_CAMERA_ONLY = 101;//拍照
private static final int RESULT_ALBUM_ONLY_THROUGH_URI = 102;//相册
private static final int CROP_PATH_RESULT = 103;//截图
触发系统拍照相关的代码:
if(have_permission){ //判断是否拥有权限
File file2 = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath()+ "/plants/temp"+"12345"+".jpg");//创建拍照图片文件
imageUri = Uri.fromFile(file2);
File cropFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath() + "/plants/temp"+"12345"+"_crop.jpg");//创建截图图片文件
imageCropUri = Uri.fromFile(cropFile);
takeCameraOnly();
}else {
Log.e("MainActivity","permission:"+have_permission);
}
void takeCameraOnly() {
Intent intent = null;
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//action is capture
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, RESULT_CAMERA_ONLY);
}
触发相册取图的代码:
if(have_permission){
gotoAlbum();
}else {
Log.e("MainActivity","permission:"+have_permission);
}
void gotoAlbum(){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
startActivityForResult(intent, RESULT_ALBUM_ONLY_THROUGH_URI);
}
重写回调函数onActivityResult():
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.i("onActivityResult","requestCode:"+requestCode+"resultCode:"+resultCode);
if (resultCode != Activity.RESULT_OK) {
return;
}
switch (requestCode) {
case RESULT_CAMERA_ONLY: {
File file2 = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath()+ "/plants/temp"+ "12345"+".jpg");// Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
imageUri = Uri.fromFile(file2);
cropFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath() + "/plants/temp"+ "12345"+"_crop.jpg");
imageCropUri = Uri.fromFile(cropFile);
cropImg(imageUri);
}
break;
case RESULT_ALBUM_ONLY_THROUGH_URI:{
String picPath = parsePicturePath(MainActivity.this,data.getData());
File file = new File(picPath);
Uri uri= Uri.fromFile(file);
cropFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath() + "/plants/temp"+ "12345"+"_crop.jpg");
imageCropUri = Uri.fromFile(cropFile);
cropImg(uri);
}
break;
case CROP_PATH_RESULT: {
if (getTempFile() != null) {
try {
imageCropUri = Uri.fromFile(cropFile);
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageCropUri));
if (bitmap != null) {
Bitmap smallBmp = setScaleBitmap(bitmap, 2);
riv_flower.setImageBitmap(smallBmp);
}
if(!TextUtils.isEmpty(imageUri.toString())){//对拍照原图进行删除操作,可视情况考虑是否保留
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath()+ "/plants/temp"+ "12345"+".jpg");
file.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}else{
Log.e("CROP_PATH_RESULT","getTempFile=null");
}
}
break;
}
}
触发截图操作:
public void cropImg(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 700);
intent.putExtra("outputY", 700);
intent.putExtra("return-data", false);
// Log.i("TAG","imageCropUri;"+imageCropUri.toString());
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageCropUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, CROP_PATH_RESULT);
}
图片压缩相关代码:
private Bitmap setScaleBitmap(Bitmap photo,int SCALE) {
if (photo != null) {
//为防止原始图片过大导致内存溢出,这里先缩小原图显示,然后释放原始Bitmap占用的内存
//这里缩小了1/2,但图片过大时仍然会出现加载不了,但系统中一个BITMAP最大是在10M左右,我们可以根据BITMAP的大小
//根据当前的比例缩小,即如果当前是15M,那如果定缩小后是6M,那么SCALE= 15/6
Bitmap smallBitmap = zoomBitmap(photo, photo.getWidth() / SCALE, photo.getHeight() / SCALE);
//释放原始图片占用的内存,防止out of memory异常发生
photo.recycle();
return smallBitmap;
}
return null;
}
public Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
float scaleWidth = ((float) width / w);
float scaleHeight = ((float) height / h);
matrix.postScale(scaleWidth, scaleHeight);// 利用矩阵进行缩放不会造成内存溢出
Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
return newbmp;
}
获取相册路径核心代码:
public static String parsePicturePath(Context context, Uri uri) {
if (null == context || uri == null)
return null;
boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentUri
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageDocumentsUri
if (isExternalStorageDocumentsUri(uri)) {
String docId = DocumentsContract.getDocumentId(uri);
String[] splits = docId.split(":");
String type = splits[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + File.separator + splits[1];
}
}
// DownloadsDocumentsUri
else if (isDownloadsDocumentsUri(uri)) {
String docId = DocumentsContract.getDocumentId(uri);
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
return getDataColumn(context, contentUri, null, null);
}
// MediaDocumentsUri
else if (isMediaDocumentsUri(uri)) {
String docId = DocumentsContract.getDocumentId(uri);
String[] split = docId.split(":");
String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
String selection = "_id=?";
String[] selectionArgs = new String[] {split[1]};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
if (isGooglePhotosContentUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
private static boolean isExternalStorageDocumentsUri(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
private static boolean isDownloadsDocumentsUri(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
private static boolean isMediaDocumentsUri(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
private static boolean isGooglePhotosContentUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
String column = "_data";
String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
try {
if (cursor != null)
cursor.close();
} catch (Exception e) {
Log.e("harvic",e.getMessage());
}
}
return null;
}