正 文:
最近飘易在做一个Android下的所见即所得的编辑器,思路是利用内置浏览器webview的
html5属性contenteditable来实现,如:
<div id='con' class='con' contenteditable='true'>请输入内容</div>。
在实际应用过程中,由于需要插入图片,所以要支持利用摄像头拍照和从图库中的相册选择图片的功能。从图库选图没有任何问题,但是拍照的时候,在小米的miui系统下就出现了其他机型没有出现的bug。
我们先来看代码,先写调用camera的代码:
camera_picname="camera.jpg"; //照片名称
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory()+defaultdir, camera_picname)));
startActivityForResult(intent, 10);
注意,这里我们使用了
startActivityForResult,表明需要返回结果。
然后需要重写当前activity的 onActivityResult 方法:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 10 && resultCode == Activity.RESULT_OK) { /*拍照*/
String imgpath = new File(Environment.getExternalStorageDirectory()+defaultdir, camera_picname).getAbsolutePath();
try {
Thread.sleep(500); //延时毫秒 等待 WebView.loadUrl 异步执行完毕
} catch (InterruptedException e) {
e.printStackTrace();
}
mWebView.loadUrl("javascript:window.appendcon('"+imgpath+"');");
}
}
另外,为了防止在调用相机的时候,当前activity被系统kill(比如内存不够时,系统会自动销毁非可见的处于onPause或onStop状态的activity),我们需要 覆写 onSaveInstanceState方法,保存当前activity的状态变量值。
/*保存界面状态,如果activity意外被系统killed,返回时可以恢复状态值*/
@Override
public void onSaveInstanceState(Bundle savedInstanceState){
savedInstanceState.putString("msg_con", htmlsource);
savedInstanceState.putString("msg_camera_picname", camera_picname);
super.onSaveInstanceState(savedInstanceState); //实现父类方法 放在最后 防止拍照后无法返回当前activity
}
然后在 onCreate(Bundle savedInstanceState) 方法里,判断savedInstanceState是否为null,不是null则读取上次保存的临时变量值。
上面的整个流程在模拟器里和其他型号的android真机设备里都没有问题,唯独红米的手机有问题!出现这个问题的手机型号是
红米1S电信版,MIUI版本是: MIUI-JHCCNBF37.0,集成的Android版本是4.3 JLS36C;而这种情况在模拟器里或其他手机上没有发生。
具体问题:
点击拍照按钮,跳转到拍照界面时,由于拍照程序是比较消耗系统资源的,一般这个时候,系统大多会调用onSaveInstanceState方法让app保存界面状态值。
小米miui系统大多数时候也是正常调用 onSaveInstanceState 方法,当系统调用这个方法的时候,整个拍照流程,包括拍照后返回调用拍照的这个activity时,都是正常的。
但是,
有些时候小米手机并没有调用 onSaveInstanceState 方法,这个时候,拍照后直接退出了调用他的这个activity(该activity覆写了onActivityResult方法),也就不会执行 onActivityResult方法。程序没有任何其他异常。 飘易的猜测是:
由于红米miui深度定制了android系统,并且红米是整个小米系里最低端的入门机,在硬件性能上缩减严重。大白话就是修改了过多的模块而又没有考虑周全产生的bug。当系统调用拍照程序时,系统认为当前的内存还够用,activity不会被销毁,所以没有执行 onSaveInstanceState方法。但是拍照程序真正启用后,系统发现内存不够用了,即将OOM,就销毁了处于onPause或onStop的activity。这个销毁系统不会通知你,系统偷偷地干了这件事。 正常的情况下,即使系统销毁了这个activity,在拍照返回到这个activity的时候,系统会重新生成被销毁的这个activity,重走 onCreate 等方法。 然而小米的miui系统在这里就有了bug!小米miui认为某个activity不会销毁,所以直接忽略了由于意外,系统需要重新创建这个activity的可能性。因此直接导致了返回到了前前activity,而不是前activity。 当小米miui系统明确地认为这个activity可能会被销毁时,执行 onSaveInstanceState 方法的时候,上面的这个bug不存在,系统在拍照完成后可以正常返回到前面的activity里并执行里面的 onActivityResult 方法。
目前,此bug没修复。上面的是飘易个人浅见,欢迎高手评论。
顺带说一下,红米手机的另外的bug:
一、有的时候在用手机浏览器访问网页或返回的时候,整个页面没有显示完全,网页上的部分元素显示不全、断层,必须手动刷新当前页,才能显示全部页面。 二、在打开APP时,点击按钮返回时,比如拍照返回时,界面上的有些控件是黑色的,必须手指滑过这些控件,才能去掉黑色。 不知道其他小伙伴们,有没有遇到如上bug。
此问题已解决,是这些手机的相机程序在保存照片的时候都会加一些特效,尤其是那个旋转,导致前面的Activity重新onCreate了。
解决方案:在清单文件的Activity中加入属性(必须)android:configChanges="orientation|screenSize|keyboardHidden|keyboard|",(可选)还可以加入android:screenOrientation="portrait"来强制横屏或者竖屏。这样Activity就不会在旋转的时候销毁重新创建了。
我要有些东西写在application中的怎么办。
哎 为什么miui不替开发人员考虑呢? 实验了一下QQ 红米手机上也有拍照闪退的问题
MIUI更新到8.0后貌似这问题解决了。。。测试手机红米note
现在红米手机还有这个问题 偶尔能正常返回值 请问能否解决
另外应该还有个问题,调用相机后,Activity被save了,在onCreate中restore WebView,然后执行onActivityResult,调用webView.loadUrl设值时,极大可能WebView并没有加载完成,导致调用不成功。
(开启开发者选项中的不保留活动必现)
解决方案:在WebViewClient的onPageFinished中回调Activity再webView.loadUrl
demo:http://2tu.github.io/2017/12/15/WebView-RestoreInstance-onActivityForResult-not-work/
786a955f8579d01e9ceba41647962165现在红米手机还有这个问题 偶尔能正常返回值 请问能否解决