android 原生camera——设置模块修改
,
此篇博客是记一次客户需求修改,从上周五到现在正好一周时间,期间的各种酸爽,就不说了,还是来看大家关注的技术问题吧。
首先看下以前效果和修改后的效果:
修改前:修改后:
不知道有没有看明白,我在简单说下,没修改前Camera 设置中是有两个选项的一个负责预览大小(显示的宽高比如16:9),一个负责照片大小(如1600x1200),修改后 只要一个Picture Size 即负责切换预览大小也负责照片大小。
看到这是不是觉的好简单只要在Picture Size添加几个选项,然后在点击不同像素的选项时同样也能切换比例,。。。。。。。。。。。。。。其实呢就是这么简单!!!
但是前提是需要对系统的Camera有一定的了解,不然就和我一样苦逼的搞了一周最后发现只要不到50行代码就可以实现这个功能。所以改这个需求也是我对Camera的一次探索之旅,如果你的工作中也要涉及到camera模块,但对它又比较陌生就和我一起开始学习camera模块吧。
说明一下这里主要围绕文章开头的那个需求来说的,也就是camera设置模块,毕竟我只研究了一周,对它的整体设计
还有待深入研究,这里就不误人子弟了 O(∩_∩)O哈哈~
还是看那个需求 这里分为三步去解决
1、在Picture Size中添加需要的所以像素;
2、隐藏Preview Size;
3、添加各个像素选中后切换比例的功能
但是 首先呢 我们还是要对Camera有个基本的认识看看系统Camera的整体构架(虽然今天只是了解一小部分但是框架还是要了解一点点滴)
Camera根据Android 架构从上至下可分为
1)Applications: 最上层的应用,编译后生成Camera APK;
2)Application Framework: 主要为Applications提供API;
3)JNI: 使Application Framework和Libraries可交互;
4)Libraries: 包括Camera Framework和Camera Service(camera service和camera client);
5)HAL: 硬件抽象层, 用来链接driver和 Camera Service;
6)Kernel: image sensor driver的实作.
在来一张图 是山寨之王MTK提供的:
这个是MTK对camera进行了一下定制 他们主要对HAL和Kernel层着两层进行了比较大的改动
好了就大致提一下,如果全部都搞通了你就很niubility了。
我们还是看应用层的东东吧
这里就是整个界面的上有用到的控件了,camera的设计只有一个activity叫CameraActivity当然看到CameraLauncher的话也是CameraActivity,CameraLauncher只是CameraActivity的别名。
好了看了上面这么多高大上的东东,我们要研究的呢只是 这一小块,而且还不会全部都看
开始我们也需要对Setting的流程有一个了解 看上图可以知道SettingManager主要就是设置模块的管理类具体的话大家有时间可以点进去看下,这里从点击这个按钮开始
public void onClick(View view) {
if (view == mIndicator) {
if (!mShowingContainer) {
showSetting();
} else {
collapse(true);
}
}
}
它会去调用showSetting() 然后一路调用到initializeSettings 开始布局设置的界面,至于其中每项显示的内容是从xml文件的camera_preferences.xml中获取,而camera_preferences.xml的解析需要从CameraDeviceCtrl中开始跟 ,最后解析的数据会保存到SettingItem类中,具体流程的话需要大家去跟一下,我其实也没太怎么跟,领导天天在屁股后面问搞好了没,这感觉你懂的。
如果你跟过了上面的显示流程(不跟也没什么关系),我们来看下关于Picture Size 和preview Size选项中的数据来源,如果跟进camera_preferences.xml看的话 你会说 这里面不是有数据么
<ListPreference
camera:key="pref_camera_picturesize_key"
camera:title="@string/pref_camera_picturesize_title"
camera:entries="@array/pref_camera_picturesize_entries"
camera:entryValues="@array/pref_camera_picturesize_entryvalues" />
但是有没有发现这里的数据并没有都显示在列表里面,这是为什么呢,
带着这个疑问我们通过打log发现刚进去Camera的时候有很多
这样的信息 通过字面意思可以发现一个是支持的size 一个是可使用的list,而 buildEnableList里面的就是在设置界面显示的size ,
public static String buildEnableList(String[] list, String current) {
String listStr = null;
if (list != null) {
listStr = ENABLE_LIST_HEAD + current + ENABLE_LIST_SEPERATOR;
List<String> uniqueList = new ArrayList<String>();
for (int i = 0, len = list.length; i < len; i++) {
if (uniqueList.contains(list[i])) {
continue;
}
uniqueList.add(list[i]);
if (i == (len - 1)) {
listStr += list[i];
} else {
listStr += (list[i] + ENABLE_LIST_SEPERATOR);
}
}
}
Log.d(TAG, "buildEnableList(" + current + ") return " + listStr);
return listStr;
}
可以发现String[] list就是可用的列表,所以需要找到buildEnableList是谁调用的
通过跟踪buildEnableList的调用堆栈,发现是在CommonRule类中调用public void execute()来获取size的list的
overrideValue = SettingUtils.buildEnableList(
resultValuesAfterFilter.toArray(values), resultValue);
当然这个方法里面有很多事情要做,辣么多的代码,我就不拷贝了 可以看出来resultValuesAfterFilter.toArray(values)就是它,我们的list, 继续跟进去
List<String> resultValues = mResults.get(index);
List<String> resultValuesAfterFilter = filterUnsupportedValue(resultValues, mResultKey);
很明朗了filterUnsupportedValue字面意思过滤掉不匹配的 所以resultValues 包括所有的尺寸
而resultValues = mResults.get(index) 继续看看mResults 是哪儿赋值的
public void addLimitation(String condition, List<String> result, MappingFinder mappingFinder) {
mConditions.add(condition);
mResults.add(result);
mMappingFinder.add(mappingFinder);
}
private void createRuleFromRestrictions() {
Restriction[] restrictionArray = SettingDataBase.getRestrictions();
...
rule.addLimitation(conditionValues.get(k), resultValues, mappingFinder);
...
}
当然还是打印堆栈最后发现createRuleFromRestrictions中有调用 最后追到了SettingDataBase.getRestrictions();中
public static Restriction[] getRestrictions() {
return RESTRICTIOINS;
}
这个是一个Restriction数组代码量好大,有条件的话最好自己去看看 我就不贴了
private static final String[] PICTURE_SIZE_4_3
private static final String[] PICTURE_SIZE_16_9
最后发现没过滤前的数据就是上面这两个数组, 我现在默认是全屏也就是16:9 所以刚进去的时候是用的PICTURE_SIZE_16_9这个数组,按我们现在的需求 只要把4:3的数据都放到这个数组里面就好了。
有没有发现对camera不了解的话这一步其实也要跟很久呢。
至此第一步合并数据算是完成了,
第二部需要把preview size给隐藏了 这个应该比较简单了方法有很多 我这里是通过
public void initialize(ArrayList<ListPreference> listItems) {
//by linyu.li for mixture picturesize 20161215 start
if (listItems != null) {
for (int i = 0; i < listItems.size(); i++) {
if (listItems.get(i) != null) {
if (listItems.get(i).getKey()
.equals("pref_camera_picturesize_ratio_key")) {
continue;
}
}
mListItem.add(listItems.get(i));
}
}
// mListItem = listItems;
//by linyu.li for mixture picturesize 20161215 end
mListItemAdapter = new SettingsListAdapter();
mSettingList.setAdapter(mListItemAdapter);
mSettingList.setOnItemClickListener(this);
mSettingList.setSelector(android.R.color.transparent);
mSettingList.setOnScrollListener(this);
}
这种方式做的
来看最后一步 切换比例
设置中点击事件的调用堆栈如上图
当时通过跟踪发现主要在SettingCtrl的
public void onSettingChanged(String settingKey, String value) {
...
onSettingChanged(parameters, currentCameraId, settingKey, value);
...
}
private void onSettingChanged(Parameters parameters, int currentCameraId, String key,
String value) {
...
//by linyu.li for mixture picturesize 20161215 start
if (SettingConstants.KEY_PICTURE_SIZE.equals(key)) {
String prefName0 = mContext.getPackageName() + "_preferences_" + 0;
String prefName1 = mContext.getPackageName() + "_preferences_" + 1;
SharedPreferences sharedPreferences0 = mContext.getSharedPreferences(prefName0, Context.MODE_PRIVATE);
SharedPreferences.Editor editor0 = sharedPreferences0.edit();
SharedPreferences sharedPreferences1 = mContext.getSharedPreferences(prefName1, Context.MODE_PRIVATE);
SharedPreferences.Editor editor1 = sharedPreferences1.edit();
int index = value.indexOf('x');
float width = Integer.parseInt(value.substring(0, index));
float height = Integer.parseInt(value.substring(index + 1));
Log.i(TAG,"heightonseting === "+height+",width === "+width+"w/h = "+width/height);
if(currentCameraId==0){
if(width/height==(4f/3f)){
editor0.putString(SettingConstants.KEY_PICTURE_RATIO, "1.3333");
onSettingChanged(parameters, currentCameraId, SettingConstants.KEY_PICTURE_RATIO,
"1.3333");
}else if(width/height==(16f/9f)||width/height>1.7f){
editor0.putString(SettingConstants.KEY_PICTURE_RATIO, "1.7778");
onSettingChanged(parameters, currentCameraId, SettingConstants.KEY_PICTURE_RATIO,
"1.7778");
}
}else{
if(width/height==(4f/3f)){
editor1.putString(SettingConstants.KEY_PICTURE_RATIO, "1.3333");
onSettingChanged(parameters, currentCameraId, SettingConstants.KEY_PICTURE_RATIO,
"1.3333");
}else if(width/height==(16f/9f)||width/height>1.7f){
editor1.putString(SettingConstants.KEY_PICTURE_RATIO, "1.7778");
onSettingChanged(parameters, currentCameraId, SettingConstants.KEY_PICTURE_RATIO,
"1.7778");
}
}
editor0.apply();
editor1.apply();
}
//if(!SettingConstants.KEY_PICTURE_RATIO.equals(key))
//by linyu.li for mixture picturesize 20161215 end
executeRule(parameters, currentCameraId, key);
}
下面就是我添加的代码应该也好懂吧。
到这里我的这个需求就完美的解决了,可以发现这个需求其实很简单,但是还是需要对camera的设计流程有一定的了解,并且通过分析android原生的app,可以发现里面的设计思想真的很值得我们学习,就比如,executeRule(parameters, currentCameraId, key); 中当点击preview size时 会递归的再次调用onSettingChanged来切换 picture size 从而使picture size 和preview size 对应,可惜我的这个需求老板一直在催,就只是简单递归了一下,其实我觉得可以用更少的代码代替上面的那一堆的代码,待我闲时在分析吧。我要闪人了,连续一周加班到现在,当然今天是加班写博客 O(∩_∩)O哈哈~。
android 原生camera——设置模块修改的更多相关文章
- 修改Android 4.2.2的原生Camera引出的java.lang.UnsatisfiedLinkError: Native method not found,及解决方法
修改Android 4.2.2的原生Camera应用,做一些定制,将Camera的包名从之前的 package com.android.* 修改成了com.zhao3546.*. 调整后,应用可以正常 ...
- React Native Android原生模块开发实战|教程|心得|怎样创建React Native Android原生模块
尊重版权,未经授权不得转载 本文出自:贾鹏辉的技术博客(http://blog.csdn.net/fengyuzhengfan/article/details/54691503) 告诉大家一个好消息. ...
- 【转】eclipse android 设置及修改生成apk的签名文件 -- custom debug keystore
原文网址:http://hold-on.iteye.com/blog/2064642 android eclipse 设置及修改生成apk的签名文件 1. 问题: 平时在使用eclipse进行andr ...
- Android 系统默认参数的修改
转自: http://www.th7.cn/Program/Android/201505/447097.shtml 写在前面的话 一般在新项目开始之初,我们需要针对客户需求进行各种系统默认属性的配置, ...
- 【转】Android ROM研究---Android build system增加模块
原文网址:http://hualang.iteye.com/blog/1141315 Android build system就是编译系统的意思 在我们需要向自己编译的源代码中增加模块的时候,需要一些 ...
- Android 访问权限设置
Android开发应用程序时,有时我们要用到很多权限, 今天我就收集了一些开发时可能用到的开启权限设置. 这些权限都是在 AndroidManifest.xml设置. 设置方法 <uses-pe ...
- MTK6577+Android之Camera驱动
MTK6577+Android之Camera驱动 <MTK安卓平台的Camera效果在线调试> 1. Camera拍照相关概念 1.1 ISP isp--(Image Signa ...
- Android 开发权限设置中英对照说明详解
android.permission.ACCESS_CHECKIN_PROPERTIES 允许读写访问 "properties"表在checkin数据库中,改值可以修改上传( Al ...
- Android原生编解码接口 MediaCodec 之——踩坑
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/gb702250823/article/d ...
随机推荐
- C# QQ & 163 邮件发送
这篇文章的目的并不是说明如果进行右键的发送,因为在.net 坝坝的怀抱下邮件发送的功能实现并不会很难,当然邮件发送的代码,还是会贴上的,昨天在写一个邮件发送的功能,我直接找到了原来的代码,想着直接就可 ...
- C++ 多态的实现及原理
C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数.如果对象类型是派生类,就调用派生类的函数:如果对象类型是基类 ...
- 学习React系列(二)——深入了解JSX
1.JX实际上是React.createElement(component,props,...children)的语法糖 2.JSX判断是否为react组件的依据是标签首字母为大写(所以要求用户自定义 ...
- Multipath在OpenStack中的faulty device的成因及解决(part 2)
| 版权:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.如有问题,可以邮件:wangxu198709@gmail.com 简介 在上次的文章M ...
- [PA 2014]Iloczyn
Description 斐波那契数列的定义为:k=0或1时,F[k]=k:k>1时,F[k]=F[k-1]+F[k-2].数列的开头几项为0,1,1,2,3,5,8,13,21,34,55,…你 ...
- [SDOI2010]地精部落
题目描述 传说很久以前,大地上居住着一种神秘的生物:地精. 地精喜欢住在连绵不绝的山脉中.具体地说,一座长度为N的山脉H可分为从左到右的N段,每段有一个[b][u]独一无二[/u][/b]的高度Hi, ...
- bzoj 5248: [2018多省省队联测]一双木棋
Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何棋子, 两人轮流在格子上落子,直到填满棋盘时结束.落子的规则是:一个格子可以落子 ...
- ●BZOJ 2393 Cirno的完美算数教室
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2393 题解: 容斥原理,暴力搜索,剪枝...和 [Scoi2010 幸运数字] 一样的(只是 ...
- hdu2795 线段树 贴广告
Billboard Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 对中断的理解handle_level_irq【原创】
如下为本人原创,在解决问题的过程中的一点心得,如果有描述不准确的地方还请各位指出,非常感谢 Linux内核版本:linux-4.9.18 曾有一次调试触摸屏的时候遇到如下的问题 /startup/mo ...