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

简介: 最近有一个客户有这样的需求:1、在【设置】--->【无障碍】中添加一个开关按钮。            如果打开开关的话,双击某个物理按键的时候,打开闪光灯,再双击该物理按键的时候,关闭闪光灯。

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

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

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



相关文章
|
2月前
|
Android开发
基于android-11.0.0_r39,系统应用的手动签名方法和过程
本文介绍了基于Android 11.0.0_r39版本进行系统应用手动签名的方法和解决签名过程中遇到的错误,包括处理`no conscrypt_openjdk_jni-linux-x86_64`和`RegisterNatives failed`的问题。
91 2
|
2月前
|
JavaScript 前端开发 Java
[Android][Framework]系统jar包,sdk的制作及引用
[Android][Framework]系统jar包,sdk的制作及引用
43 0
|
2月前
|
Shell Linux 开发工具
"开发者的救星:揭秘如何用adb神器征服Android设备,开启高效调试之旅!"
【8月更文挑战第20天】Android Debug Bridge (adb) 是 Android 开发者必备工具,用于实现计算机与 Android 设备间通讯,执行调试及命令操作。adb 提供了丰富的命令行接口,覆盖从基础设备管理到复杂系统操作的需求。本文详细介绍 adb 的安装配置流程,并列举实用命令示例,包括设备连接管理、应用安装调试、文件系统访问等基础功能,以及端口转发、日志查看等高级技巧。此外,还提供了常见问题的故障排除指南,帮助开发者快速解决问题。掌握 adb 将极大提升 Android 开发效率,助力项目顺利推进。
52 0
|
12天前
|
监控 Android开发 iOS开发
深入探索安卓与iOS的系统架构差异:理解两大移动平台的技术根基在移动技术日新月异的今天,安卓和iOS作为市场上最为流行的两个操作系统,各自拥有独特的技术特性和庞大的用户基础。本文将深入探讨这两个平台的系统架构差异,揭示它们如何支撑起各自的生态系统,并影响着全球数亿用户的使用体验。
本文通过对比分析安卓和iOS的系统架构,揭示了这两个平台在设计理念、安全性、用户体验和技术生态上的根本区别。不同于常规的技术综述,本文以深入浅出的方式,带领读者理解这些差异是如何影响应用开发、用户选择和市场趋势的。通过梳理历史脉络和未来展望,本文旨在为开发者、用户以及行业分析师提供有价值的见解,帮助大家更好地把握移动技术发展的脉络。
|
8天前
|
Dart 开发工具 Android开发
在 Android 系统上搭建 Flutter 环境的具体步骤是什么?
在 Android 系统上搭建 Flutter 环境的具体步骤是什么?
|
1月前
|
Android开发 UED 开发者
Android经典实战之WindowManager和创建系统悬浮窗
本文详细介绍了Android系统服务`WindowManager`,包括其主要功能和工作原理,并提供了创建系统悬浮窗的完整步骤。通过示例代码,展示了如何添加权限、请求权限、实现悬浮窗口及最佳实践,帮助开发者轻松掌握悬浮窗开发技巧。
55 1
|
2月前
|
Java Android开发
全志 Android 11:实现响应全局按键
本文介绍了在全志平台Android 11上实现响应全局按键的方法,通过修改`TvWindowManager.java`来全局拦截特定的热键事件,并在`FocusActivity`中处理这些事件以启动调焦界面和控制步进电机调整焦距。
27 2
|
2月前
|
Java 物联网 Android开发
移动应用与系统:技术演进与未来展望探索安卓应用开发:从新手到专家的旅程
【8月更文挑战第28天】本文将深入探讨移动应用开发的技术演进、移动操作系统的发展历程以及未来的发展趋势。我们将通过实例和代码示例,展示如何利用最新的技术和工具来开发高效、可靠的移动应用。无论你是初学者还是经验丰富的开发者,这篇文章都将为你提供有价值的信息和见解。 【8月更文挑战第28天】在这个数字时代,掌握安卓应用的开发技能不仅是技术人员的追求,也成为了许多人实现创意和梦想的途径。本文将通过深入浅出的方式,带领读者从零基础开始,一步步走进安卓开发的奇妙世界。我们将探讨如何配置开发环境,理解安卓应用的核心组件,以及如何通过实际编码来构建一个功能完整的应用。无论你是编程新手还是希望提升自己的开发者
|
2月前
|
Ubuntu Android开发
安卓系统调试与优化:(一)bootchart 的配置和使用
本文介绍了如何在安卓系统中配置和使用bootchart工具来分析系统启动时间,包括安装工具、设备端启用bootchart、PC端解析数据及分析结果的详细步骤。
86 0
安卓系统调试与优化:(一)bootchart 的配置和使用
|
2月前
|
存储 安全 物联网
Android经典实战之跳转到系统设置页面或其他系统应用页面大全
本文首发于公众号“AntDream”,关注获取更多技巧。文章总结了Android开发中跳转至系统设置页面的方法,包括设备信息、Wi-Fi、显示与声音设置等,并涉及应用详情与电池优化页面。通过简单的Intent动作即可实现,需注意权限与版本兼容性。每日进步,尽在“AntDream”。
179 2
下一篇
无影云桌面