兼容android 11 唤起系统相机拍照并显示
兼容android 11 唤起系统相机拍照并显示(建议大家从android 10开始适配,我就遇到了部分android 10手机也出现这个问题)
本文是记录兼容android 11的唤起系统相机拍照并正常显示,此处我默认已经获取到相机和读写的权限。
打开相机
/*** 保存 photoUri*/private Uri photoUri;/*** 打开相机*/private void openCamera() {Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//确保有相机来处理Intentif (takePictureIntent.resolveActivity(getPackageManager()) != null) {File photoFile = saveFileName();if (photoFile != null) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//适配Android 7.0文件权限,通过FileProvider创建一个content类型的UriphotoUri = FileProvider.getUriForFile(getApplicationContext(), "com.stg.rouge.activity.fileprovider", photoFile);} else {photoUri = getDestinationUri();}takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);startActivityForResult(takePictureIntent, 10086);}}}/*** 获取 Uri* @return*/private Uri getDestinationUri(){String fileName = String.format("winetalk_%s.jpg", System.currentTimeMillis());File cropFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName);return Uri.fromFile(cropFile);}//当前路径,拍照回调后需要使用private String currentPath=null;/*** 保存照片路径* @return*/private File saveFileName(){File newFolder = this.getExternalFilesDir(Environment.DIRECTORY_PICTURES);SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");Date date = new Date(System.currentTimeMillis());String name =format.format(date)+".jpg" ;File ji=null;try {ji=new File(newFolder+"/"+name);ji.createNewFile();currentPath = ji.getAbsolutePath();} catch (Exception e) {e.printStackTrace();}return ji;}
记住,配置文件的写法:
<providerandroid:name="androidx.core.content.FileProvider"android:authorities="com.stg.rouge.activity.fileprovider"android:exported="false"android:grantUriPermissions="true"tools:replace="android:authorities"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths_public"tools:replace="android:resource" /></provider>
而res/xml/file_paths_public文件中要添加如下路径:
<external-path name="external_files" path="." />
拍照后的回调
@SuppressWarnings("unchecked")@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);G.look("onActivityResult!!!!!!");switch (requestCode) {case 10086:G.look("10086");if (G.isEmpty(currentPath)) {G.toast(context, "拍照失败");return;}if (resultCode == RESULT_OK) {G.look("currentPath=" + currentPath);// String filepath = PhotoBitmapUtils.amendRotatePhoto// (currentPhotoPath, this);try {File file1=null;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { //兼容android 11,不然在android 11 上无法拿到图片file1 = new Compressor(this).setCompressFormat(Bitmap.CompressFormat.JPEG).setDestinationDirectoryPath(C.getDownloadPath(context)).compressToFile(currentPath);}else {file1 = new Compressor(this).setCompressFormat(Bitmap.CompressFormat.JPEG).setDestinationDirectoryPath(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()).compressToFile(currentPath);}String absolutePath = file1.getAbsolutePath(); //我这里需要的是拍照后照片的路径,至于大家是否需要别的,反正都有了file,可以自己转换。//下面这是我自己项目的东西,大家没有必要细究ImageInfoBean bean = new ImageInfoBean();bean.path = absolutePath;if (!G.isListNullOrEmpty(chooseimages)){chooseimages.add(bean);}else {chooseimages = new ArrayList<>();chooseimages.add(bean);}setImageList();} catch (IOException e) {G.look("IOException: "+e.toString());e.printStackTrace();}}break;}}
/*** 公共方法,兼容android 11* 存储路径* @param context* @return*/public static String getDownloadPath(Context context) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { //android 11return Constants.SDCardConstants.getDir(context) + File.separator;}else {return Environment.getExternalStorageDirectory() + "/winetalk/";}}
Constants工具类
public class Constants {/*** 文件存储相关常量*/public static class SDCardConstants {private static final String TAG = "SDCardConstants";/*** 转码文件后缀*/public final static String TRANSCODE_SUFFIX = ".mp4_transcode";/*** 裁剪文件后缀*/public final static String CROP_SUFFIX = "-crop.mp4";/*** 合成文件后缀*/public final static String COMPOSE_SUFFIX = "-compose.mp4";/*** 裁剪 & 录制 & 转码输出文件的目录* android Q 版本默认路径* /storage/emulated/0/Android/data/包名/files/Media/* android Q 以下版本默认"/sdcard/DCIM/Camera/"*/public static String getDir(Context context) {String dir;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {dir = context.getExternalFilesDir("") + File.separator + "Media" + File.separator;} else {dir = Environment.getExternalStorageDirectory() + File.separator + "DCIM"+ File.separator + "Camera" + File.separator;}File file = new File(dir);if (!file.exists()) {//noinspection ResultOfMethodCallIgnoredfile.mkdirs();}return dir;}/*** 获取外部缓存目录 版本默认"/storage/emulated/0/Android/data/包名/file/Cache/svideo"** @param context Context* @return string path*/public static String getCacheDir(Context context) {File cacheDir = new File(context.getExternalCacheDir(), "svideo");if (!cacheDir.exists()) {cacheDir.mkdirs();}return cacheDir.exists() ? cacheDir.getPath() : "";}/*** 清空外部缓存目录文件 "/storage/emulated/0/Android/data/包名/file/Cache/svideo"** @param context Context*/public static void clearCacheDir(Context context) {final File cacheDir = new File(context.getExternalCacheDir(), "svideo");ThreadUtils.runOnSubThread(new Runnable() {@Overridepublic void run() {boolean b = deleteFile(cacheDir);Log.i(TAG, "delete cache file " + b);}});}/*** 递归删除文件/目录* @param file File*/private static boolean deleteFile(File file) {if (file == null || !file.exists()) {return true;}if (file.isDirectory()) {File[] files = file.listFiles();if (files == null) {return true;}for (File f : files) {deleteFile(f);}}return file.delete();}}
}
Compressor工具类
public class Compressor {//max width and height values of the compressed image is taken as 612x816private int maxWidth = 612;private int maxHeight = 816; //缩放比例,亲测不失真private Bitmap.CompressFormat compressFormat = Bitmap.CompressFormat.JPEG;private int quality = 90;private String destinationDirectoryPath;public Compressor(Context context) {destinationDirectoryPath = context.getCacheDir().getPath() + File.pathSeparator + "Compressor";}public Compressor setMaxWidth(int maxWidth) {this.maxWidth = maxWidth;return this;}public Compressor setMaxHeight(int maxHeight) {this.maxHeight = maxHeight;return this;}public Compressor setCompressFormat(Bitmap.CompressFormat compressFormat) {this.compressFormat = compressFormat;return this;}public Compressor setQuality(int quality) {this.quality = quality;return this;}public Compressor setDestinationDirectoryPath(String destinationDirectoryPath) {this.destinationDirectoryPath = destinationDirectoryPath;return this;}public File compressToFile(File imageFile) throws IOException {return compressToFile(imageFile, imageFile.getName());}public File compressToFile(File imageFile, String compressedFileName) throws IOException {return ImageUtil.compressImage(imageFile, maxWidth, maxHeight, compressFormat, quality,destinationDirectoryPath + File.pathSeparator + compressedFileName);}public File compressToFile(String imageFile,File file, String compressedFileName) throws IOException {return ImageUtil.compressImage(imageFile,file, maxWidth, maxHeight, compressFormat, quality,destinationDirectoryPath + File.pathSeparator + compressedFileName);}public File compressToFile(String imageFile) throws IOException {File file = new File(imageFile);return compressToFile(imageFile,file, file.getName());}public Bitmap compressToBitmap(File imageFile) {return ImageUtil.decodeSampledBitmapFromFile(imageFile, maxWidth, maxHeight);}
}
ImageUtil工具类
class ImageUtil {private ImageUtil() {}static File compressImage(File imageFile, int reqWidth, int reqHeight, Bitmap.CompressFormat compressFormat, int quality, String destinationPath) throws IOException {FileOutputStream fileOutputStream = null;try {fileOutputStream = new FileOutputStream(destinationPath);// write the compressed bitmap at the destination specified by destinationPath.Bitmap bitmap = decodeSampledBitmapFromFile(imageFile, reqWidth, reqHeight);bitmap.compress(compressFormat, quality, fileOutputStream);} finally {if (fileOutputStream != null) {fileOutputStream.flush();fileOutputStream.close();}}return new File(destinationPath);}static File compressImage(String path,File imageFile, int reqWidth, int reqHeight, Bitmap.CompressFormat compressFormat, int quality, String destinationPath) throws IOException {FileOutputStream fileOutputStream = null;// 取得图片旋转角度int angle = readPictureDegree(path);try {fileOutputStream = new FileOutputStream(destinationPath);// write the compressed bitmap at the destination specified by destinationPath.
// Bitmap bitmap = decodeSampledBitmapFromFile(imageFile, reqWidth, reqHeight);// 修复图片被旋转的角度Bitmap bitmap = rotaingImageView(angle, decodeSampledBitmapFromFile(imageFile, reqWidth, reqHeight));bitmap.compress(compressFormat, quality, fileOutputStream);} finally {if (fileOutputStream != null) {fileOutputStream.flush();fileOutputStream.close();}}return new File(destinationPath);}/*** 读取照片旋转角度** @param path 照片路径* @return 角度*/public static int readPictureDegree(String path) {int degree = 0;try {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;}/*** 旋转图片* @param angle 被旋转角度* @param bitmap 图片对象* @return 旋转后的图片*/public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {Bitmap returnBm = null;// 根据旋转角度,生成旋转矩阵Matrix matrix = new Matrix();matrix.postRotate(angle);try {// 将原始图片按照旋转矩阵进行旋转,并得到新的图片returnBm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);} catch (OutOfMemoryError e) {}if (returnBm == null) {returnBm = bitmap;}if (bitmap != returnBm) {bitmap.recycle();}return returnBm;}static Bitmap decodeSampledBitmapFromFile(File imageFile, int reqWidth, int reqHeight) {// First decode with inJustDecodeBounds=true to check dimensionsBitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);options.inPreferredConfig = Bitmap.Config.RGB_565;// Calculate inSampleSizeoptions.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);// Decode bitmap with inSampleSize setoptions.inJustDecodeBounds = false;return BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);}private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {// Raw height and width of imagefinal int height = options.outHeight;final int width = options.outWidth;int inSampleSize = 1;if (height > reqHeight || width > reqWidth) {final int halfHeight = height / 2;final int halfWidth = width / 2;// Calculate the largest inSampleSize value that is a power of 2 and keeps both// height and width larger than the requested height and width.while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {inSampleSize *= 2;}}return inSampleSize;}}
兼容android 11 唤起系统相机拍照并显示相关推荐
- Android 调起系统相机拍照
概述 比奇小说网 m.biqi.org 最近在看 nanChen 写的图片选择器 ImagePicker,感觉写得很不错,也打算把从中学到的东西写下来.很多时候,遇到一个好的框架能够降低开发成本这是好 ...
- android代码调用相机,Android如何调用系统相机拍照
本文实例为大家分享了Android调用系统相机拍照的具体代码,供大家参考,具体内容如下 /** * 调用系统相机 */ private void takePhoto() { Uri uri = nul ...
- Android手机调用系统相机拍照、裁剪以及获取Url上传图片
前言 最近一个人在公司搞独立开发,遇到问题只能自己解决,虽然过程比较坎坷,但是收获还是颇多的,一个人也是要坚强滴,最近弄用户的头像遇到了一些小问题,虽然上一款应用有头像上传,但是发现了其中的一些小问题 ...
- 安卓调用系统相机拍照并且显示在ImageView上
并没有什么技术难点,只是在保存到sdCard的时候有一点小细节需要注意,所以写了这篇文章.代码很简单,就不解释什么了,直接贴上源码. public class TakePhotoActivity ex ...
- android 相机拍照返回,Android6.0机型上调用系统相机拍照返回的resultCode值始终等于0的问题...
版权声明:本文为博主原创文章,未经博主允许不得转载. 正常情况下调用系统相机拍照: 如果拍照后点击的是"确定"图标,返回的resultCode = -1(Activity.RESU ...
- Android开发 调用系统相机相册图片功能,解决小米手机拍照或者图片横竖相反问题,及小米手机相册图片路径问题
Android开发 调用系统相机相册图片功能,解决小米手机拍照或者图片横竖相反问题,及小米手机相册图片路径问题 1.调用相机,兼容7.0 AndroidManifest配置 <providera ...
- android 调用系统相机拍照 获取原图
博客源址:android 调用系统相机拍照 获取原图 博客时间:2013-04-23 11:08 好吧,为了这个问题又折腾了一整天.之前在网上找来的方法,如果在onActivityResult中直接用 ...
- Android多层嵌套Fragment中调用系统相机拍照以及裁剪的相关问题解决
多层嵌套Fragment中调用系统相机拍照.裁剪 最近公司项目有频繁使用相机拍照的需求,然后频繁的实际使用过程中遇到很多大大小小的坑,在此记录下. (ps.关于一些拍照后图片旋转.裁剪设置返回数据为t ...
- Android调用系统相机拍照并保存到指定位置
Android调用系统相机拍照并保存到指定位置 @Click(R.id.btn_takePhoto)void onclick() {Intent intent = new Intent(MediaSt ...
- android固定位置拍照,Android调用系统相机拍照并保存到指定位置
Android调用系统相机拍照并保存到指定位置 @Click(R.id.btn_takePhoto) void onclick() { Intent intent = new Intent(Media ...
最新文章
- ArcGIS API for JavaScript4.x 之加载2D、3D地图
- [ webpack4 ] 配置属于自己的打包系统教程(最终篇)—— 环境配置篇
- 接上一篇Ansible和celery的结合,在celery的tasks.py文件里为了实现并发不阻塞的需求,用到了多进程
- QT文件日志系统(可选择出到文件,数据库,或者网络传输)
- Android JNI开发生成.h头文件问题(转)
- man hdparm
- windows程序设计基础知识
- java安装包的大概组成部分
- KL散度 JS散度 熵
- zabbix 利用脚本发邮件(mail)
- TIM下载的文件在哪个手机文件夹中(安卓)
- 用Prolog解决爱因斯坦斑马问题
- 电脑键盘equals在哪个位置_【电脑键盘在哪里调出来】电脑键盘在哪里找_电脑模拟键盘在哪里...
- 邮件群发软件使用攻略
- 打造一款可靠的WAF(Web应用防火墙)
- 联想服务器CPU系列,联想推出采用第三代英特尔至强处理器的ThinkSystem SR860 V2服务器...
- 信创引领丨呼叫中心加速适配国产化
- 2019年最新出搜索引擎蜘蛛网页爬虫大全
- mos管的rc吸收电路计算_正激式RC吸收电路计算
- Dubbo官方入门实例
热门文章
- c语言从键盘输入圆柱体的半径和高,c 写程序:输入圆柱的半径和高,计算并输出圆柱体的体积和表面积...
- css鼠标移入变成小手
- 如何用php建立图库,教你搭建自己的图片库
- SQL 日期交差判断
- 异数OS 织梦师-纤手(二)-- LPC RPC篇
- Rayman的绝顶之路——Leetcode每日一题打卡19
- Unstoppable Domains域名使用教程(区块链域名)
- 2021年系统架构设计师考试上午真题与答案
- omnet++tictoc12案例解析
- 基于steamworks获取steam用户头像