关于安卓调用相机有关知识(含6.0新增权限使用)
2016-08-29 10:42
495 查看
一、调用系统相机拍照
拍照和相册的功能在实际开发中是最常见的功能,这里记录下。
准备工作
权限
常量
相机
onActivityResult
拿到cameraPath,就随便你搞了。
相册
onActivityResult
调用系统相册,然后通过Uri拿到图片的绝对地址。
getAbsolutePath方法
二、调用第三方相机进行拍照
1、需要添加调用相机和外部存储的权限
[html] view
plain copy
<span style="font-size:14px;"><uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/></span>
需要注意的是安卓6.0后使用相机等涉及隐私的权限需要在代码内在申明,可通过以下方法:
[java] view
plain copy
<span style="font-size:14px;">if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_JAVA_REQUEST_CODE);
}</span>
2、使用Intent启动第三方相机
可以通过startActivityForResult获取到拍完照片的结果信息。
[java] view
plain copy
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getUri());
startActivityForResult(intent, CAMERA_REQUEST_CODE);
其中需要的到给定一个图片保存的Uri
[java] view
plain copy
private Uri getUri() {
return Uri.fromFile(getFile());
}
/**
* 该方法用于获取指定路径 和 名字 的file
* @return
*/
private File getFile() {
File filePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "CameraDemo");
if (!filePath.exists()) {
filePath.mkdirs();
}
//将图片保存的名字设置为当前拍照的时间
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String name = format.format(new Date());
File file = new File(filePath.getPath() + File.separator + name + ".jpg");
return file;
}
3、重写onActivityResult获取拍照后返回的信息
[java] view
plain copy
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Log.d("print", "拍照成功");
}
}
}
二、使用camera进行拍照
1、需要借助SurfaceView来显示,进行拍照预览。在布局文件中添加SurfaceView。
2、对相应权限进行设置,同调用第三方相机。
3、为SurfaceView设置回调
[java] view
plain copy
sf_camera.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
/**
* 请求权限是一个异步任务 不是立即请求就能得到结果 在结果回调中返回
*/
requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
} else {
//打开相机 前置摄像头
openCamera(front_camera);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//设置相机自动对焦
mcamera.autoFocus(null);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//释放相机资源
if (mcamera != null) {
mcamera.release();
mcamera = null;
}
}
});
其中打开相机的方法
[java] view
plain copy
private void openCamera(int inDex) {
mcamera = Camera.open(inDex);
try {
mcamera.setPreviewDisplay(sf_camera.getHolder());//关联surfaceview,成为相机的预览界面
setCamra();
mcamera.startPreview();//开启预览
mcamera.autoFocus(null);
} catch (IOException e) {
e.printStackTrace();
}
}
3、设置屏幕的分辨率
不同机型的分辨率不同,我们这取最大分辨率进行相机预览
[java] view
plain copy
private void setCamra() {
Camera.Parameters parameters = mcamera.getParameters();
List<Camera.Size> sizeList = parameters.getSupportedPictureSizes();//得到手机支持的图片的尺寸的集合
int size = sizeList.size();
Camera.Size size1 = sizeList.get(0);
Log.d("qf", size1.height + "*" + size1.width + "=" + size1.width * size1.height);
Camera.Size size2 = sizeList.get(size - 1);
Log.d("qf", size2.height + "*" + size2.width + "=" + size2.width * size2.height);
//判断 去最大的尺寸为相机的分辨率
if (size1.height * size1.width > size2.width * size2.height) {
parameters.setPictureSize(size1.height, size1.width);
Log.d("qf", size1.height + "*" + size1.width + "=" + size1.width * size1.height);
} else {
parameters.setPictureSize(size2.height, size2.width);
Log.d("qf", size2.height + "*" + size2.width + "=" + size2.width * size2.height);
}
mcamera.setParameters(parameters);
mcamera.setDisplayOrientation(90);//预览结果屏幕飞正常显示 需要旋转屏幕
}
4、让相机点击屏幕可以进行聚焦,需要为SurfaceView设置触摸监听
[java] view
plain copy
sf_camera.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mcamera.autoFocus(null);
return true;
}
}
5、预览完成,可以进行拍照
调用相机的takePicture的方法进行拍照,拍照返回数据为一个byte数组,可转为bitmap并进行保存。
[java] view
plain copy
private void takePhotos() {
mcamera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap btmap = rotateBitmap(bitmap);//旋转原bitmap得到新的bitmap
savePic(btmap);
bitmap.recycle();//回收原来的bitmap
mcamera.startPreview();
}
});
}
//对bitmap进行旋转
private Bitmap rotateBitmap(Bitmap bitmap) {
Matrix matrix = new Matrix();
matrix.reset();
if (isBack) {
matrix.postRotate(90);//后置摄像头需要进行90度旋转,前置进行-90度旋转
} else {
matrix.postRotate(-90);
}
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
}
6、进行图片保存
[java] view
plain copy
private void savePic(Bitmap bitmap) {
File filePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "CameraDemo");
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String name = format.format(new Date());
File file = new File(filePath.getPath() + File.separator + name + ".jpg");
BufferedOutputStream os;
try {
os = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);//进行图片压缩 保存在file路径下
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(Main2Activity.this, "拍照成功,图片存至" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
}
7、设置一个boolean值记录目前相机是为前置或后置
[java] view
plain copy
boolean isBack = true;//true表示后置
8、得到系统相机的数量和相机信息,进行相机的切换
[java] view
plain copy
private void getCameraId() {
int numberOfCameras = Camera.getNumberOfCameras();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
front_camera = i;
Log.d("print", front_camera + "前");
} else {
back_camera = i;
Log.d("print", back_camera + "后");
}
}
}
在相机切换时需要释放前一个相机
[java] view
plain copy
private void changeCamera() {
if (mcamera != null) {
mcamera.release();
mcamera = null;
}
if (isBack) {
openCamera(front_camera);
isBack = false;
} else {
openCamera(back_camera);
isBack = true;
}
}
这样就可以进行相机的拍照和摄像头的切换了
三、常见问题
由于国内Android机型繁多,各家都自己的rom,调用系统的还是会出现不少问题:
一、拍照照片被旋转
这种情况是使用Camera拍照以后,得到的照片会被自动旋转(90°、180°、270°)。解决方案:
1、读取图片的旋转属性
2、将图片按照某个角度进行旋转
详见博客:https://www.baidufe.com/item/4bb733d9999c53cb8fed.html
二、调用系统相册,拿不到绝对路径
上篇的方法,我在大部分手机测试是可行,但是一些机型还是拿不到,解决方案:
详见stackoverflow:http://stackoverflow.com/questions/13209494/how-to-get-the-full-file-path-from-uri
三、裁剪
拿到图片的绝对路径,有可能需要对它进行裁剪,这里当然也可以调用系统的裁剪,不过我推荐UCrop,功能好强大,简单的使用方法:
详见github:https://github.com/Yalantis/uCrop
拍照和相册的功能在实际开发中是最常见的功能,这里记录下。
准备工作
权限
<!-- 往SDCard写入数据权限 --> <uses-permission android:name="android.permission. WRITE_EXTERNAL_STORAGE" /> <!--请求访问使用照相设备--> <uses-permission android:name="android.permission.CAMERA" />
常量
public final static int ALBUM_REQUEST_CODE = 1; public final static int CROP_REQUEST = 2; public final static int CAMERA_REQUEST_CODE = 3; // 拍照路径 public static String SAVED_IMAGE_DIR_PATH = Environment.getExternalStorageDirectory().getPath() + "/AppName/camera/"; String cameraPath;
相机
// 指定相机拍摄照片保存地址 String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED)) { cameraPath = SAVED_IMAGE_DIR_PATH + System.currentTimeMillis() + ".png"; Intent intent = new Intent(); // 指定开启系统相机的Action intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); String out_file_path = SAVED_IMAGE_DIR_PATH; File dir = new File(out_file_path); if (!dir.exists()) { dir.mkdirs(); } // 把文件地址转换成Uri格式 Uri uri = Uri.fromFile(new File(cameraPath)); // 设置系统相机拍摄照片完成后图片文件的存放地址 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, CAMERA_REQUEST_CODE); } else { Toast.makeText(getApplicationContext(), "请确认已经插入SD卡", Toast.LENGTH_LONG).show(); }
onActivityResult
拿到cameraPath,就随便你搞了。
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { if (requestCode == CAMERA_REQUEST_CODE) { LogUtil.d("path=" + cameraPath); } }
相册
Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(intent, ALBUM_REQUEST_CODE);
onActivityResult
调用系统相册,然后通过Uri拿到图片的绝对地址。
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { if (requestCode == AppConstants.ALBUM_REQUEST_CODE) { try { Uri uri = data.getData(); final String absolutePath= getAbsolutePath(mActivity, uri); ogUtil.d("path=" + absolutePath); } catch (Exception e) { e.printStackTrace(); } } } }
getAbsolutePath方法
public String getAbsolutePath(final Context context, final Uri uri) { if (null == uri) return null; final String scheme = uri.getScheme(); String data = null; if (scheme == null) data = uri.getPath(); else if (ContentResolver.SCHEME_FILE.equals(scheme)) { data = uri.getPath(); } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null); if (null != cursor) { if (cursor.moveToFirst()) { int index = cursor.getColumnIndex( MediaStore.Images.ImageColumns.DATA); if (index > -1) { data = cursor.getString(index); } } cursor.close(); } } return data; }
二、调用第三方相机进行拍照
1、需要添加调用相机和外部存储的权限
[html] view
plain copy
<span style="font-size:14px;"><uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/></span>
需要注意的是安卓6.0后使用相机等涉及隐私的权限需要在代码内在申明,可通过以下方法:
[java] view
plain copy
<span style="font-size:14px;">if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_JAVA_REQUEST_CODE);
}</span>
2、使用Intent启动第三方相机
可以通过startActivityForResult获取到拍完照片的结果信息。
[java] view
plain copy
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getUri());
startActivityForResult(intent, CAMERA_REQUEST_CODE);
其中需要的到给定一个图片保存的Uri
[java] view
plain copy
private Uri getUri() {
return Uri.fromFile(getFile());
}
/**
* 该方法用于获取指定路径 和 名字 的file
* @return
*/
private File getFile() {
File filePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "CameraDemo");
if (!filePath.exists()) {
filePath.mkdirs();
}
//将图片保存的名字设置为当前拍照的时间
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String name = format.format(new Date());
File file = new File(filePath.getPath() + File.separator + name + ".jpg");
return file;
}
3、重写onActivityResult获取拍照后返回的信息
[java] view
plain copy
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Log.d("print", "拍照成功");
}
}
}
二、使用camera进行拍照
1、需要借助SurfaceView来显示,进行拍照预览。在布局文件中添加SurfaceView。
2、对相应权限进行设置,同调用第三方相机。
3、为SurfaceView设置回调
[java] view
plain copy
sf_camera.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
/**
* 请求权限是一个异步任务 不是立即请求就能得到结果 在结果回调中返回
*/
requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
} else {
//打开相机 前置摄像头
openCamera(front_camera);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//设置相机自动对焦
mcamera.autoFocus(null);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//释放相机资源
if (mcamera != null) {
mcamera.release();
mcamera = null;
}
}
});
其中打开相机的方法
[java] view
plain copy
private void openCamera(int inDex) {
mcamera = Camera.open(inDex);
try {
mcamera.setPreviewDisplay(sf_camera.getHolder());//关联surfaceview,成为相机的预览界面
setCamra();
mcamera.startPreview();//开启预览
mcamera.autoFocus(null);
} catch (IOException e) {
e.printStackTrace();
}
}
3、设置屏幕的分辨率
不同机型的分辨率不同,我们这取最大分辨率进行相机预览
[java] view
plain copy
private void setCamra() {
Camera.Parameters parameters = mcamera.getParameters();
List<Camera.Size> sizeList = parameters.getSupportedPictureSizes();//得到手机支持的图片的尺寸的集合
int size = sizeList.size();
Camera.Size size1 = sizeList.get(0);
Log.d("qf", size1.height + "*" + size1.width + "=" + size1.width * size1.height);
Camera.Size size2 = sizeList.get(size - 1);
Log.d("qf", size2.height + "*" + size2.width + "=" + size2.width * size2.height);
//判断 去最大的尺寸为相机的分辨率
if (size1.height * size1.width > size2.width * size2.height) {
parameters.setPictureSize(size1.height, size1.width);
Log.d("qf", size1.height + "*" + size1.width + "=" + size1.width * size1.height);
} else {
parameters.setPictureSize(size2.height, size2.width);
Log.d("qf", size2.height + "*" + size2.width + "=" + size2.width * size2.height);
}
mcamera.setParameters(parameters);
mcamera.setDisplayOrientation(90);//预览结果屏幕飞正常显示 需要旋转屏幕
}
4、让相机点击屏幕可以进行聚焦,需要为SurfaceView设置触摸监听
[java] view
plain copy
sf_camera.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mcamera.autoFocus(null);
return true;
}
}
5、预览完成,可以进行拍照
调用相机的takePicture的方法进行拍照,拍照返回数据为一个byte数组,可转为bitmap并进行保存。
[java] view
plain copy
private void takePhotos() {
mcamera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap btmap = rotateBitmap(bitmap);//旋转原bitmap得到新的bitmap
savePic(btmap);
bitmap.recycle();//回收原来的bitmap
mcamera.startPreview();
}
});
}
//对bitmap进行旋转
private Bitmap rotateBitmap(Bitmap bitmap) {
Matrix matrix = new Matrix();
matrix.reset();
if (isBack) {
matrix.postRotate(90);//后置摄像头需要进行90度旋转,前置进行-90度旋转
} else {
matrix.postRotate(-90);
}
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
}
6、进行图片保存
[java] view
plain copy
private void savePic(Bitmap bitmap) {
File filePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "CameraDemo");
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String name = format.format(new Date());
File file = new File(filePath.getPath() + File.separator + name + ".jpg");
BufferedOutputStream os;
try {
os = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);//进行图片压缩 保存在file路径下
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(Main2Activity.this, "拍照成功,图片存至" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
}
7、设置一个boolean值记录目前相机是为前置或后置
[java] view
plain copy
boolean isBack = true;//true表示后置
8、得到系统相机的数量和相机信息,进行相机的切换
[java] view
plain copy
private void getCameraId() {
int numberOfCameras = Camera.getNumberOfCameras();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
front_camera = i;
Log.d("print", front_camera + "前");
} else {
back_camera = i;
Log.d("print", back_camera + "后");
}
}
}
在相机切换时需要释放前一个相机
[java] view
plain copy
private void changeCamera() {
if (mcamera != null) {
mcamera.release();
mcamera = null;
}
if (isBack) {
openCamera(front_camera);
isBack = false;
} else {
openCamera(back_camera);
isBack = true;
}
}
这样就可以进行相机的拍照和摄像头的切换了
三、常见问题
由于国内Android机型繁多,各家都自己的rom,调用系统的还是会出现不少问题:
一、拍照照片被旋转
这种情况是使用Camera拍照以后,得到的照片会被自动旋转(90°、180°、270°)。解决方案:
1、读取图片的旋转属性
/** * 读取图片的旋转的角度 * * @param path * 图片绝对路径 * @return 图片的旋转角度 */ private int getBitmapDegree(String path) { int degree = 0; try { // 从指定路径下读取图片,并获取其EXIF信息 ExifInterface exifInterface = new ExifInterface(path); // 获取图片的旋转信息 int orientation = exifInterface. getAttributeInt(ExifInterface. TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; }
2、将图片按照某个角度进行旋转
/** * 将图片按照某个角度进行旋转 * * @param bm * 需要旋转的图片 * @param degree * 旋转角度 * @return 旋转后的图片 */public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) { Bitmap returnBm = null; // 根据旋转角度,生成旋转矩阵 Matrix matrix = new Matrix(); matrix.postRotate(degree); try { // 将原始图片按照旋转矩阵进行旋转,并得到新的图片 returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); } catch (OutOfMemoryError e) { } if (returnBm == null) { returnBm = bm; } if (bm != returnBm) { bm.recycle(); } return returnBm; }
详见博客:https://www.baidufe.com/item/4bb733d9999c53cb8fed.html
二、调用系统相册,拿不到绝对路径
上篇的方法,我在大部分手机测试是可行,但是一些机型还是拿不到,解决方案:
public class AbsolutePathUtil { public static String getAbsolutePath(final Context context , final Uri uri) { // DocumentProvider if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract .getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } // TODO handle non-primary volumes } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { final String docId = DocumentsContract .getDocumentId(uri); final String[] split = docId.split(":"); final 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; } final String selection = "_id=?"; final String[] selectionArgs = new String[]{ split[1] }; return getDataColumn(context, contentUri , selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @param selection (Optional) Filter used in the query. * @param selectionArgs (Optional) Selection arguments used in the query. * @return The value of the _data column, which is typically a file path. */ public static String getDataColumn(Context context , Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = "_data"; final String[] projection = { column }; try { cursor = context.getContentResolver() .query(uri, projection, selection, selectionArgs,null); if (cursor != null && cursor.moveToFirst()) { final int column_index = cursor .getColumnIndexOrThrow(column); return cursor.getString(column_index); } } finally { if (cursor != null) cursor.close(); } return null; } /** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents" .equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */ public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents" .equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is MediaProvider. */ public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents" .equals(uri.getAuthority()); } }
详见stackoverflow:http://stackoverflow.com/questions/13209494/how-to-get-the-full-file-path-from-uri
三、裁剪
拿到图片的绝对路径,有可能需要对它进行裁剪,这里当然也可以调用系统的裁剪,不过我推荐UCrop,功能好强大,简单的使用方法:
/** * 启动裁剪 */ public static String startUCrop(Activity activity, String sourceFilePath, int requestCode, float aspectRatioX, float aspectRatioY) { Uri sourceUri = Uri.fromFile(new File(sourceFilePath)); File outDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES); if (!outDir.exists()) { outDir.mkdirs(); } File outFile = new File(outDir, System.currentTimeMillis() + ".jpg"); String cameraScalePath = outFile.getAbsolutePath(); Uri destinationUri = Uri.fromFile(outFile); UCrop uCrop = UCrop.of(sourceUri, destinationUri); UCrop.Options options = new UCrop.Options(); options.setAllowedGestures(UCropActivity.SCALE, UCropActivity.ROTATE, UCropActivity.ALL); options.setHideBottomControls(true); options.setFreeStyleCropEnabled(true); uCrop.withOptions(options); uCrop.withAspectRatio(aspectRatioX, aspectRatioY); uCrop.start(activity, requestCode); return cameraScalePath; }
详见github:https://github.com/Yalantis/uCrop
相关文章推荐
- 关于安卓调用相机有关知识(含6.0新增权限使用)
- 关于Android 6.0 调用 要求使用权限代码报红色问题
- 关于Android6.0/7.0权限,以及7.0调用相机和切图的解决办法
- 关于安卓调用C#的WebService上传图片问题(不使用ksoap2)
- android 6.0 动态申请权限后 相机的使用核心方法
- 关于android安卓的wifi功能使用需要申请的权限和管理类
- 安卓开发_关于WebView使用链接时调用浏览器显示的问题
- 菜鸟笔记2、Android6.0版本,关于调用系统相机的使用和图片保存
- Android 拍照以及一些常用的处理,例如将图片显示到相册(包含了安卓系统6.0以上调用相机的处理)
- Android 6.0动态权限调用相册相机
- 关于小米4 以及酷派手机安卓开发 调用相机相册适配的问题
- 关于对话框的知识(函数的调用机制和控件的使用)
- 以调用系统相机拍照为例了解Android 6.0运行时权限
- 关于input在苹果和安卓手机上调用相机和相册的问题
- 关于使用安卓系统自带的相机进行拍照,把照片存到系统图库gallery中
- Android 6.0 动态权限实战(二 - 终结章 - 高手必看!)------ 关于动态权限的正确使用与理解
- 关于imageloader的使用以及调用系统相机相片 三星手机上的旋转90度解决
- 使用input type=file标签进行文件上传时,在安卓手机中的微信浏览器中不能调起相机,但是在苹果手机中的微信浏览器中可以调用相机。解决办法很简单, <input type="file" nam
- 关于安卓调用C#的WebService上传图片问题(不使用ksoap2)
- Android调用系统相机、相册功能,适配6.0权限获取以及7.0以后获取URI(兼容多版本)