产品为一款基于android的交互终端,现在已经在android嵌入式系统上运行了一个第三方的交易软件(没有源码)。在产品量产投入使用时,可以实现以下两点需求:
设备开机时自动启动交易App。
由于产品投入市场之前,需要对系统的Framework进行定制,屏蔽设备的状态栏,这样如果不借助其他设备,我们就无法退出到系统的Launcher进行其他操作,但为了方便现场开发人员调试,有时候需要打开系统的Setting,希望可以找到一种通过某种方法调出系统Setting的方法。
针对需求1,解决思路为:
(1)自己创建一个App,在Manifest.xml文件下加入:
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.MONKEY"/>
<category android:name="android.intent.category.DEFAULT"/>
将我们的App提升为系统Launcher级别的App。
(2)获取第三方的交易软件的包名方法为打开第三方交易软件App,利用Adb工具输入指令:adb shell dumpsys activity | grep mFocusedActivity
会打印出类似下面的内容:
mFocusedActivity: ActivityRecord{42ddcd78 u0 com.android.mms/.ui.ConversationList t3}
即可得到返回栈栈顶,及当前活动的Acitivity的信息,信息为包名+活动名。获得包名和活动名之后,我们就可以得到完整的跳转代码,形式如:
Intent mIntent = new Intent();
ComponentName mComp = new ComponentName("包名", "活动名");
mIntent.setComponent(mComp);
mIntent.setAction(Intent.ACTION_VIEW);
startActivity(mIntent);
重写App的onCreate()和onResume()方法,加入上述跳转代码,即可完成开机时先自启自定义的App,然后自动跳转到第三方的交易软件。
(3)重写App的onCreate()和onResume()方法,加入上述跳转代码,即可完成开机时先自启自定义的App,然后自动跳转到第三方的交易软件。
针对第二个需求,找到一种方法,可以在运行交易软件的时候,通过某种方式调出系统Settings界面。我们想到的方法是
我们采用了第二种外接usb键盘实现跳转的方式。
但是,因为交易软件是第三方提供的,没有源码,不可能修改它完成键盘事件的监听,我们想到可不可以单独写一个服务来监听前台的键盘时间,然后实现跳转,但是感觉这种思路是不可能实现的,假如可以实现监听,那么我们运行一些App在输入密码的时候,这些信息不就被轻而易举的监听到了吗?后来证实了自己的假设,底层屏蔽了服务监听键盘事件的方式。那我们只能采取修改android系统的Framework层代码来实现键盘监听了。
首先需要了解andorid的键值上报流程,这里就不展开介绍了,直接说解决方案。首先,在android源码包下找到/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
文件,文件里有一个方法interceptKeyBeforeDispatching()
,方法名翻译成中文可以理解为在分发之前完成键值的拦截。通过在这个方法中加入我们的逻辑,就可以实现外接键盘实现程序Settings的跳转了。
在函数中添加下面的代码:
/**
* launch Setting:Ctrl+Alt+G
*/
if(event.isCtrlPressed() && event.isAltPressed() && keyCode == KeyEvent.KEYCODE_G && event.getAction() == KeyEvent.ACTION_UP)
{
Log.d(TAG,"---Ctrl+Alt+G is pressed---");
Intent mIntent = new Intent();
ComponentName mComp = new ComponentName("com.android.settings", "com.android.settings.Settings");
mIntent.setComponent(mComp);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mIntent.setAction("android.intent.action.MAIN");
mContext.startActivity(mIntent);
return -1;
}
意思是,当Ctrl+Alt+G
键同时按下时,会完成应用程序的跳转,跳转到android 的Settings程序。关于如果监听组合按键可以参考这篇文章:
android中捕获组合键
完成后,保存打开终端,先将目录切换到android源码包下,执行
$source build/envsetup
$lunch
然后将目录切换到/frameworks/base/policy/
,发现下面有个Android.mk
文件,我们打开这个文件,看源码:
LOCAL_PATH:= $(call my-dir)`
# the library
# ============================================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE := android.policy
include $(BUILD_JAVA_LIBRARY)
# additionally, build unit tests in a separate .apk
include $(call all-makefiles-under,$(LOCAL_PATH))
注意这两句话:
LOCAL_MODULE := android.policy
include $(BUILD_JAVA_LIBRARY)
意思是,编译后生成的文件名称叫做android.policy
扩展名为.jar
。
然后我们在终端中输入mm
单独编译模块。
生成的文件android.policy.jar
保存在android/out/target/product/system/framework
下面。我们可以直接连接设备把它push进我们的设备里,但是直接push存在一个问题,就是无法覆盖掉原有的文件。我们需要删除掉系统原来的android.policy.jar
文件,然后再把它push进去。方法为:
adb remount
adb shell
cd system/framework
rm android.policy.jar
exit
adb push /home/A64/andoroid/out/target/product/system/framework/android.policy.jar /system/framework
然后重启设备后,就发现外接键盘可以满足需求了。因为状态栏被屏蔽了,如果需要执行back键,只需要按下键盘的Esc键盘,android系统已经帮我们写好了。