- 浏览: 2213536 次
- 性别:
- 来自: 北京
-
文章分类
- 全部博客 (1240)
- mac/IOS (287)
- flutter (1)
- J2EE (115)
- android基础知识 (582)
- android中级知识 (55)
- android组件(Widget)开发 (18)
- android 错误 (21)
- javascript (18)
- linux (70)
- 树莓派 (18)
- gwt/gxt (1)
- 工具(IDE)/包(jar) (18)
- web前端 (17)
- java 算法 (8)
- 其它 (5)
- chrome (7)
- 数据库 (8)
- 经济/金融 (0)
- english (2)
- HTML5 (7)
- 网络安全 (14)
- 设计欣赏/设计窗 (8)
- 汇编/C (8)
- 工具类 (4)
- 游戏 (5)
- 开发频道 (5)
- Android OpenGL (1)
- 科学 (4)
- 运维 (0)
- 好东西 (6)
- 美食 (1)
最新评论
-
liangzai_cool:
请教一下,文中,shell、C、Python三种方式控制led ...
树莓派 - MAX7219 -
jiazimo:
...
Kafka源码分析-序列5 -Producer -RecordAccumulator队列分析 -
hp321:
Windows该命令是不是需要安装什么软件才可以?我试过不行( ...
ImageIO读jpg的时候出现javax.imageio.IIOException: Unsupported Image Type -
hp321:
Chenzh_758 写道其实直接用一下代码就可以解决了:JP ...
ImageIO读jpg的时候出现javax.imageio.IIOException: Unsupported Image Type -
huanghonhpeng:
大哥你真强什么都会,研究研究。。。。小弟在这里学到了很多知识。 ...
android 浏览器
说起调用系统相机来拍照的功能,大家肯定不陌生,现在所有应用都具备这个功能。例如最基本的,用户拍照上传头像。Android开发的孩纸都知道,碎片化给拍照这个功能的实现带来挺多头疼的问题。所以,我决定写写一些网上不多见但又经常听到童鞋们吐槽的问题。
拍照功能实现
Android 程序上实现拍照功能的方式分为两种:第一种是利用相机的 API 来自定义相机,第二种是利用 Intent 调用系统指定的相机拍照。下面讲的内容都是针对第二种实现方式的适配。
通常情况下,我们调用拍照的业务场景是如下面这样的:
1.A 界面,点击按钮调用相机拍照;
2.A 界面得到拍完照片,跳转到 B 界面进行预览;
3.B 界面有个按钮,点击后触发某个业务流程来处理这张照片;
实现的大体流程代码如下:
到这里基本科普完了如何调用系统相机拍照,相信这些网上一搜一大把的代码,很多童鞋都能看懂。
有没有相机可用?
前面讲到我们是调用系统指定的相机App来拍照,那么系统是否存在可以被我们调用的App呢?这个我们不敢确定,毕竟 Android 奇葩问题多,还真有遇到过这种极端的情况导致闪退的。虽然很极端,但作为客户端人员还是要进行处理,方式有二:
try-catch 这种粗暴的方式大家肯定很熟悉了,那么要如何检测系统有没有相机 App 可用呢?系统在 PackageManager 里为我们提供这样一个 API。
通过这样一个 API ,可以知道系统是否存在 action 为 MediaStore.ACTION_IMAGE_CAPTURE 的 intent 可以唤起的拍照界面,具体实现代码如下:
拍出来的照片“歪了”!!!
经常会遇到一种情况,拍照时看到照片是正的,但是当我们的 App 获取到这张照片时,却发现旋转了 90° (也有可能是 180°、270°,不过 90° 比较多见,貌似都是由于手机传感器导致的)。很多童鞋对此感到很困扰,因为不是所有手机都会出现这种情况,就算会是出现这种情况的手机上,也并非每次必现。要怎么解决这个问题呢?从解决的思路上看,只要获取到照片旋转的角度,利用 Matrix 来进行角度纠正即可。那么问题来了,要怎么知道照片旋转的角度呢? 细心的童鞋可能会发现,拍完一张照片去到相册点击属性查看,能看到下面这样一堆关于照片的属性数据。
没错,这里面就有一个旋转角度,倘若拍照后保存的成像照片文件发生了角度旋转,这个图片的属性参数就能告诉我们到底旋转了多少度。只要获取到这个角度值,我们就能进行纠正的工作了。 Android 系统提供了 ExifInterface 类来满足获取图片各个属性的操作。
通过ExifInterface类拿到 TAG_ORIENTATION 属性对应的值,即为我们想要得到旋转角度。再根据利用 Matrix 进行旋转纠正即可。实现代码大致如下:
ExifInterface 能拿到的信息远远不止旋转角度,其他的参数感兴趣的童鞋可以看看 API 文档。
拍完照怎么闪退了?
曾在小米和魅族的某些机型上遇到过这样的问题,调用系统相机拍照,拍完点击确定回到自己的App里面却莫名奇妙的闪退了。这种闪退有两个特点:
1.没有什么错误日志(有些机子啥日志都没有,有些机子会出来个空异常错误日志);
2.同个机子上非必现(有时候怎么拍都不闪退,有时候一拍就闪退)。
对待非必现问题往往比较头疼,当初遇到这样的问题也是非常不解。上网搜罗了一圈也没方案,后来留意到一个比较有意思信息:有些系统厂商的 ROM 会给自带相机应用做优化,当某个 App 通过 intent 进入相机拍照界面时,系统会把这个 App 当前最上层的 Activity 销毁回收。(注意:我遇到的情况是有时候很快就回收掉,有时候怎么等也不回收,没有什么必现规律)为了验证一下,便在启动相机的 Activity 中对 onDestory 方法进行加 log 。果不其然,终于发现进入拍照界面的时候 onDestory 方法被执行了。所以,前面提到的闪退基本可以推测是 Activity 被回收导致某些非UI控件的成员变量为空导致的。(有些机子会报出空异常错误日志,但是有些机子闪退了什么都不报,是不是觉得很奇葩!)
既然涉及到 Activity 被回收的问题,自然要想起 onSaveInstanceState 和 onRestoreInstanceState 这对方法。去到 onSaveInstanceState 把数据保存,并在 onRestoreInstanceState 方法中进行恢复即可。大体代码思路如下:
对于 onSaveInstanceState 和 onRestoreInstanceState 方法的作用还不熟悉的童鞋,网上资料很多,可以自行搜索。
到这里,可能有童鞋要问,这种闪退并不能保证复现,我要怎么知道问题所在和是否修复了呢?我们可以去到开发者选项里开启不保留活动这一项进行调试验证。
它作用是保留当前和用户接触的 Activity ,并将目前无法和用户交互 Activity 进行销毁回收。打开这个调试选项就可以满足验证的需求,当你的 App 的某个 Activity 跳转到拍照的 Activity 后,这个 Activity 立马就会被系统销毁回收,这样就可以很好的完全复现闪退的场景,帮助开发者确认问题有没有修复了。
涉及到 Activity 被销毁,还想提一下代码实现上的问题。假设当前有两个 Activity ,MainActivity 中有个 Button ,点击可以调用系统相机拍照并显示到 PreviewActivity 进行预览。有下面两种实现方案:
上面两种方案得到的实现效果是一模一样的,但是第二种方案却存在很大的问题。因为启动相机的代码放在 onCreate(或者onStart、onResume)中,当进入拍照界面后,PreviewActivity 随即被销毁,拍完照确认后回到 PreviewActivity 时,被销毁的 PreviewActivity 需要重建,又要走一遍 onCreate、onStart、onResume,又调用了启动相机拍照的代码,周而复始的进入了死循环状态。为了避免让你的用户抓狂,果断明智的选择方案一。
以上这种情况提到调用系统拍照时,Activity就回收的情况,在小米4S和小米4 LTE机子上(MIUI的版本是7.3,Android系统版本是6.0)出现的概率很高。所以,建议看到此文的童鞋也可以去验证适配一下。
图片无法显示
图片无法显示这个问题也是略坑,如何坑法?往下看,同样是在小米4S和小米4 LTE机子上(MIUI的版本是7.3,Android系统版本是6.0)出现概率很高的场景(当然,不保证其他机子没出现过)。按照我们前面提到的业务场景,调用相机拍照完成后,我们的 App 会有一个预览图片的界面。但是在用了小米的机子进行拍照后,自己 App 的预览界面却怎么也无法显示出照片来,同样是相当郁闷,郁闷完后还是要一步一步去排查解决问题的!为此,需要一步一步猜测验证问题所在。
猜测一:没有拿到照片路径,所以无法显示?
直接断点打 log 跟踪,猜测一很快被推翻,路径是有的。
猜测二:Bitmap太大了,无法显示?
直接在AS的log控制台仔细的观察了一下系统 log ,发现了一些蛛丝马迹。
每次拍完照片,都会出现上面这样的 log ,果然,因为图片太大而导致在 ImageView 上无法显示。到这里有童鞋要吐槽了,没对图片的采样率 inSampleSize 做处理?天地良心啊,绝对做处理了,直接看代码:
运行打印出来的日志如下:
图片原来的宽高居然都是 -1 ,真是奇葩了!难怪,inSampleSize 经过处理之后结果还是 1 。狠狠的吐槽了之后,总是要回来解决问题的。那么,图片的宽高信息都丢失了,我去哪里找啊? 像下面这样?
no,此方案行不通,inJustDecodeBounds = true 时,BitmapFactory 获得 Bitmap 对象是 null;那要怎样才能获图片的宽高呢?前面提到的 ExifInterface 再次帮了我们大忙,通过它的下面两个属性即可拿到图片真正的宽高。
顺手吐槽一下,为什么高不是 TAG_IMAGE_HEIGHT 而是 TAG_IMAGE_LENGTH。改良过后的代码实现如下:
再看一下,打印出来的log。
这样就可以解决问题啦。
总结
以上总结了这么些身边童鞋经常问起,但网上又不多见的适配问题,希望可以帮到一些开发童鞋少走弯路。文中多次提到小米的机子,并不代表只有MIUI上有这样的问题存在,仅仅只是因为我身边带的几部机子大都是小米的。对待适配问题,在搜索引擎都无法提供多少有效的信息时,我们只能靠断点、打log、观察控制台的日志、以及API文档来寻找一些蛛丝马迹作为突破口,相信办法总比困难多。
以上的示例代码已经整理到:https://github.com/D-clock/AndroidStudyCode ,主要的代码在下面红圈部分。
感兴趣的童鞋可以自行查看!如有错误,欢迎大家指正!
拍照功能实现
Android 程序上实现拍照功能的方式分为两种:第一种是利用相机的 API 来自定义相机,第二种是利用 Intent 调用系统指定的相机拍照。下面讲的内容都是针对第二种实现方式的适配。
通常情况下,我们调用拍照的业务场景是如下面这样的:
1.A 界面,点击按钮调用相机拍照;
2.A 界面得到拍完照片,跳转到 B 界面进行预览;
3.B 界面有个按钮,点击后触发某个业务流程来处理这张照片;
实现的大体流程代码如下:
//1. 调用相机 File mPhotoFile = new File(folder,filename); Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri fileUri = Uri.fromFile(mPhotoFile); captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); mActivity.startActivityForResult(captureIntent, CAPTURE_PHOTO_REQUEST_CODE); //2. 拿到照片 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CapturePhotoHelper.CAPTURE_PHOTO_REQUEST_CODE && resultCode == RESULT_OK) { File photoFile = mCapturePhotoHelper.getPhoto();//获取拍完的照片 if (photoFile != null) { PhotoPreviewActivity.preview(this, photoFile);//跳转到预览界面 } finish(); } else { super.onActivityResult(requestCode, resultCode, data); } } //3. 各种各样处理这张图片的业务代码
到这里基本科普完了如何调用系统相机拍照,相信这些网上一搜一大把的代码,很多童鞋都能看懂。
有没有相机可用?
前面讲到我们是调用系统指定的相机App来拍照,那么系统是否存在可以被我们调用的App呢?这个我们不敢确定,毕竟 Android 奇葩问题多,还真有遇到过这种极端的情况导致闪退的。虽然很极端,但作为客户端人员还是要进行处理,方式有二:
- 调用相机时,简单粗暴的 try-catch;
- 调用相机前,检测系统有没有相机 App 可用;
try-catch 这种粗暴的方式大家肯定很熟悉了,那么要如何检测系统有没有相机 App 可用呢?系统在 PackageManager 里为我们提供这样一个 API。

通过这样一个 API ,可以知道系统是否存在 action 为 MediaStore.ACTION_IMAGE_CAPTURE 的 intent 可以唤起的拍照界面,具体实现代码如下:
/** * 判断系统中是否存在可以启动的相机应用 * * @return 存在返回true,不存在返回false */ public boolean hasCamera() { PackageManager packageManager = mActivity.getPackageManager(); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); return list.size() > 0; }
拍出来的照片“歪了”!!!
经常会遇到一种情况,拍照时看到照片是正的,但是当我们的 App 获取到这张照片时,却发现旋转了 90° (也有可能是 180°、270°,不过 90° 比较多见,貌似都是由于手机传感器导致的)。很多童鞋对此感到很困扰,因为不是所有手机都会出现这种情况,就算会是出现这种情况的手机上,也并非每次必现。要怎么解决这个问题呢?从解决的思路上看,只要获取到照片旋转的角度,利用 Matrix 来进行角度纠正即可。那么问题来了,要怎么知道照片旋转的角度呢? 细心的童鞋可能会发现,拍完一张照片去到相册点击属性查看,能看到下面这样一堆关于照片的属性数据。

没错,这里面就有一个旋转角度,倘若拍照后保存的成像照片文件发生了角度旋转,这个图片的属性参数就能告诉我们到底旋转了多少度。只要获取到这个角度值,我们就能进行纠正的工作了。 Android 系统提供了 ExifInterface 类来满足获取图片各个属性的操作。

通过ExifInterface类拿到 TAG_ORIENTATION 属性对应的值,即为我们想要得到旋转角度。再根据利用 Matrix 进行旋转纠正即可。实现代码大致如下:
/** * 获取图片的旋转角度 * * @param path 图片绝对路径 * @return 图片的旋转角度 */ public static 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; } /** * 将图片按照指定的角度进行旋转 * * @param bitmap 需要旋转的图片 * @param degree 指定的旋转角度 * @return 旋转后的图片 */ public static Bitmap rotateBitmapByDegree(Bitmap bitmap, int degree) { // 根据旋转角度,生成旋转矩阵 Matrix matrix = new Matrix(); matrix.postRotate(degree); // 将原始图片按照旋转矩阵进行旋转,并得到新的图片 Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); } return newBitmap; }
ExifInterface 能拿到的信息远远不止旋转角度,其他的参数感兴趣的童鞋可以看看 API 文档。
拍完照怎么闪退了?
曾在小米和魅族的某些机型上遇到过这样的问题,调用系统相机拍照,拍完点击确定回到自己的App里面却莫名奇妙的闪退了。这种闪退有两个特点:
1.没有什么错误日志(有些机子啥日志都没有,有些机子会出来个空异常错误日志);
2.同个机子上非必现(有时候怎么拍都不闪退,有时候一拍就闪退)。
对待非必现问题往往比较头疼,当初遇到这样的问题也是非常不解。上网搜罗了一圈也没方案,后来留意到一个比较有意思信息:有些系统厂商的 ROM 会给自带相机应用做优化,当某个 App 通过 intent 进入相机拍照界面时,系统会把这个 App 当前最上层的 Activity 销毁回收。(注意:我遇到的情况是有时候很快就回收掉,有时候怎么等也不回收,没有什么必现规律)为了验证一下,便在启动相机的 Activity 中对 onDestory 方法进行加 log 。果不其然,终于发现进入拍照界面的时候 onDestory 方法被执行了。所以,前面提到的闪退基本可以推测是 Activity 被回收导致某些非UI控件的成员变量为空导致的。(有些机子会报出空异常错误日志,但是有些机子闪退了什么都不报,是不是觉得很奇葩!)
既然涉及到 Activity 被回收的问题,自然要想起 onSaveInstanceState 和 onRestoreInstanceState 这对方法。去到 onSaveInstanceState 把数据保存,并在 onRestoreInstanceState 方法中进行恢复即可。大体代码思路如下:
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mRestorePhotoFile = mCapturePhotoHelper.getPhoto(); if (mRestorePhotoFile != null) { outState.putSerializable(EXTRA_RESTORE_PHOTO, mRestorePhotoFile); } } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mRestorePhotoFile = (File) savedInstanceState.getSerializable(EXTRA_RESTORE_PHOTO); mCapturePhotoHelper.setPhoto(mRestorePhotoFile); }
对于 onSaveInstanceState 和 onRestoreInstanceState 方法的作用还不熟悉的童鞋,网上资料很多,可以自行搜索。
到这里,可能有童鞋要问,这种闪退并不能保证复现,我要怎么知道问题所在和是否修复了呢?我们可以去到开发者选项里开启不保留活动这一项进行调试验证。

它作用是保留当前和用户接触的 Activity ,并将目前无法和用户交互 Activity 进行销毁回收。打开这个调试选项就可以满足验证的需求,当你的 App 的某个 Activity 跳转到拍照的 Activity 后,这个 Activity 立马就会被系统销毁回收,这样就可以很好的完全复现闪退的场景,帮助开发者确认问题有没有修复了。
涉及到 Activity 被销毁,还想提一下代码实现上的问题。假设当前有两个 Activity ,MainActivity 中有个 Button ,点击可以调用系统相机拍照并显示到 PreviewActivity 进行预览。有下面两种实现方案:
- 方案一:MainActivity 中点击 Button 后,启动系统相机拍照,并在 MainActivity 的 onActivityResult 方法中获取拍下来的照片,并启动跳转到 PreviewActivity 界面进行效果预览;
- 方案二:MainActivity 中点击 Button 后,启动 PreviewActivity 界面,在 PreviewActivity 的 onCreate(或者onStart、onResume)方法中启动系统相机拍照,然后在 PreviewActivity 的 onActivityResult 方法中获取拍下来的照片进行预览。
上面两种方案得到的实现效果是一模一样的,但是第二种方案却存在很大的问题。因为启动相机的代码放在 onCreate(或者onStart、onResume)中,当进入拍照界面后,PreviewActivity 随即被销毁,拍完照确认后回到 PreviewActivity 时,被销毁的 PreviewActivity 需要重建,又要走一遍 onCreate、onStart、onResume,又调用了启动相机拍照的代码,周而复始的进入了死循环状态。为了避免让你的用户抓狂,果断明智的选择方案一。
以上这种情况提到调用系统拍照时,Activity就回收的情况,在小米4S和小米4 LTE机子上(MIUI的版本是7.3,Android系统版本是6.0)出现的概率很高。所以,建议看到此文的童鞋也可以去验证适配一下。
图片无法显示
图片无法显示这个问题也是略坑,如何坑法?往下看,同样是在小米4S和小米4 LTE机子上(MIUI的版本是7.3,Android系统版本是6.0)出现概率很高的场景(当然,不保证其他机子没出现过)。按照我们前面提到的业务场景,调用相机拍照完成后,我们的 App 会有一个预览图片的界面。但是在用了小米的机子进行拍照后,自己 App 的预览界面却怎么也无法显示出照片来,同样是相当郁闷,郁闷完后还是要一步一步去排查解决问题的!为此,需要一步一步猜测验证问题所在。
猜测一:没有拿到照片路径,所以无法显示?
直接断点打 log 跟踪,猜测一很快被推翻,路径是有的。
猜测二:Bitmap太大了,无法显示?
直接在AS的log控制台仔细的观察了一下系统 log ,发现了一些蛛丝马迹。

引用
OpenGLRenderer: Bitmap too large to be uploaded into a texture
每次拍完照片,都会出现上面这样的 log ,果然,因为图片太大而导致在 ImageView 上无法显示。到这里有童鞋要吐槽了,没对图片的采样率 inSampleSize 做处理?天地良心啊,绝对做处理了,直接看代码:
/** * 压缩Bitmap的大小 * * @param imagePath 图片文件路径 * @param requestWidth 压缩到想要的宽度 * @param requestHeight 压缩到想要的高度 * @return */ public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) { if (!TextUtils.isEmpty(imagePath)) { if (requestWidth <= 0 || requestHeight <= 0) { Bitmap bitmap = BitmapFactory.decodeFile(imagePath); return bitmap; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高 BitmapFactory.decodeFile(imagePath, options); options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //计算获取新的采样率 options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(imagePath, options); } else { return null; } } public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; Log.i(TAG, "height: " + height); Log.i(TAG, "width: " + width); if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } long totalPixels = width * height / inSampleSize; final long totalReqPixelsCap = reqWidth * reqHeight * 2; while (totalPixels > totalReqPixelsCap) { inSampleSize *= 2; totalPixels /= 2; } } return inSampleSize; }
运行打印出来的日志如下:

图片原来的宽高居然都是 -1 ,真是奇葩了!难怪,inSampleSize 经过处理之后结果还是 1 。狠狠的吐槽了之后,总是要回来解决问题的。那么,图片的宽高信息都丢失了,我去哪里找啊? 像下面这样?
public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) { ... BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高 Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options); bitmap.getWidth(); bitmap.getHeight(); ... } else { return null; } }
no,此方案行不通,inJustDecodeBounds = true 时,BitmapFactory 获得 Bitmap 对象是 null;那要怎样才能获图片的宽高呢?前面提到的 ExifInterface 再次帮了我们大忙,通过它的下面两个属性即可拿到图片真正的宽高。

顺手吐槽一下,为什么高不是 TAG_IMAGE_HEIGHT 而是 TAG_IMAGE_LENGTH。改良过后的代码实现如下:
public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) { if (!TextUtils.isEmpty(imagePath)) { Log.i(TAG, "requestWidth: " + requestWidth); Log.i(TAG, "requestHeight: " + requestHeight); if (requestWidth <= 0 || requestHeight <= 0) { Bitmap bitmap = BitmapFactory.decodeFile(imagePath); return bitmap; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true;//不加载图片到内存,仅获得图片宽高 BitmapFactory.decodeFile(imagePath, options); Log.i(TAG, "original height: " + options.outHeight); Log.i(TAG, "original width: " + options.outWidth); if (options.outHeight == -1 || options.outWidth == -1) { try { ExifInterface exifInterface = new ExifInterface(imagePath); int height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的高度 int width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的宽度 Log.i(TAG, "exif height: " + height); Log.i(TAG, "exif width: " + width); options.outWidth = width; options.outHeight = height; } catch (IOException e) { e.printStackTrace(); } } options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //计算获取新的采样率 Log.i(TAG, "inSampleSize: " + options.inSampleSize); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(imagePath, options); } else { return null; } }
再看一下,打印出来的log。

这样就可以解决问题啦。
总结
以上总结了这么些身边童鞋经常问起,但网上又不多见的适配问题,希望可以帮到一些开发童鞋少走弯路。文中多次提到小米的机子,并不代表只有MIUI上有这样的问题存在,仅仅只是因为我身边带的几部机子大都是小米的。对待适配问题,在搜索引擎都无法提供多少有效的信息时,我们只能靠断点、打log、观察控制台的日志、以及API文档来寻找一些蛛丝马迹作为突破口,相信办法总比困难多。
以上的示例代码已经整理到:https://github.com/D-clock/AndroidStudyCode ,主要的代码在下面红圈部分。

感兴趣的童鞋可以自行查看!如有错误,欢迎大家指正!
发表评论
-
带你深入理解 FLUTTER 中的字体“冷”知识
2020-08-10 23:40 651本篇将带你深入理解 Flutter 开发过程中关于字体和文 ... -
Flutter -自定义日历组件
2020-03-01 17:56 1122颜色文件和屏幕适配的文件 可以自己给定 import ... -
Dart高级(一)——泛型与Json To Bean
2020-02-23 19:13 1019从 Flutter 发布到现在, 越来越多人开始尝试使用 Da ... -
flutter loading、Progress进度条
2020-02-21 17:03 1194Flutter Progress 1 条形无固定值进度条 ... -
Flutter使用Https加载图片
2020-02-21 01:39 1039Flutter使用Https加载图片 使用http加载图片出 ... -
flutter shared_preferences 异步变同步
2020-02-21 00:55 857前言 引用 在开发原生iOS或Native应用时,一般有判断上 ... -
Flutter TextField边框颜色
2020-02-19 21:31 951监听要销毁 myController.dispose(); T ... -
flutter Future的正确用法
2020-02-18 21:55 813在flutter中经常会用到异步任务,dart中异步任务异步处 ... -
记一次Flutter简单粗暴处理HTTPS证书检验方法
2020-02-18 14:13 997最近在做Flutter项目到了遇到一个无解的事情,当使用Ima ... -
flutter 获取屏幕宽度高度 通知栏高度等屏幕信息
2019-07-27 08:39 1358##MediaQuery MediaQuery.of(con ... -
关于flutter RefreshIndicator扩展listview下拉刷新的问题
2019-07-10 19:40 1154当条目过少时listview某些嵌套情况下可能不会滚动(条目 ... -
flutter listview 改变状态的时候一直无限添加
2019-07-10 16:01 810setstate的时候会一直无限的调用listview.bui ... -
Flutter Android端启动白屏问题的解决
2019-07-09 00:51 1541问题描述 Flutter 应用在 Android 端上启动时 ... -
Flutter中SnackBar使用
2019-07-08 23:43 796底部弹出,然后在指定时间后消失。 注意: build(Bui ... -
Flutter 之点击空白区域收起键盘
2019-07-08 18:43 1801点击空白处取消TextField焦点这个需求是非常简单的,在学 ... -
Flutter 弹窗 Dialog ,AlertDialog,IOS风格
2019-07-08 18:04 1397import 'package:flutter/mate ... -
flutter ---TextField 之 输入类型、长度限制
2019-07-08 14:30 2354TextField想要实现输入类型、长度限制需要先引入impo ... -
【flutter 溢出BUG】键盘上显示bottom overflowed by 104 PIXELS
2019-07-08 11:13 1593一开始直接使用Scaffold布局,body:new Colu ... -
解决Flutter项目卡在Initializing gradle...界面的问题
2019-07-07 12:53 896Flutter最近很火,我抽出了一点时间对Flutter进行了 ... -
关于android O 上 NotificationChannel 的一些注意事项
2019-07-04 11:47 951最近在适配android O,遇到个问题,应用中原本有设置界面 ...
相关推荐
综上所述,实现Android 7.0和6.0的拍照适配及头像上传功能,涉及权限管理、启动相机、处理图片、裁剪、上传等多个环节,需要充分理解和运用Android的相关API,并注重用户体验和兼容性。项目中的`PhotoTest`可能包含...
适配方案需要考虑到这些差异,提供兼容性的代码来避免`FileNotFoundException`。 3. **工具类的使用**:为了方便判断当前手机是否为小米设备以及其系统版本,方案中可能会包含一个工具类。这个工具类通常包含检查...
在本文中,我们将详细探讨如何实现这一功能,并讨论在Android 7.0上可能遇到的问题和解决方案。 首先,让我们来了解如何在Android应用中实现多图选择。这通常需要自定义一个图片选择器,可以是基于系统相册的API,...
总之,`android 6.0 权限适配工具`,尤其是`easypermissions`库,为开发者提供了一个方便的解决方案,使得在Android 6.0及更高版本中管理运行时权限变得更加简单。通过学习和使用这个库,开发者可以更好地遵循最新的...
这个“android封装的拍照和选择图片上传”项目,旨在提供一个通用且高度适配的解决方案,使得开发者能够轻松地在各种Android设备上实现这些功能,而无需编写大量的自定义代码。以下是关于这个项目的一些关键知识点和...
在Android开发中,Camera模块是应用最多的硬件接口之一,它允许...这一过程不仅需要扎实的理论基础,还需要丰富的实践经验,因为每个硬件平台和操作系统版本可能都有细微的差异,需要开发者进行细致的调整和适配。
本节我们将探讨一个轻量级的Android原生图片选择拍照第三方库——TakePhoto,它能够简化这些操作,提供易用且高效的解决方案。 TakePhoto是一个针对Android平台设计的开源库,主要功能包括图片选择和拍照,同时也...
在Android平台上实现静默拍照是一项常见的需求,尤其是在自动化测试、安全监控...在Android 8.0及更高版本,由于系统的限制,静默拍照可能需要更复杂的解决方案,如使用MediaRecorder或者依赖于系统服务的间接方式。
在Android开发中,图片选择和拍照是常见的功能需求,尤其对于社交、相册类应用更是不可或缺。...对于需要在应用中集成图片选择和拍照功能的开发者来说,PhotoPicker无疑是一个值得尝试的优秀解决方案。
总的来说,解决Android 7.0拍照裁剪的兼容性问题需要理解系统的变化,采用适当的API和第三方库,处理好权限问题,并进行充分的设备适配测试。通过这些步骤,你的应用就能在不同Android版本上提供一致的用户体验。
在Android 7.0系统中,开发者们在处理拍照和图片裁剪时会遇到一些适配问题,主要是由于系统安全性的提升导致File Uri的使用受到限制。本文将深入探讨这些问题并提供解决方案。 首先,让我们了解两个关键概念:File ...
在Android开发中,"android拍照截图相册上传"是一个常见的需求,它涵盖了多个关键知识点,包括用户界面交互、多媒体处理以及网络通信。本实例提供的`PhotoCropper-master`压缩包可能是一个完整的解决方案,包含了...
开发者需要适配不同的Android版本,因为不同版本的API对文件选取的支持可能有所不同。例如,对于早期版本,可能需要使用ACTION_GET_CONTENT,而在KitKat及以上版本,可以使用DocumentsUI API来获取更广泛的文件访问...
综上所述,实现Android拍照上传图片功能需要涵盖权限管理、相机启动、图片捕获、裁剪处理、网络上传等多个技术环节,并注重用户体验和兼容性。每个环节都有其特定的挑战和解决方案,理解并熟练掌握这些知识点是构建...
解决这个问题花了很长时间搜索了解,网上大部分使用openFileChooser但都没解决一个存在的问题。...这篇文章是为了记录这一点,为验证整个流程部署了后端,但是由于很久没接触后端,后端...单纯的说下Android端的解决方案。
对于这种情况,你需要对不同设备和Android版本进行充分的测试,找出问题并寻找解决方案,如适配不同的硬件特性或使用特定的API版本。 9. **优化性能** 为了确保录像的稳定性和效率,你可以考虑调整摄像头的参数,...
因此,在Android 2.2上实现录屏可能需要第三方库或者自定义解决方案,这通常会比较复杂且不推荐。 在压缩包中的`JavaApk源码说明.txt`文件可能会包含有关如何理解和使用这些Demo的详细信息,它可能是对源码的解释和...
总的来说,Android开发中的二维码横竖屏适配和拍照预览图像的处理需要对Android生命周期、布局适配、相机API有深入理解。通过合理的设计和编程,我们可以确保用户在任何屏幕方向下都能获得良好的扫描体验。
在Android应用开发中,处理图片是一项常见的任务,无论是用户上传、选择、裁剪还是预览。...不过,由于不包含图片预览时的手势放大缩小功能,开发者可能需要寻找其他解决方案或者自行实现这一特性。
这个"Android 拍照与录像切换UI源码"提供了一种解决方案。本文将深入解析相关知识点,帮助你理解和构建类似的系统。 1. **Android多媒体框架**: Android系统提供了丰富的多媒体框架,包括Camera API(分为Camera1...