最近有一个客户有这样的需求:

1、在【设置】--->【无障碍】中添加一个开关按钮。

如果打开开关的话,双击某个物理按键的时候,打开闪光灯,再双击该物理按键的时候,关闭闪光灯。

如果关闭开关的话,双击该物理按键的时候,不做任何处理。

2、打开关闭闪光灯的状态,在下拉菜单中也要同步。

如下图所示的效果:

当打开上面添加的开关后,如果双击POC键(POC键是我们公司自定义的一个物理按键)的时候,就打开闪光灯,并将下拉菜单中的闪光灯图标点亮,如下图所示

如果再次双击POC键(POC键是我们公司自定义的一个物理按键)的时候,就关闭闪光灯,并将下拉菜单中的闪光灯图标熄灭,如下图所示

====================================================================================================================================

下面来具体说说怎么实现该功能:

第一步:添加开关按钮布局

在packages/apps/Settings/res/xml/accessibility_settings.xml 文件中添加一个开关,开关位置放在【按电源按钮结束通话】和【自动选择屏幕】中间,代码如下

        <SwitchPreference
android:key="toggle_power_button_ends_call_preference"
android:title="@string/accessibility_power_button_ends_call_prerefence_title"
android:persistent="false"/>
<!-- added by ouyang start [2015-11-3] -->
<SwitchPreference
android:key="toggle_camera_button__start_flashlight_preference"
android:title="@string/accessibility_camera_button_start_flashlight_preference_title"
android:summary="@string/accessibility_camera_button_start_flashlight_preference_subtitle"
android:persistent="false"/>
<!-- added by ouyang end [2015-11-3] --> <SwitchPreference
android:key="toggle_lock_screen_rotation_preference"
android:title="@string/accelerometer_title"
android:persistent="false"/>

在packages/apps/Settings/res/values-zh-rCN/strings.xml文件中添加相应的字符串

    <!-- added by ouyang start [2015-11-3] -->
<string name="accessibility_camera_button_start_flashlight_preference_title">"双击[相机键]打开闪光灯"</string>
<string name="accessibility_camera_button_start_flashlight_preference_title_E580">"双击[POC键]打开闪光灯"</string>
<string name="accessibility_camera_button_start_flashlight_preference_subtitle">"开启此功能后,摄像机暂时无法使用"</string>
<!-- added by ouyang end [2015-11-3] -->

packages/apps/Settings/res/values/strings.xml文件中添加相应的字符串

    <!-- added by ouyang start [2015-11-3] -->
<string name="accessibility_camera_button_start_flashlight_preference_title">"Camera button twice,open flash light"</string>
<string name="accessibility_camera_button_start_flashlight_preference_title_E580">"POC button twice,open flash light"</string>
<string name="accessibility_camera_button_start_flashlight_preference_subtitle">"After open this feature, the camera can not be used"</string>
<!-- added by ouyang end [2015-11-3] -->

第二步:对该开关按钮做逻辑处理,在packages/apps/Settings/src/com/android/settings/accessibility/AccessibilitySettings.java文件中

先定义一个字符串常量,该常量为添加的开关的key,定义该按钮开关常量和SharedPreences常量,用来保存该按钮打开关闭状态值

    // added by ouyang start [2015-11-3]
private static final String TOGGLE_CAMER_BUTTON_START_FLASHLIGHT_PREFERENCE =
"toggle_camera_button__start_flashlight_preference";
// added by ouyang end [2015-11-3]
    // added by ouyang start [2015-11-3]
private SwitchPreference mToggleCameraButtonStartFlashlightPreference;
private SharedPreferences preferences;
private SharedPreferences.Editor editor;
// added by ouyang end [2015-11-3]

通过该字符串找到定义的开关,并做些处理,如从保存好的Perference中读取开关打开关闭状态并显示,在initializeAllPreferences方法中,添加如下代码

// added by ouyang start [2015-11-3]
mToggleCameraButtonStartFlashlightPreference =
(SwitchPreference) findPreference(TOGGLE_CAMER_BUTTON_START_FLASHLIGHT_PREFERENCE);
if (android.os.SystemProperties.isHanbangVersion()) {
Log.e(TAG, "is HanbangVersion()");
mToggleCameraButtonStartFlashlightPreference.setEnabled(false);
}else{
Log.e(TAG, "is not HanbangVersion()");
mToggleCameraButtonStartFlashlightPreference.setEnabled(true);
}
Log.e(TAG, "mToggleCameraButtonStartFlashlightPreference.isEbable="+ mToggleCameraButtonStartFlashlightPreference.isEnabled());
if (android.os.SystemProperties.isDT800Project()) {
mToggleCameraButtonStartFlashlightPreference.setTitle(R.string.accessibility_camera_button_start_flashlight_preference_title);
}else if (android.os.SystemProperties.isE580Project()) {
mToggleCameraButtonStartFlashlightPreference.setTitle(R.string.accessibility_camera_button_start_flashlight_preference_title_E580);
}
preferences= getActivity().getApplicationContext().getSharedPreferences("FlashLight",
Context.MODE_MULTI_PROCESS
+Context.MODE_WORLD_READABLE
+Context.MODE_WORLD_WRITEABLE);
editor=preferences.edit();
boolean flashChecked=preferences.getBoolean("flashChecked", false);
mToggleCameraButtonStartFlashlightPreference.setChecked(flashChecked);
Log.e(TAG, "flashChecked="+flashChecked);
// added by ouyang end [2015-11-3]

这段代码主要是对该开关进行初始化,并对不同的项目进行判断,DT800项目和E580项目加载不同的字符串来描述开关。这些方法可以在/frameworks/base/core/java/android/os/SystemProperties.java文件中自己添加,代码如下:

       public static boolean isDT800Project() {
return SystemProperties.get("ro.custom.build.version").contains("DT800");
} public static boolean isE580Project() {
return SystemProperties.get("ro.custom.build.version").contains("E580");
} public static boolean isHanbangVersion(){
return SystemProperties.get("ro.product.model").contains("Hanbang");
}

在packages/apps/Settings/src/com/android/settings/accessibility/AccessibilitySettings.java文件中的onPreferenceTreeClick方法中,要添加对该开关的点击事件处理。

代码如下,添加几行代码:

else if (mTogglePowerButtonEndsCallPreference == preference) {
handleTogglePowerButtonEndsCallPreferenceClick();
return true;
}
// added by ouyang start [2015-11-3]
else if (mToggleCameraButtonStartFlashlightPreference == preference) {
handleToggleCameraButtonStartFlashlightPreferenceClick();
return true;
}
// added by ouyang end [2015-11-3]
else if (mToggleLockScreenRotationPreference == preference) {
handleLockScreenRotationPreferenceClick();
return true;
}

其中handleToggleCameraButtonStartFlashlightPreferenceClick()方法自己自定义的,代码如下:

   // added by ouyang start [2015-11-3]
private void handleToggleCameraButtonStartFlashlightPreferenceClick(){
if (mToggleCameraButtonStartFlashlightPreference.isChecked()) {
editor.putBoolean("flashChecked", true);
editor.commit();
}else{
editor.putBoolean("flashChecked", false);
editor.commit();
}
}
// added by ouyang end [2015-11-3]

该方法主要功能是保存该开关是打开状态还是关闭状态,这个状态值可以让其他的进程读取。

第三步:定义一个BroadcastReceiver,并动态注册该广播。代码文件在frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java

,在该文件中添加一个BroadcastReceiver

 //added by ouyang
private final BroadcastReceiver mFlashBroadcastReceiver =new BroadcastReceiver(){
boolean isDoublePress = false;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action= " + action);
Log.d(TAG, "isDoublePress= " + isDoublePress);
Log.d(TAG, "now time = " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS").format(new Date()));
if ((action == "com.runbo.camera.key.up") || (action == "com.runbo.poc.key.up")) {
Handler checkHandler = new Handler();
if (!isDoublePress) {
isDoublePress = true;
Log.i(TAG, "<----===============Single Press the Camera Key---->");
Runnable CheckDoubleRunnable = new Runnable() {
@Override
public void run() {
isDoublePress = false;
}
};
checkHandler.postDelayed(CheckDoubleRunnable, 500);
} else {
isDoublePress = false;
Log.i(TAG, "<----============Double Press the Camera Key ---->");
boolean handlerReceiver = false;
boolean flashChecked=false;
try {
Context myContext= context.createPackageContext("com.android.settings",
Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = myContext.getSharedPreferences("FlashLight",
Context.MODE_WORLD_READABLE | Context.MODE_MULTI_PROCESS);
flashChecked = sharedPreferences.getBoolean("flashChecked", false);
} catch (Exception e) {
Log.d(TAG, Log.getStackTraceString(e));
}
if (action == "com.runbo.camera.key.up") {
if (android.os.SystemProperties.isDT800Project()
&& !android.os.SystemProperties.isHanbangVersion()) {
handlerReceiver = true;
}
} else if (action == "com.runbo.poc.key.up") {
if (android.os.SystemProperties.isE580Project()) {
handlerReceiver = true;
}
}
Log.d(TAG, "handlerReceiver= " + handlerReceiver);
Log.d(TAG, "flashChecked= " + flashChecked);
if (handlerReceiver && flashChecked) {
Log.i(TAG, "============mState.value="+mState.value);
if (!mState.value) {
boolean newState = !mState.value;
mFlashlightController.setFlashlight(newState);
refreshState(newState ? UserBoolean.USER_TRUE : UserBoolean.USER_FALSE);
Log.i(TAG, "============setFlashlight(true);============");
}else{
boolean newState = !mState.value;
mFlashlightController.setFlashlight(newState);
refreshState(newState ? UserBoolean.USER_TRUE : UserBoolean.USER_FALSE);
Log.i(TAG, "============setFlashlight(false);============");
}
}
}
}
}
};

在FlashlightTile的构造方法中进行注册,代码如下:

  public FlashlightTile(Host host) {
super(host);
mFlashlightController = host.getFlashlightController();
mFlashlightController.addListener(this); //added by ouyang start
IntentFilter pocFilter = new IntentFilter();
pocFilter.addAction("com.runbo.poc.key.up");
pocFilter.addAction("com.runbo.camera.key.up");
this.mContext.registerReceiver(mFlashBroadcastReceiver, pocFilter);
Log.d(TAG, "registerReceiver(mFlashBroadcastReceiver, pocFilter)");
//added by ouyang end
}

该BroadcastReceiver接收通过按POC键后释放而发送的广播“com.runbo.poc.key.up”和通过按Camera键后释放而发送的广播“com.runbo.camera.key.up”,这两个广播是自定义的广播。然后判断是单击还是双击,当双击后再通过读取SharedPreferences的值来判断定义的开关是否是打开的,如果开关是打开的再判断闪光灯是打开还是关闭,如果是打开的,双击后就关闭闪光灯。如果是关闭的,就打开闪光灯。并更新下拉菜单的图标和相应的状态。如果开关是关闭的,不进行打开关闭闪光灯的操作。

这两个广播是在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java文件中的interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)方法中额外添加的代码,发送广播出来的。

====================================================================================

  作者:欧阳鹏  欢迎转载,与人分享是进步的源泉!

  转载请保留原文地址:http://blog.csdn.net/ouyang_peng

====================================================================================

Android系统移植与调试之------->增加一个双击物理按键打开和关闭闪光灯并将闪光灯状态同步到下拉菜单中的更多相关文章

  1. Android系统移植与调试之------->如何修改Android手机NFC模块,使黑屏时候能够使用NFC

    我们都知道在不修改源代码的情况下,只能是解锁之后才能使用NFC功能.而在锁屏和黑屏2个状态下是没办法用NFC的,但是最近有个客户要求手机在黑屏状态下能够使用NFC,因此我们需要去修改Android源代 ...

  2. Android系统移植与调试之------->如何添加一个adb wifi无线调试的功能【开发者选项】-【Wifi调试】

    首先弄懂怎么设置adb wifi无线调试的功能,如下所示. 1. 手机端开启adb tcp连接端口 :/$setprop service.adb.tcp.port :/$stop adbd :/$st ...

  3. [置顶] Android系统移植与调试之------->Amlogic方案编译步骤

    1. 拷贝Amlogic的SourceCode 切换目录到  /home/roco/work/amlogic/SourceCode/mx0831-0525下将mx0831-0525.tgz拷贝到  / ...

  4. Android系统移植与调试之------->Amlogic方案编译步骤

    1. 拷贝Amlogic的SourceCode 切换目录到  /home/roco/work/amlogic/SourceCode/mx0831-0525下将mx0831-0525.tgz拷贝到  / ...

  5. [置顶] Android系统移植与调试之------->build.prop文件详细赏析

    小知识:什么是build.prop?   /system/build.prop 是一个属性文件,在Android系统中.prop文件很重要,记录了系统的设置和改变,类似於/etc中的文件.这个文件是如 ...

  6. Android系统移植与调试之------->build.prop文件详细赏析

    小知识:什么是build.prop?   /system/build.prop 是一个属性文件,在Android系统中.prop文件很重要,记录了系统的设置和改变,类似於/etc中的文件.这个文件是如 ...

  7. Android系统移植与调试之------->如何修改Android手机显示的4G信号强度的格子数

    在修改显示的信号强度之前,先了解一下什么是dB,什么是dBm? 1.dB dB是一个表征相对值的值,纯粹的比值,只表示两个量的相对大小关系,没有单位,当考虑甲的功率相比于乙功率大或小多少个dB时, 按 ...

  8. Android系统移植与调试之------->build.prop生成过程分析

    本文简要分析一下build.prop是如何生成的.Android的build.prop文件是在Android编译时刻收集的各种property(LCD density/语言/编译时间, etc.),编 ...

  9. [置顶] Android系统移植与调试之------->如何修改Android设备状态条上音量加减键在横竖屏的时候的切换与显示

    这两天由于一个客户的要求,将MID竖屏时候的状态条上的音量键去掉.所以尝试修改了一下,成功了,分享一下经验. 先看一下修改后的效果图,如下所示 . 横屏的时候:有音量加减键 竖屏的时候:音量加减键被去 ...

随机推荐

  1. ST股福音:涨停潮开始! 最全ST摘帽股汇总!

    本周ST股摘帽行情提前预演,ST股上演涨停潮,部分ST股甚至出现连续涨停.云财经在三季报披露之前曾经做过一期ST股摘帽分析,在三季报正式披 露完毕后,以及部分ST公司公布了2015年年报预告,ST股能 ...

  2. POJ 2528 Mayor&#39;s posters 离散化+线段树

    题目大意:给出一些海报和贴在墙上的区间.问这些海报依照顺序贴完之后,最后能后看到多少种海报. 思路:区间的范围太大,然而最多仅仅会有10000张海报,所以要离散化. 之后用线段树随便搞搞就能过. 关键 ...

  3. QT错误笔记-Qt Creator needs a compiler set up to build. Configure a compiler in the kit options.

    上午在linux环境下,使用QT编译一段C++代码,出现下列错误: 最近在stackoverflow上找到了答案: i was also having the same problem so what ...

  4. composer 初始化办法和方法

    php -r "readfile('https://getcomposer.org/installer');" > composer-setup.php php -r &qu ...

  5. c++如何new构造函数是protected的对象

    如果确实要new的话,可以继承这个类,然后new派生类,再转换为基类指针

  6. ubuntu下软件安装

    1. 软件源:ubuntu.cn99.com/ubuntu2. 安装vncviewer    sudo apt-get install vncviewer3. aptitude     sudo ap ...

  7. error: xslt-config not found. Please reinstall the libxslt >= 1.1.0 distribution

    解决编译php扩展xsl时出现 error: xslt-config not found. Please reinstall the libxslt >= 1.1.0 distribution ...

  8. iOS开发之删除过期Provisioning Profiles方法

    1.在finder下打开go -> go to folder输入: ~/Library/MobileDevice/Provisioning Profiles 2.查看上面的列表,依照时间顺序删除 ...

  9. 配置LANMP环境(5)-- 安装NGINX与配置

    安装nginx yum install nginx 若提示找不到nginx,则在软件源中添加nginx的软件源文件: vim /etc/yum.repos.d/nginx.repo 添加如下内容: [ ...

  10. mySQL 开启事件存储过程

    怎样在Navicat中设置,是数据库按照记录中的日期更新状态字段 其实这个很常用,比如你网站里的某条记录的日期——比如说数据库中某条活动记录的审核日期字段已经过期,亦即当前时间已经超过审核日期,那么定 ...