您的位置:首页 > 移动开发

Android webview 关于拍照上传图片的解决方法

2017-03-19 12:46 686 查看
本文地址:https://my.oschina.net/zengliubao/blog/862161

演示Demo中assets 目录内置了index.html 和JSbridge.js 来演示, this.goWebView("http://my.oschina.net/zengliubao/blog/file:/android_asset/index.html") 来启动吧!Demo演示请点击这里



Android 开发实在要考虑太多的因素,webview 就像IE6时代的产物,甚至JS 注入的惊天漏洞也有过呢,而且这部分设备永远得不到更新,炸弹一直没法拆除。

看很多朋友在实际的项目开发中遇到webview 拍照上传图片遇到的坑,最多的是webview 无法处理 type =file标签导致无法上传图片(重写onOpenFile 不会回调);当然我们项目由于业务的关系遇到一个更加麻烦的事情,低内存状态从拍照返回来页面被销毁重置了。

Android 4.X 无法处理Type=file 的标记.

这个问题在很多的Android 4.X 都是必现的,那年项目上有人因为无法拍照没法接单,直接买了一部新手机把问题手机给我们了,感动ING;这也导致你针对不同的版本Webview重写了onOpenFile 仍然无法达到完美的解决方案的时候你会很难过。

最终我们的解决方案是iOS 的仍然处理type=file 标签,Android 全部通过Jsbridge 调用Native 把照片bitmap 通过Base64编码回传给JS,param.content = "data:image/jpg;base64," + Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT),忙完这阵,我会把Demo上传到Github。

#低内存状态从拍照返回来页面被销毁重置了



上面的图使我们的业务相关的web 页面,如果前面几个步骤都做好了,最后去拍照的正准备去按下快门来了个电话,接着回复了一下微信,这个过程在一些低端的红米和魅族等手机(没有批判,国产的很多低端机都这样)返回来拍照返回数据的时候,发起拍照的那个含有webview 的页面一闪---onCreate了,全面填写的内容没有了,这又要让用户去操作填写一遍数据!尝试过onSavewInstance ,webview.storeInstance等方法看能不能恢复(对webkie内核不是非常的熟悉,去stackoverflow 看的),然而我没有恢复内容,多么的悲伤!

那么为什么会出现这种情况呢?

当某个 app 通过 intent 调用进入相机拍照界面时,系统会把这个 app 当做是后台进程,后台进程优先级是比较低的,当内存不足的时候就被销毁了,等重新回来拍完照回到这个app 的时候会恢复这个app 的进程页面数据等。

原生的控件的一些编辑的数据能在onSaveInstance 中保存起来,webview 中的页面也可以缓存,但是编辑中的那些数据能吗?我没有找到方法。我的做法简单粗暴,提高app 进程的优先级,启动前台Servie 以及 不要让我们的app变成后台进程,自定义相机不要用系统相机(新的App会让调用app 变为后台进程)

最重要的,Webview 所在的Activity配置成在一个新的独立进程中会很好的解决很多的问题-OOM 内存泄露等!

#拍的照片被旋转了?
这个经常出现在三星的手机中,拍好的照片导入电脑查看也是旋转度数的!我们读取的时候需要旋转处理一下

/**
* 获取图片的旋转角度
*
* @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;
}

Bitmap 过大?

这个网上很多的解决方法。

#没有系统相机可以使用?
前几天因为推送的问题设置天池优化,然而360 手机竟然竟然发送intent 请求电池优化的时候闪退了;系统相机会不会也被切除了,修改了,Android 奇葩事情无所不有。

虽然很极端,但作为客户端人员还是要进行处理,方式有二:

调用相机时,简单粗暴的 try-catch

调用相机前,检测系统有没有相机 app 可用
try-catch 这种粗暴的方式大家肯定很熟悉了,那么要如何检测系统有没有相机 app 可用呢?系统在 PackageManager 里为我们提供这样一个 API:queryIntentActivities通过这样一个 API ,可以知道系统是否存在 action 为 MediaStore.ACTION_IMAGE_CAPTURE 的 intent 可以唤起的拍照界面,具体实现代码如下:

public boolean hasCamera() {
PackageManager packageManager = mActivity.getPackageManager();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
List list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}

准备整理一下写一个关于Jsbridge 总结的文章和Demo放到github

http://blog.csdn.net/sk719887916/article/details/52402470
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐