android7.0 拍照以及图片剪辑--(再次修改)
如果你是在fragment里头调用的拍照,出了bug 可以查看 这篇文章 点我 不懂的可以留言。
这篇博客对于7.0的版本的修改。主要是在文件存储的处理。
6.0、8.0版本使用本文的存储文件会出现 java.io.FileNotFoundException: No such file or directory 找不到文件夹
至于怎么做版本适配大家可以度娘一下,我这个问题往后我处理好放在博客给大家看看还有什么不足的,还请指点。
本次修改的地方是使用了第三方的截图开源框架 uCrop,解决了一些机型剪辑图片时gg了。原因一个就是,Android自带的截图有点坑啊(应该是我用不好的原因)毕竟别人的框架也是基于系统的所提供嘛。
这边先说明一下uCrop的使用,再往下看就是拍照功能的实现
1、添加依赖走起 -->app.gradle
implementation 'com.yalantis:ucrop:1.4.1'
-->build.gradle (Project)
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" } //添加的是这句
}
}
2、申请activity,这个并不是说你自己去创建一个,你看清楚他的包名,uCrop是作者的喔。
<activity android:name="com.yalantis.ucrop.UCropActivity" android:screenOrientation="portrait" android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
3、开搞啦。这里直接使用代码就可以,截图跳转到UCropActivity
UCrop uCrop = UCrop.of(uri, cropUri); //第一参数是处理图片你的文件的路径,第二个参数就是存放剪辑后的路径 UCrop.Options options = new UCrop.Options(); //设置裁剪图片可操作的手势 options.setAllowedGestures(UCropActivity.SCALE, UCropActivity.ROTATE, UCropActivity.ALL); //是否隐藏底部容器,默认显示 options.setHideBottomControls(true); //设置toolbar颜色 options.setToolbarColor(ActivityCompat.getColor(activity, R.color.colorPrimary)); //设置状态栏颜色 options.setStatusBarColor(ActivityCompat.getColor(activity, R.color.colorPrimary)); // //是否能调整裁剪框 // options.setShowCropFrame(true); options.setCompressionFormat(Bitmap.CompressFormat.JPEG); //UCrop配置 //设置裁剪图片的宽高比,比如1:1 你自己随意 uCrop.withAspectRatio(1, 1); uCrop.withMaxResultSize(250,250); uCrop.withOptions(options); //uCrop.useSourceImageAspectRatio(); //跳转裁剪页面 uCrop.start(getContext(),this,CODE_RESULT_REQUEST); //start 方法中提供几种方式 也就是说你在fragment、activity 都可以使用,其中fragment也做了一个适配 你在fragment中调用也没有问题的。 参数使用的话,点击去看一下源码就知道怎么用了。
4、看下uCrop的效果
旋转
5、截图后的显示
然后进入我们的主题。
//拍照 private void showCamera() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, REQUEST_CAMERA); }
//保存图片路径 private void saveUrl() { file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/test/" + System.currentTimeMillis() + ".jpg"); file.getParentFile().mkdirs(); uri = FileProvider.getUriForFile(this, "com.example.cnb.cemera.fileprovider", file); }
//权限申请以及开启 下面有一段新的权限申请,至于版本适配大家还是得自己去写 public void applyWritePermission() { String[] permissions = {android.Manifest.permission.WRITE_EXTERNAL_STORAGE}; if (Build.VERSION.SDK_INT >= 23) { int check = ContextCompat.checkSelfPermission(this, permissions[0]); // 权限是否已经 授权 GRANTED---授权 DINIED---拒绝 if (check == PackageManager.PERMISSION_GRANTED) { //调用相机 showPhoto(); } else { requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } } else { showPhoto(); } }
//这一段新的权限申请/** /** * * @param selectFun 请求码,对应的功能,拍照 || 图库选取 */ public void applyWriteAndReadPermission(int selectFun) { if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { //如果灭有权限 ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA}, selectFun); //requestCode } else { showPhoto(); } }
//权限返回 @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { showPhoto(); } else { // 没有获取 到权限,从新请求,或者关闭app Toast.makeText(this, "需要存储权限", Toast.LENGTH_SHORT).show(); } }
//activity返回 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CAMERA && resultCode == RESULT_OK) { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); Uri contentUri = Uri.fromFile(file); mediaScanIntent.setData(contentUri); sendBroadcast(mediaScanIntent); String path = this.getExternalCacheDir().getPath(); cropRawPhoto(uri); } else if (requestCode == CODE_RESULT_REQUEST) { //在手机相册中显示刚拍摄的图片 if (data == null) { return; } Bundle extras = data.getExtras(); if (extras != null) { bm = extras.getParcelable("data"); } // sendImage(bm); img.setImageBitmap(bm); } }
//裁剪图片 使用第三方框架uCrop 进行编辑, public void cropRawPhoto(Uri uri) { //这个uri是拍照后保存下来的图片文件路径 Log.e("url", uri + "-------"); File cropFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/test/crop_" + System.currentTimeMillis() + ".jpg"); cropFile.getParentFile().mkdirs(); Uri cropUri = FileProvider.getUriForFile(getContext(), "com.example.cnb.superschool.fileprovider", cropFile); UCrop uCrop = UCrop.of(uri, cropUri); UCrop.Options options = new UCrop.Options(); //设置裁剪图片可操作的手势 options.setAllowedGestures(UCropActivity.SCALE, UCropActivity.ROTATE, UCropActivity.ALL); //是否隐藏底部容器,默认显示 options.setHideBottomControls(true); //设置toolbar颜色 options.setToolbarColor(ActivityCompat.getColor(activity, R.color.colorPrimary)); //设置状态栏颜色 options.setStatusBarColor(ActivityCompat.getColor(activity, R.color.colorPrimary)); // //是否能调整裁剪框 // options.setShowCropFrame(true); options.setCompressionFormat(Bitmap.CompressFormat.JPEG); //UCrop配置 //设置裁剪图片的宽高比,比如1:1 你自己随意 uCrop.withAspectRatio(1, 1); uCrop.withMaxResultSize(250, 250); uCrop.withOptions(options); //uCrop.useSourceImageAspectRatio(); //跳转裁剪页面 uCrop.start(getContext(), this, CODE_RESULT_REQUEST); }
//裁剪图片 系统自带的图片剪辑 public void cropRawPhoto(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 200); intent.putExtra("outputY", 200); intent.putExtra("return-data", true); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); startActivityForResult(intent, CODE_RESULT_REQUEST); }
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.example.cnb.cemera.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths"/> </provider>
<?xml version="1.0" encoding="utf-8"?> <resources>
<external-path name="external_files" path="." /></resources>
复制以上的代码一般就可以运行了啦。
捋一捋处理思路
首先android6.0 以上 都需要 权限申请,
如果权限已经开启,那么执行拍照功能。否则判断用户是否要开启该权限
开启/关闭 权限都后会有一个权限返回结果,那么,返回中去判断权限是否开启,开启则进行拍照
接着,拍照功能开启,确定后保存图片路径,返回到onActivityResult 根据requestCode 来判定
是哪一个功能的返回,在判断为拍照功能里头添加剪辑。
最后轮到剪辑功能,跳转到剪辑页面,需要的设置他们的参数,也就是截取的比例,完成后返回到onActivityResult
判断是不是剪辑功能的返回值,设置图片显示。
这个图片显示需要转换成bitmap,获取data之后转成bitmap
Bundle extras = data.getExtras(); if (extras != null) { bm = extras.getParcelable("data"); }
img.setImageBitmap(bm)
android7.0以后 需要通过获取路径来获取图片。
新建一个xml文件夹,然后新建一个xml文件,名字随意。可以返回上面代码看一下