Android4.4 Camera Gallery2 App之间消息传递分析!
来源:互联网 发布:trados翻译软件官方 编辑:程序博客网 时间:2024/06/05 18:30
在Android4.4上面,Camera和Gallery2的关系在代码上是分开的。但是在在实际代码上,Camera和Gallery的关系很密切。
下面以实际开发过程中遇到的一个问题来展开分析:
需求:客户要求做假对焦,进入到preview界面的时候,自动对焦一次。
我的做法是在PhotoActor.java中的onPreviewStartDone预览完成的函数中模拟onSingleTapUp触摸点击效果的自动对焦过程。
mCamera.getFocusManager().onSingleTapUp(mCamera.getPreviewFrameWidth() / 2, mCamera.getPreviewFrameHeight() / 2);
FocusManager.java
public void onSingleTapUp(int x, int y) { Log.i(TAG,"onSingleTapUp x = " + x + " y = " + y); if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH || mState == STATE_UNKNOWN) { return; } ……………… // Disable "center" rule because we no longer want to put it in the center. int[] rules = p.getRules(); rules[RelativeLayout.CENTER_IN_PARENT] = 0; mFocusIndicatorRotateLayout.requestLayout(); // Stop face detection because we want to specify focus and metering area. mListener.stopFaceDetection(); // Set the focus area and metering area. mListener.setFocusParameters(); if (mFocusAreaSupported) { autoFocus(); } else { // Just show the indicator in all other cases. updateFocusUI(); // Reset the metering area in 3 seconds. mHandler.removeMessages(RESET_TOUCH_FOCUS); mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY); //add mHandler.removeMessages(MSG_SHOW_FOCUS_END); mHandler.sendEmptyMessageDelayed(MSG_SHOW_FOCUS_END, MSG_SHOW_FOCUS_END_DELAY); } }
@Override public void handleMessage(Message msg) { switch (msg.what) { case RESET_TOUCH_FOCUS: cancelAutoFocus(); mListener.startFaceDetection(); break; case MSG_SHOW_FOCUS_END: mFocusIndicatorRotateLayout.showSuccess(true); mListener.playSound(MediaActionSound.FOCUS_COMPLETE); break; default: break; } }
这样,简单的功能是实现了,但是首先遇到的第一个问题是:由于Preview的SurfaceView界面是先绘制出来,然后取景的,取景需要时间,这样对焦就经常发生在SurfaceView还是灰色界面的时候就开始对焦,特别是在切换前后摄像头的时候特别明显。真实对焦是不会发生这样的问题的,因为它是根据Sensor捕获到的信息上传后产生效果的,取景没完成是不会对焦的。假对焦那就采取野蛮的办法,增加一个延时,演变成下面的代码:
new Handler().postDelayed(new Runnable() { @Override public void run() { mCamera.getFocusManager().onSingleTapUp(mCamera.getPreviewFrameWidth() / 2, mCamera.getPreviewFrameHeight() / 2); } }, 1000);
这样基本上能接受了。
很快,测试找到了第二个问题点:Camera Activity启动后,进入到图片预览界面,然后OnPause,再OnResume的时候,进入到的还是图片预览界面,但是这时候会有对焦行为。通过log分析,OnResume的时候也是有startPreview行为的(不管你是在preview界面,还是在图片预览界面),我的理解是,这时候不管在哪个界面,Preview都已经需要Init,只是在图片预览时,Camera preview的行为是在另外开辟的一个缓存中进行的,只是没有在当前屏幕显示出来而已。
自然而然,我们就必须增加一个判断条件来判断Camera Preview是否在当先的显示画面。很快在PhotoPage.java就找到了相关的代码。重点问题来的,我要怎么在Camera和Gallery之间来传递消息呢?
Camera.java和GalleryActivity.java都集成自AbstractGalleryActivity.java,通过分析在ActivityBase.java中找到AppBridge,顾名思义,可以看出来,这就是桥梁。在AppBridge抽象类中有一个接口:
public interface Server { // Set the camera frame relative to GLRootView. public void setCameraRelativeFrame(Rect frame); // Switch to the previous or next picture using the capture animation. // The offset is -1 to switch to the previous picture, 1 to switch to // the next picture. public boolean switchWithCaptureAnimation(int offset); // Enable or disable the swiping gestures (the default is enabled). public void setSwipingEnabled(boolean enabled); // Notify that the ScreenNail is changed. public void notifyScreenNailChanged(); // Add a new media item to the secure album. public void addSecureAlbumItem(boolean isVideo, int id); /// M: for camera gesture feature @ public Listener setGestureListener(Listener listener); /// @} // M: Notify PhotoView to render FullPicture only to boost performance public void renderFullPictureOnly(boolean fullPictureOnly); public void setOritationTag(boolean lock, int oritationNum); ///M:add for set camera path public void setCameraPath(String setPath); public int getSecureAlbumCount(); public boolean isCameraScreen(int offset); }
而PhotoPage实现了该接口:
public class PhotoPage extends ActivityState implements PhotoView.Listener, OrientationManager.Listener, ShareActionProvider.OnShareTargetSelectedListener,AppBridge.Server, PhotoPageBottomControls.Delegate, GalleryActionBar.OnAlbumModeSelectedListener, AbstractGalleryActivity.GyroPositionListener, AbstractGalleryActivity.HotknotCompleteListener{
……
public boolean isCameraScreen(int offset) { return mModel.isCamera(offset); }
……
}
找到问题点,实现起来就非常简单了,中间还有两层的封装就不多说了,最终的代码变为:
if(mCamera.isCameraScreen(0)) { new Handler().postDelayed(new Runnable() { @Override public void run() { mCamera.getFocusManager().onSingleTapUp(mCamera.getPreviewFrameWidth() / 2, mCamera.getPreviewFrameHeight() / 2); } }, 1000); }
整个过程还是花了我1.5天的时间,主要是没有找到好的可以查看整个app UML结构的工具,所以一点点找起来麻烦,浪费时间,而且代码量大,很容易就迷失了。
有好的工具,请留言推荐,谢谢!
- Android4.4 Camera Gallery2 App之间消息传递分析!
- Android4.2.2 Gallery2源码分析(4)——GLCanvas.java
- Android4.2.2 Gallery2源码分析(4)——GLCanvas.java
- Android4.4 Camera 数据流分析
- Android4.4 Gallery2图库浅析
- android4.4 Camera 框架纵横方向分析
- android4.0 的图库Gallery2代码分析(一)
- android4.0 的图库Gallery2代码分析(二)
- Android4.0图库Gallery2代码分析(一) 程序总体结构
- Android4.0图库Gallery2代码分析(一) 程序总体结构
- Android4.2.2 Gallery2源码分析(5)——GLCanvasImpl.java
- Android4.2.2 Gallery2源码分析(6)——GLView.java
- Android4.2.2 Gallery2源码分析(5)——GLCanvasImpl.java
- Android4.2.2 Gallery2源码分析(6)——GLView.java
- Android4.0图库Gallery2代码分析(一) 程序总体结构
- 网络首发]导入Android4.2源码里的Gallery2和Camera模块至Eclipse全过程
- Android4.2源码里的Gallery2和Camera模块至Eclipse全过程
- 导入Android4.2源码里的Gallery2和Camera模块至Eclipse全过程
- Hibernate多表映射之多对一
- 10进制N进制
- 浅谈HTTP中Get与Post的区别
- 算法的时间复杂度和空间复杂度-总结
- Gradle脚本基础全攻略
- Android4.4 Camera Gallery2 App之间消息传递分析!
- 欧几里德的游戏
- 【算法】程序猿不写代码是不对的58
- vs2010连接mysql数据库(含win32和x64两种平台)
- Help Hanzo (数论(素数(打表进阶(任意段区域打表)))))
- Linux(八)用户管理
- poj 1655 DP
- CUDA学习笔记一
- Redis protected-mode