背景

公司平台化开发,一个重要的地方是上层应用可以兼容不同的芯片平台。比如上层camera应用可以兼容Mtk和Qcom等不同平台。这个我们公司的camera不知道他们从哪里搞来了一个中间键的实现方法。说白一点,就是统一在hal层通过中间键给上层camera发送固定格式的消息,然后上层camera通过解析此消息来实现具体的逻辑功能。好高大上啊!

问题

然后,我被抽调支持camera的工作。在android Go (8.1.0)有一个柔光灯的功能没有实现,说要从android 7.0上来移植。正好,我刚刚移植了一个自拍镜像的功能,好吧,这个任务就这么缘份的分到了我名下。我开始以为这是一个简单的移植,应该问题不大。一开工,发现这个具体的实现是在中间键上来实现,而此android Go (8.1.0)软件上,我们不打算移植中间键,影像部门给的解释是说移植此中间键的工作量特别大,要一个熟悉此模块的工程师一个星期才能移植成功(我们心里冷笑一下吧,这个可以骗骗老板,请不要来骗我)。所以要求我在不实现中间键的情况,使用MTK平台的方式来实现此功能。并且,他们还给了一个传说中的备份方案说可以实现,然后此工作就看我了,小伙子加油,我们会为你鼓劲的噢。

柔光灯的功能简单说明:
当我们使用前置camera时,如果发现当前环境的光线比较暗时,开启前置flash,如果发现当前环境的光线比较明时,关闭前置flash。

具体问题分析

那我们先看看此问题在代码上的实现吧:

在frameworks/base/core/java/android/hardware/Camera.java文件中,接受到hal层发送的识别当前环境的值(msg.arg2),此值是通过消息MTK_CAMERA_MSG_EXT_NOTIFY_ASD来发送的:

private void handleExtNotify(Message msg, Camera camera) {switch (msg.arg1) {case MTK_CAMERA_MSG_EXT_NOTIFY_ASD:if (mAsdCallback != null) {mAsdCallback.onDetected(msg.arg2);return;}break;

我们可以查看mAsdCallback,发现其为一个接口AsdCallback对象。:

// ASD
private Camera.AsdCallback mAsdCallback;
.....................................
//ASD
/**
* @hide An interface which contains a callback for the auto scene detection
*/
public interface AsdCallback {/*** @param scene the scene detected*/void onDetected(int scene);
}/**
* @param cb the callback to run
* @hide Registers a callback to be invoked when auto scene is detected
*/
public final void setAsdCallback(AsdCallback cb) {mAsdCallback = cb;
}

好吧,这就是我们现在有的所有信息,开始干活吧。

当然,立刻有大神会说,你太菜了,这个太简单了,在camera应用中要实现具体功能的地方实现此接口就可以了。

是的,原理的确如此。但是我们上面说了,我们上层应用是做成平台化,也就是与平台无关,也就是此应用的编译不参与整个项目的编译,应用会在Android Studio中直接生成APK,不和平台的代码产生任何交集。所以,你说的方法是做不了的。

下面就开始介绍传说中的备份方案吧:
也就是直接在应用中开一个服务,一直监听此hal层传上来的值,如果此值发生变化,就进行对应的操作。
我和他们交流了一下,最后他们自己都不好意思的说此方法不好,哥哥,请不要出嫂主意。但是,这是部门合作,他们给领导汇报工作说给了备份的方案,然后他们领导还在群里说他们已经给了方案,为什么你搞不定,你这个废物,好吧,哥,你厉害,我菜。

功能实现

直接来调用此接口,肯定是不行的,要想办法。

和周围一堆人讨论了一圈,各路大神各种神通,各种仙技,但是最后实现此功能的一定是你自己,所以这要求自己对各种主意有精准的识别和判断,不要被带坑里去了,最后的事实也是证明,大部分人的主意连边都没有粘。

我们要记住:
android本身的代码就是最好的老师,一定要以android本身的代码为导向原则

我们要记住:
我们是二次开发,所以,当前的代码也是有充分的参考价值。

好吧,经过讨论和分析现有的代码,我发现camera应用有一个笑容识别功能,也是调用frameworks下的接口,好吧, 我们就仿造此方法来实现此功能。

笑容识别功能的关键思想是不直接调用此接口,而是先提供一个重新包装后的AsdCallback 接口的jar包给上层camera应用使用。

好吧,那我们先来做一个jar包吧。

生产上层应用使用的jar包

第一步,打开Eclipse,新建一个android应用工程。
File–New–Android Application Project–新建一个MTKCameraAsd项目—next–取消Create Activity和Create custom launcher icon,选中Mark this project as library。

第二步,新建MTKCameraAsd.java 文件.
此类MTKCameraAsd有一个类AsdCallbackMTK实现接口Camera类中的接口AsdCallback,还新建了一个接口AsdCallbackMTKInterface,此接口为上层应用中使用的要实现的接口.还有一个setAsdCallback方法,此方法主要功能是为调用Camera类中的方法setAsdCallback.

package com.tinno.MTkCamera;import android.hardware.Camera;
import android.hardware.Camera.AsdCallback;public class MTKCameraAsd {public MTKCameraAsd() {}private MTKCameraAsd.AsdCallbackMTK asdCallbackMTK;private MTKCameraAsd.AsdCallbackMTKInterface asdCallbackMTKInterface;public interface AsdCallbackMTKInterface {void onDetected(int scene);}private final class AsdCallbackMTK implements AsdCallback {private AsdCallbackMTK() {}public void onDetected(int scene){if(MTKCameraAsd.this.asdCallbackMTKInterface != null) {MTKCameraAsd.this.asdCallbackMTKInterface.onDetected(scene);}}}public void setAsdCbInterfaceListener(MTKCameraAsd.AsdCallbackMTKInterface as) {this.asdCallbackMTKInterface = as;}public void setAsdCallback(Camera camera) {if(camera != null) {if(this.asdCallbackMTK == null) {this.asdCallbackMTK = new MTKCameraAsd.AsdCallbackMTK();}camera.setAsdCallback(this.asdCallbackMTK);}}}

AndroidManifest.xml文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.tinno.MTKAsdHelpLib"android:versionCode="1"android:versionName="1.0" ><uses-sdk
        android:minSdkVersion="23"android:targetSdkVersion="23" /></manifest>

到此,我们会发现Eclipse报错,因为其不识别Camera类中的接口AsdCallback.没有关系,这主要是因为android标注接口中没有接口导致的错误,我们可以找到编译工程的项目out目录下,找到对应的Camera类的jar包,装其导入到Eclipse中.

第三步:查找jar包和导入到Eclipse的项目中

具体查找jar包和导入到Eclipse的项目中的方法可以查看如下的参考资料:
2.Android之导入源码到eclipse中以及单模块调试
http://blog.csdn.net/way_ping_li/article/details/10494925
4.Android学习之往系统应用中添加framework层的jar包
http://blog.csdn.net/feishangbeijixing/article/details/44156945

我说一下我的方法:

grep -rni   --include=*.jar  "AsdCallback"  ./out/
匹配到二进制文件 ./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar

一行命令定位到,事实上,./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar文件,也是framework的jar包.

然后我们将其导入到Eclipse的项目中.
方法为:
在eclipse的Android项目中,选择项目–右键–选择属性–Java Build Path–Libraries–Add Library–User Library–Next–UserLibraries–User Libraries–New–新建一个User Library–点击刚新建的user library–Add JARS把Jar包加入到建立的User Library中–最后点击OK。回到Java Build Path界面–Order and Export,把所建立的User Libraries移到android sdk的上面

第四步:使用Eclipse将此应用生成一个jar包.

这个非常简单,具体的实现过程可以参考:
1.使用eclipse工程导出jar包
http://blog.csdn.net/changqing5818/article/details/52062790

在应用中使用此jar包

第一步:导入此jar包到Android Studio中.
具体的实现方法请参考:
3.Android studio如何导入jar包
https://jingyan.baidu.com/article/d621e8da41135e2865913fb1.html

第二步:实现其具体的逻辑功能.

那么我们在上层应用中的关键实现方法为:
关键代码一:
在CameraManager.java文件中:

//导入类MTKCameraAsd
import com.tinno.MTkCamera.MTKCameraAsd;
........................................................
//定义一个类MTKCameraAsd的对象mMTKCameraAsd
private MTKCameraAsd mMTKCameraAsd = new MTKCameraAsd();
........................................................
//在方法中调用对象mMTKCameraAsd的仅有的二个公开接口
private void setAsdCb(int id) {//调用对象mMTKCameraAsd的setAsdCbInterfaceListener方法,设置接口对象mAsdCb,此接口对象mAsdCb为我们具体的实现逻辑操作的回调接口.mMTKCameraAsd.setAsdCbInterfaceListener(mAsdCb);//调用对象mMTKCameraAsd的setAsdCallback方法,给camera设置接口mMTKCameraAsd.setAsdCallback(mCamera[id]);
}
........................................................
//定义一个asdCallback对象mAsdCb
private asdCallback mAsdCb = new asdCallback();
//定义一个类AsdCallbackMTKInterface,其实现接口AsdCallbackMTKInterface.而此类AsdCallbackMTKInterface又将其具体的回调推迟到了接口onAsdListener中.其实,我们也可以完全在这实现具体的逻辑,不再使用onAsdListener回调接口.只是此功能需要要别的文件实现具体的逻辑,所以才又使用了一次onAsdListener回调接口private class asdCallback implements MTKCameraAsd.AsdCallbackMTKInterface {public void onDetected(int scene) {// TODO Auto-generated method stubif(onAsdListener != null) {onAsdListener.onDetected(scene);}}}
........................................................
//我们定义推迟回调的接口OnAsdListener对象onAsdListener
public ICamera.OnAsdListener onAsdListener=null;
........................................................
//我们再在对应的地方将赋值为其它文件的实现此推迟回调的接口OnAsdListener的对象
onAsdListener = (ICamera.OnAsdListener)msg.obj;
........................................................

在ICamera.java定义一个接口,此接口为推迟的回调接口.

    public interface OnAsdListener {void onDetected(int scene);}

我们真正实现此推迟的回调接口的具体逻辑为:
PhotoModule.java

..........................................................................
private final ActorAsdCallback mAsdCallback = new ActorAsdCallback();
//定义类ActorAsdCallback,此类ActorAsdCallback实现推迟的回调接口OnAsdListener
private final class ActorAsdCallback implements ICamera.OnAsdListener {public void onDetected(int scene) {//此处才是真正实现上层监听回调接口的具体逻辑的地方.....................}
}
..........................................................................
//将具体的mAsdCallback接口赋值给CameraManager.java文件中的对象onAsdListener,使其调用起来
public void startAsdDetection() {//mCameraDevice.setAsdCallback(mAsdCallback);
}..........................................................................

至此,功能完成,打完收工.

再回首

我们再回过头来看一看,为什么我们这样就可以调用Framework中Camera类的接口AsdCallback呢?

不着急,我们先在上层camera应用中查看一下AsdCallback关键字,我们会发现,在整个上层应用中,竟然没有搜索到使用接口AsdCallback.

这,就是这个方法为什么我们这样就可以调用Framework中Camera类的接口AsdCallback的秘密.因为我们根本上应用中没有使用此接口,所以当然就不会报错了.

那么,我们为什么在上层应用中没有使用此接口AsdCallback而又实现了此功能呢?奥秘就在我们生成为上层应用使用的jar包的项目文件MTKCameraAsd.java中.

请你再回去看MTKCameraAsd.java文件,能发现什么不?

奥秘就是我们使用了一个中间类AsdCallbackMTK,此类实现接口AsdCallback,将类将MTKCameraAsd和接口AsdCallbackMTKInterface关联,并且对外只提供公开的可以操作Camera和AsdCallbackMTKInterface的接口,但是我们不提供公开的接口来使用AsdCallback这个类.也就是重新包装AsdCallback,将其对外隐藏.

心里的话:

说实在话,做这个东东,坑太多,真是让人非常痛苦,领导只有拼命的催进度,心里还觉得你特别的菜,外人完全不知道此实现的难度,只有冷暖自知.

但是,说实话,做完这个,解答了我多年前的几个疑惑,还是有收获的.。

但是,悲剧在于我现在根本对这些东东没有兴趣了。没劲!

场景光线的值的配置参数

此场景光线的值的识别配置参数为

在文件vendor/mediatek/proprietary/custom/mt6580/hal/camera/camera_custom_asd.cpp

ASDDataOut1->u1ScoreThrNight
ASDDataOut2->s2EvLoThrNight
ASDDataOut2->s2EvHiThrNight

vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/v1/hal/client/CamClient/FD/Asd/AsdClient.cpp


在hal层更新此当前环境的值u4Scene的方法:void
AsdClient::
update(MUINT8 * OT_Buffer, MINT32 a_Buffer_width, MINT32 a_Buffer_height, MINT32 a_FaceNum)
{
...................................u4Scene = mSceneCur;MY_LOGD("u4Scene:%d ", u4Scene);if  (1){mpCamMsgCbInfo->mNotifyCb(MTK_CAMERA_MSG_EXT_NOTIFY,MTK_CAMERA_MSG_EXT_NOTIFY_ASD,u4Scene,mpCamMsgCbInfo->mCbCookie);}
..............................
}

安装使用jar包生成的APK报错的处理

如果报此错误:

adb install ApeCamera48-debug.apk
Failed to install ApeCamera48-debug.apk: Failure [INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION: Failed to parse /data/app/vmdl1065641074.tmp/base.apk: Corrupt XML binary file]

解决原因,是你的AndroidManifest.xml文件不对.

解决方法:
对应修改你的AndroidManifest.xml文件

参考资料

1.使用eclipse工程导出jar包
http://blog.csdn.net/changqing5818/article/details/52062790
2.Android之导入源码到eclipse中以及单模块调试
http://blog.csdn.net/way_ping_li/article/details/10494925
3.Android studio如何导入jar包
https://jingyan.baidu.com/article/d621e8da41135e2865913fb1.html
4.Android学习之往系统应用中添加framework层的jar包
http://blog.csdn.net/feishangbeijixing/article/details/44156945

android开发笔记之app应用间接使用frameworks接口相关推荐

  1. Android开发笔记(五十四)数据共享接口ContentProvider

    ContentProvider 前面几节介绍了进程间通信的几种方式,包括消息包级别的Messenger.接口调用级别的AIDL.启动页面/服务级别的Notification,还有就是本节这个数据库级别 ...

  2. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  3. Android开发笔记(一百二十六)自定义音乐播放器

    MediaRecorder/MediaPlayer 在Android手机上面,音频的处理比视频还要复杂,这真是出人意料.在前面的博文< Android开发笔记(五十七)录像录音与播放>中, ...

  4. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  5. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

  6. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

  7. Android开发笔记(九十三)装饰模式

    基本概念 装饰模式是扩展功能用的一种设计模式, 一般要扩展功能,我们都会想到继承,可是继承只能继承一个基类,如果有多个条件需要分别进行扩展,那得写好几个派生类,条件越多派生类的数量也越多. 上面描述比 ...

  8. Android开发笔记(一百一十七)app省电方略

    电源管理PowerManager PowerManager是Android的电源管理类,用于管理电源操作如睡眠.唤醒.重启以及调节屏幕亮度等等. PowerManager的对象从系统服务POWER_S ...

  9. Android开发笔记(一百七十)给App的应用页面注册快捷方式

    元数据不单单能传递简单的字符串参数,还能传送更复杂的资源数据,从Android7.1开始新增的快捷方式便用到了这点,譬如在手机上桌面长按支付宝图标,会弹出如下图所示的菜单. 点击菜单项"扫一 ...

最新文章

  1. Python+OpenCV 图像处理系列(7)—— 图像色彩空间及转换
  2. 全新版本仿网易云音乐来啦
  3. 创新实训团队记录:为BR-MTC问题设计一个近似算法
  4. 学好计算机科学的诀窍,【教学方法论文】计算机科学技术专业高效教学方法(共4295字)...
  5. 淘宝API调用 申请 获取session key
  6. oracle ojvm generic,Oracle OJVM安全补丁
  7. linux在线扩展文件系统空间ext2online
  8. 2021高考成绩查询省排名,【重磅整理】2021全国各地高考预测分数线出炉,这样估分可以估算全省排名...
  9. ni max不能连续采集图像_1.6视觉检测项目过程分解——程序的连续运行
  10. 14. Django基础:关系映射
  11. 2021年“泰迪杯”数据分析技能赛A题
  12. 个人向常用的一些函数的汇总成一个简易模板
  13. java.sql.SQLException: Parameter index out of range (2 」 number of parameters, which is 1).
  14. 计算机usb接口无法读取,USB设备识别不了,USB接口无法识别设备怎么办
  15. WinCC 在线变量绘制趋势图(自定义内部变量-随机数据)
  16. 生成验证码并判断用户是否输入正确
  17. 怎样恢复内存卡的视频文件?(图文操作解析)
  18. Skleran-线性模型-普通最小二乘法-LinearRegression
  19. Mac 端口号8080被占用
  20. flash保存html,如何把网页上的flash动画保存为swf格式文件(缓存提取)

热门文章

  1. sis防屏蔽程序_程序员如何写一份更好的简历
  2. 3DMAX如何建模手
  3. 二维码报修系统的技术实现
  4. 单点登录(一)| LDAP 协议
  5. 【bzoj4318】【OSU!】期望dp——维护多个期望值递推
  6. 安装Virtualbox出现严重错误
  7. RabbitMQ(Java操作工作队列-按劳分配方式)
  8. Microsoft .NET Framework 3.5 sp1离线安装(DotNetFX35)
  9. 腾讯翻译自然语言处理实习经验贴
  10. Git (代码托管)