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

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

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的值来判断定义的开关是否是打开的,如果开关是打开的再判断闪光灯是打开还是关闭,如果是打开的,双击后就关闭闪光灯。如果是关闭的,就打开闪光灯。并更新下拉菜单的图标和相应的状态。如果开关是关闭的,不进行打开关闭闪光灯的操作。

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

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

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

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

版权声明:本文为欧阳鹏原创文章,欢迎转载,转载请注明出处! http://blog.csdn.net/ouyang_peng

时间: 2024-12-17 23:16:48

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

Android系统移植与调试之-------&gt;如何修改开机动画的两种方式剖析【转】

本文转载自:http://blog.csdn.net/ouyang_peng/article/details/9564753 首先,我们先来分析一下源码: frameworks/base/cmds/bootanimation/BootAnimation.cpp 首先看一下定义的常量: BootAnimation::readyToRun() 进入一个if判断语句 BootAnimation::threadLoop() ==> BootAnimation::Android()会加载"image

Android系统移植与调试之-------&gt;如何修改Android系统默认显示【开发者选项】并默认打开【USB调试】和【未知来源】开关

今天有个用户对[设置]有个特殊的要求,即: 1.开机的时候默认显示[开发者选项]并打开[USB调试]开关    ([Developer options]-->[USB debugging]) 2.开机的时候默认打开[安全]-->[未知来源]的开关    ([Security]--->[Unknown sources]) 1.首先解决[设置]界面默认显示[开发者选项]的问题 查看源代码:packages/apps/Settings/src/com/android/settings/Sett

Android 系统移植与调试(一)Android编译环境编译服务器搭建

1.ubuntu系统安装 android 编译官方推荐 64bit的编译. Ubuntu 建议安装 12.04 的 64 位版,可用 ultraiso 等工具制作 U 盘启动盘. 安装与一般Ubuntu系统安装一致,这里不做赘述! 2. Ubuntu 环境搭建 代码的编译需要在 Ubuntu 64 位系统下进行,所以环境搭建以 ubuntu 系统为主. 2.1. Ubuntu 基础工具 在ubuntu 命令窗口输入下面的命令,安装一些基础的工具.等待安装完毕,可以继续下一步: sudo apt-

Android系统移植:驱动篇

[导语]在Android系统移植中,有很重要的一个部分工作,就是为新平台上的硬件设备移植驱动程序.因为Android系统是基于Linux kernel内核构建,所以这里说的移植驱动程序,其实就是基于Android系统平台开发适应移动设备的Linux内核驱动程序. 一. Android系统中Linux内核与设备驱动 Android系统中使用了Linux内核作为自己的操作系统,除了linux的通用代码之外,主要还包含三个方面的东西: 体系结构和处理器 体系结构处理器和标准的设备驱动程序这两个方面是和

Android系统移植与驱动开发

Android是基于Linux的操作系统,底层是Linux内核层(Linux2.6, Linux3.4等),android使用了Linux操作系统的内核和驱动,其中驱动部分除了Linux的设备驱动,android还增加了专用驱动(例如Binder实现进程间通信).学习驱动之前,必须先了解linux内核,然后针对其运行方式进行探究. Android系统移植是在某一个特定的平台上运行特定的Android操作系统,因此需要特定的linux驱动促使linux内核支持Android识别不同的硬件平台. L

概述 Android系统移植与驱动开发

第一章主要概述绍了Android系统移植与驱动开发和我们之前课上的内容大同小异,Android的系统架构分为四层:Linux内核(Android使用Linux2.系列作为内核).C/C++代码库.Android SDK API(JAVA编写的Library).应用程序. 而Android移植分为系统移植 和 应用移植,在移植中,Android在不同的cpu架构之间 不需要 做过多的改动(有时仍需要一些调整),也是为了可以让Android支持不同的硬件平台,当然我们还需要进行Linux驱动移植.A

Android系统移植与驱动开发概述

1.1android系统架构 第一层 linux内核:驱动程序以及管理内存.进程.电源等资源的程序 第二层 c/c++代码库 linux的.so文件以及嵌入到APK程序中的NDK代码 第三层 android SDK API直接面向应用程序的JAVA APK 第四层 应用程序 1.2Android系统移植的主要工作 系统移植:让android操作系统在某一个特定平台上运行,条件是 操作系统支持硬件平台的CPU架构.移植linux驱动.移植HAL(HAL位于第二层,android SDK通过HAL直

学习Android系统移植与驱动开发的心得1

首先,学习Android系统移植与驱动开发,我们需要了解两个概念.什么是“移植”?由于Android原生的代码支持的设备并不多,因此我们想要在自己的设备上完美运行Android,就需要另外开发一些程序,使得Android可以识别相应设备中的各种硬件,这个过程被称为“移植”.在这个移植的过程中,我们必需要了解另外一个知识,就是“驱动开发”(Android是基于Linux内核的).到底什么是“Linux驱动”呢?作为初学者,我们只需要知道任何的Linux驱动都有一个加载函数和一个卸载函数即可,它们分

Android系统移植与驱动开发----第一章

第一章 Android系统移植与驱动开发 Android源代码定制完全属于自己的嵌入式系统,但是支持的设备不多,所以要移植,而在移植的过程中使用的不得不提的是驱动开发. Android系统构架主要包括四个层次:Linux内核,C/C++代码库,Android SDK API,应用程序.在第一层Linux中主要包括驱动程序,内存管理,进程管理,电源管理等程序,但是不同版本的系统则驱动也不相同,切记不可通用.在第二层C/C++代码库中有.so文件和虚拟机的Runtime,第三层的java语言是基于l