Android 后摄相机退出速度慢问题分析及优化
<p>一、问题:</p><p>在MMITest中后主摄拍照完成点击通过或者失败,比前摄退出慢1s左右</p>
<p>二、问题分析</p>
<p>1、分析log如下:</p>
<div class="cnblogs_code">
<pre>前相机测试:<br>S0020D3<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">38.000</span> <span style="color: rgba(128, 0, 128, 1)">789</span><span style="color: rgba(128, 0, 128, 1)">5591</span> I ActivityTaskManager: START u0 {cmp=com.sprd.validationtools/.itemstest.camera.FrontCameraTestActivity (has extras)} with LAUNCH_MULTIPLE <span style="color: rgba(0, 0, 255, 1)">from</span> uid <span style="color: rgba(128, 0, 128, 1)">1000</span> pid <span style="color: rgba(128, 0, 128, 1)">3884</span> (BAL_ALLOW_ALLOWLISTED_UID) result code=START_SUCCESS <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">点击进入前相机测试</span>
M002276<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">38.357</span><span style="color: rgba(128, 0, 128, 1)">3884</span><span style="color: rgba(128, 0, 128, 1)">8970</span> I FrontCameraTestActivity: start preview <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">进入测试项开始预览</span>
M002428<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">38.897</span> <span style="color: rgba(128, 0, 128, 1)">409</span><span style="color: rgba(128, 0, 128, 1)">9003</span> I Cam3OEMIf: <span style="color: rgba(128, 0, 128, 1)">4900</span>, receivePreviewFrame: Launch Camera Time:<span style="color: rgba(128, 0, 128, 1)">687</span>(ms).<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开预览耗时</span>
M0027A9<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">42.718</span><span style="color: rgba(128, 0, 128, 1)">3884</span><span style="color: rgba(128, 0, 128, 1)">3884</span> D onclick : pass..com.sprd.validationtools.itemstest.camera.FrontCameraTestActivity@7e51409 <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">点击通过按钮</span>
M0027AA<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">42.719</span><span style="color: rgba(128, 0, 128, 1)">3884</span><span style="color: rgba(128, 0, 128, 1)">3884</span> D BaseActivity: storeResult classname:com.sprd.validationtools.itemstest.camera.FrontCameraTestActivity <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">保存测试结果</span>
S00298D<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">43.010</span> <span style="color: rgba(128, 0, 128, 1)">789</span><span style="color: rgba(128, 0, 128, 1)">1147</span> I WindowManager: Input focus has changed to Window{50e05e4 u0 com.sprd.validationtools/com.sprd.validationtools.itemstest.ListItemTestActivity}, - <span style="color: rgba(0, 0, 255, 1)">from</span> c49cb57 com.sprd.validationtools/com.sprd.validationtools.itemstest.camera.FrontCameraTestActivity mDisplayId <span style="color: rgba(128, 0, 128, 1)">0</span> updateInputWindows <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回到测试列表界面</span>
<span style="color: rgba(0, 0, 0, 1)">后相机测试:
S002AE1</span><span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">44.510</span> <span style="color: rgba(128, 0, 128, 1)">789</span><span style="color: rgba(128, 0, 128, 1)">3333</span> I ActivityTaskManager: START u0 {cmp=com.sprd.validationtools/.itemstest.camera.CameraTestActivity (has extras)} with LAUNCH_MULTIPLE <span style="color: rgba(0, 0, 255, 1)">from</span> uid <span style="color: rgba(128, 0, 128, 1)">1000</span> pid <span style="color: rgba(128, 0, 128, 1)">3884</span> (BAL_ALLOW_ALLOWLISTED_UID) result code=START_SUCCESS <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">点击进入前相机测试</span>
M002CC4<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">44.906</span><span style="color: rgba(128, 0, 128, 1)">3884</span><span style="color: rgba(128, 0, 128, 1)">3884</span> E CameraTestActivity: start preview<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">进入测试项开始预览</span>
M002EA3<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">45.607</span> <span style="color: rgba(128, 0, 128, 1)">409</span><span style="color: rgba(128, 0, 128, 1)">9080</span> I Cam3OEMIf: <span style="color: rgba(128, 0, 128, 1)">4900</span>, receivePreviewFrame: Launch Camera Time:<span style="color: rgba(128, 0, 128, 1)">933</span>(ms).<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">打开预览耗时 测试10次,平均700ms</span>
M003550<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">54.163</span><span style="color: rgba(128, 0, 128, 1)">3884</span><span style="color: rgba(128, 0, 128, 1)">3884</span> D onclick : pass..com.sprd.validationtools.itemstest.camera.CameraTestActivity@<span style="color: rgba(128, 0, 128, 1)">7076185</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">点击通过按钮</span>
M003551<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">54.163</span><span style="color: rgba(128, 0, 128, 1)">3884</span><span style="color: rgba(128, 0, 128, 1)">3884</span> D BaseActivity: storeResult classname:com.sprd.validationtools.itemstest.camera.CameraTestActivity<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">保存测试结果</span>
S003652<span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">54.712</span> <span style="color: rgba(128, 0, 128, 1)">789</span> <span style="color: rgba(128, 0, 128, 1)">813</span> W ActivityTaskManager: Activity pause timeout <span style="color: rgba(0, 0, 255, 1)">for</span> ActivityRecord{1b0e20f u0 com.sprd.validationtools/<span style="color: rgba(0, 0, 0, 1)">.itemstest.camera.CameraTestActivity t12 d0 f}}
S003811</span><span style="color: rgba(128, 0, 128, 1)">01</span>-<span style="color: rgba(128, 0, 128, 1)">02</span> <span style="color: rgba(128, 0, 128, 1)">01</span>:<span style="color: rgba(128, 0, 128, 1)">13</span>:<span style="color: rgba(128, 0, 128, 1)">55.531</span> <span style="color: rgba(128, 0, 128, 1)">789</span> <span style="color: rgba(128, 0, 128, 1)">803</span> I WindowManager: Input focus has changed to Window{50e05e4 u0 com.sprd.validationtools/com.sprd.validationtools.itemstest.ListItemTestActivity}, - <span style="color: rgba(0, 0, 255, 1)">from</span> 63b0934 com.sprd.validationtools/com.sprd.validationtools.itemstest.camera.CameraTestActivity mDisplayId <span style="color: rgba(128, 0, 128, 1)">0</span> updateInputWindows <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回到测试列表界面</span></pre>
</div>
<p> </p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">2、在log中发现异常:</span><strong>Activity pause timeout for ActivityRecord{1b0e20f u0 com.sprd.validationtools/.itemstest.camera.CameraTestActivity t12 d0 f}},</strong></span>protected void onPause()后退出速度在300ms左右</p>
<p>3、问题定位:</p>
<p>@Override</p>
<p>protected void onPause() { ... ...}此方法执行出现问题</p>
<p>4、查看代码中的protected void onPause()方法,在 onPause()中有执行相机闪光灯模式关闭的操作。涉及到Camera对象的参数设置,可能需要一定的处理时间,尤其是在某些设备上可能较慢,如果放在onPause()里,这时候Activity可能还在进行其他暂停相关的操作,如果Camera操作耗时,会导致主线程被阻塞,从而延迟onPause()的完成,进而影响Activity切换的流畅度。onPause()是在Activity失去焦点但仍部分可见的时候调用,比如另一个Activity以对话框形式出现,所以,onPause()执行的时间点比较早,可能在界面还在部分显示的时候,这时候如果进行一些资源释放的操作,可能会阻塞主线程,导致界面卡顿,用户觉得退出慢</p>
<div>
<div class="cnblogs_code">
<div>@Override</div>
<div> protected void onPause() {</div>
<div> super.onPause();</div>
<div> mIsPause = true;</div>
<div> Log.d(TAG, "onPause");</div>
<div> try {</div>
<div> if (mCamera != null) {</div>
<div>
<div>
<div> <span style="color: rgba(255, 0, 0, 1)">Camera.Parameters parameters = mCamera.getParameters();</span></div>
<div><span style="color: rgba(255, 0, 0, 1)"> parameters.setFlashMode(Parameters.FLASH_MODE_OFF);</span></div>
<div><span style="color: rgba(255, 0, 0, 1)"> mCamera.setParameters(parameters);</span></div>
</div>
</div>
<div> mCamera.setPreviewCallback(null);</div>
<div> mCamera.stopPreview();</div>
<div> mCamera.release();</div>
<div> mCamera = null;</div>
<div> }</div>
<div> } catch (Exception e) {</div>
<div> e.printStackTrace();</div>
<div> }</div>
<div> }</div>
</div>
<p>5、优化方案:onPause()是在Activity失去焦点但仍部分可见的时候调用,而onStop()是在Activity完全不可见时调用,比如用户跳转到其他Activity或者回到主屏幕,这时候用户已经看不到界面了,所以即使这里的代码执行时间较长,对用户感知的影响较小,可能不会明显感觉到退出变慢。因此,将耗时的操作比如关闭闪光灯模式操作移到onStop()中可以改善用户体验。</p>
<div class="cnblogs_code">
<pre></pre>
<div>
<div>@Override</div>
<div> protected void onPause() {</div>
<div> super.onPause();</div>
<div> mIsPause = true;</div>
<div> Log.d(TAG, "onPause");</div>
<div> try {</div>
<div> if (mCamera != null) {</div>
<div> mCamera.setPreviewCallback(null);</div>
<div> mCamera.stopPreview();</div>
<div> mCamera.release();</div>
<div> mCamera = null;</div>
<div> }</div>
<div> } catch (Exception e) {</div>
<div> e.printStackTrace();</div>
<div> }</div>
<div> }</div>
</div>
<pre><span style="color: rgba(0, 0, 0, 1)">...<br>@Override
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onStop() {
super.onStop();
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (mCamera != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
Camera.Parameters parameters </span>=<span style="color: rgba(0, 0, 0, 1)"> mCamera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(parameters);</span>
<span style="color: rgba(0, 0, 0, 1)"> }
}</span></pre>
</div>
<p>三、总结</p>
<p>将相机操作从 <code>onPause()</code> 移至 <code>onStop()</code>,利用了生命周期阶段的特性:将耗时操作推迟到界面不可见时执行,避免阻塞主线程,从而提升用户体验</p>
</div><br><br>
来源:https://www.cnblogs.com/tangtangsweet/p/18789606
頁:
[1]