Android调用系统相机、图库、裁剪图片并压缩上传(适配7.0)
来源:互联网 发布:网络中的信息交流方式 编辑:程序博客网 时间:2024/05/17 20:34
一、前言
最近在开发中遇到了一个比较棘手的问题
由于在之前使用的版本-targetSdkVersion小于24也就是小于7.0所以在使用相机拍照的时候不会出现问题,但是当targetSdkVersion版本大于或者等于7.0的时候用原来的方法调用相机就会抛出一个SecurityException安全异常
通过搜索发现是出于对系统安全的考虑,在sdk24及以上,对相机的操作需要使用FileProvider才行。
虽然有些麻烦,但除非用第三方框架,不然也只能自己动手去解决了。
二、操作流程
1、定义全局标识
用于接收图库选择或拍照完成后的结果回调
//图库 private static final int PHOTO_TK = 0; //拍照 private static final int PHOTO_PZ = 1; //裁剪 private static final int PHOTO_CLIP = 2;
定义全局的uri
private Uri contentUri;
2、图库操作
这里用的是一个自定义的dialog
update_dialog_TK.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //调用系统图库,选择图片 Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType( MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*"); //返回结果和标识 startActivityForResult(intent, PHOTO_TK); dialog.dismiss(); } });
3、相机操作
3.1 Android7.0以下版本
直接调用系统相机,通过日志可以看到会返回一个类似
的文件
file:///storage/emulated/0/temp.jpg
update_dialog_PZ.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 启动系统相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 获取拍完后的uri Uri mImageCaptureUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "temp.jpg")); intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageCaptureUri); // 返回结果和标识 startActivityForResult(intent, PHOTO_PZ); dialog.dismiss(); } });
3.2 兼容Android7.0以上版本
在新的版本中,Android对内容提供者做了限制,返回的不再是uri,而需要一个FileProvider
使用 content://
代替了 file:///
所以如果直接使用原来的方法就会报错。
所以在之前我们要给AndroidManifest文件中application标签添加权限
<provider android:name="android.support.v4.content.FileProvider" android:authorities="你的包名.fileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider>
并且需要创建一个xml
(可以在上面android:resource="@xml/provider_paths"
直接使用快捷键alt+enter创建,然后将代码拷贝进去)
external-path标签用来指定Uri共享,name属性的值可以自定义,path属性的值表示共享的具体位置
<paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external_files" path="."/></paths>
然后在调用系统相机的时候判断
update_dialog_PZ.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 启动系统相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri mImageCaptureUri; // 判断7.0android系统 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //临时添加一个拍照权限 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //通过FileProvider获取uri contentUri = FileProvider.getUriForFile(UpdatePhotoActivity.this, "你的包名.fileProvider", new File(Environment.getExternalStorageDirectory(), "temp.jpg")); intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri); } else { mImageCaptureUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "temp.jpg")); intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageCaptureUri); } startActivityForResult(intent, PHOTO_PZ); dialog.dismiss(); } });
4、 onActivityResult
使用onActivityResult接收操作完成的回调
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { switch (requestCode) { case PHOTO_PZ: //获取拍照结果,执行裁剪 Uri pictur; //如果是7.0android系统,直接获取uri if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { pictur = contentUri; } else { pictur = Uri.fromFile(new File( Environment.getExternalStorageDirectory() + "/temp.jpg")); } startPhotoZoom(pictur); break; case PHOTO_TK: //获取图库结果,执行裁剪 startPhotoZoom(data.getData()); break; case PHOTO_CLIP: //裁剪完成后的操作,上传至服务器或者本地设置 break; } } }
5、裁剪
当拍照完成后或者本地选择图片完毕之后会执行该方法。同时也做了7.0适配
/** * 裁剪图片的方法. * 用于拍照完成或者选择本地图片之后 */ private Uri uritempFile; public void startPhotoZoom(Uri uri) { Log.e("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", 60); intent.putExtra("outputY", 60); //uritempFile为Uri类变量,实例化uritempFile if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //开启临时权限 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); //重点:针对7.0以上的操作 intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, uri)); uritempFile = uri; } else { uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "small.jpg"); } intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile); intent.putExtra("return-data", false); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); startActivityForResult(intent, PHOTO_CLIP); }
三、裁剪后的处理
在onActivityResult方法还有一个最后的处理,前面只是在给图片做操作,下面是将完成后的图片选择加载到本地或者上传到项目的服务端,一般在实际开发中用的比较多
1、加载至本地
使用Picasso加载,因为Picasso支持Uri、File、Stirng类型,不需要做进一步的转换就可以直接用。
Picasso.with(this) .load(uritempFile) .into(cardviewImg);
2、转成File并压缩、上传
在实际开发中有时候需要对图片进行进一步的处理,比如传到服务器需要File类型的文件,所以就需要进行再一次的转换。
具体可以根据需求来进行相应的操作
//裁剪后的图像转成BitMap photo1 = BitmapFactory.decodeStream(getContentResolver().openInputStream(uritempFile)); //创建路径 String path = Environment.getExternalStorageDirectory() .getPath() + "/Pic"; //获取外部储存目录 file = new File(path); Log.e("file", file.getPath()); //创建新目录 file.mkdirs(); //以当前时间重新命名文件 long i = System.currentTimeMillis(); //生成新的文件 file = new File(file.toString() + "/" + i + ".png"); Log.e("fileNew", file.getPath()); //创建输出流 OutputStream out = new FileOutputStream(file.getPath()); //压缩文件,返回结果 boolean flag = photo1.compress(Bitmap.CompressFormat.JPEG, 100, out);
项目demo地址:https://github.com/wapchief/android-CollectionDemo
- Android调用系统相机、图库、裁剪图片并压缩上传(适配7.0)
- Android调用系统相机、图库、裁剪图片并压缩上传(适配7.0)
- Android调用系统图库和相机获取图片并裁剪
- (复习)android 调用系统相机 图库 裁剪-图片上传-客服端-服务器
- Android调用系统图库并裁剪图片
- Android调用系统图库并裁剪图片
- Android:调用系统相机 图库 裁剪-图片上传-客服端-服务器
- Android 调用系统相机、图库 ,取图片并裁剪、保存sd卡
- Android调用系统的相机,图库,以及裁剪图片功能。
- Android 调用系统相机和图库,裁剪图片
- 调用系统相机和图库,裁剪图片
- Android 调用相机或图库,裁剪图片
- 调用系统相机、图库并选择图片
- Android:调用系统图库/裁剪图片
- Android 打开相机和图库获取图片并裁剪
- android调用系统相机拍照并裁剪
- Android 调用系统相机拍照(适配7.0)、从图库选择图片;从数据库读取联系人信息、相册图片
- Android调用相机拍照并返回路径和调用系统图库选择图片
- 怎么使用hibernate 查询
- 最实用的 Linux 命令行使用技巧
- MySQL百万级、千万级数据多表关联SQL语句调优
- Hello world
- ButterKnife使用详解
- Android调用系统相机、图库、裁剪图片并压缩上传(适配7.0)
- 斐波那契数
- shell中执行mysql命令
- MySQL笔记
- 背包问题——0-1背包
- bzoj 1611: [Usaco2008 Feb]Meteor Shower流星雨
- 求字符串中的,最长不重复子串--java代码
- HDU --- 5703 Desert 水题【找规律】
- 扫地机器人排行榜