最近基于Android4.0,移植了一个长按返回键结束程序的功能。在这里分享一下。希望能对有需要的朋友有所帮助。

在正式开始移植工作之前,你需要了解:1、Android framework 编译以及反编译过程 2、有一定的Android开发基础和汇编知识(保证你能读懂Dalvik Code) 3、你能耐得住性子

Android4.0中,关于按键部分的功能实现在PhoneWindowManager中实现的。

第一步:

在#instance fields下增加

.field mBackKillTimeout:Z

.field mBackLongPress:Ljava/lang/Runnable;

 在.method public constructor ()V中增加

    new-instance v0, Lcom/android/internal/policy/impl/PhoneWindowManager$KillConcept;
    invoke-direct {v0, p0}, Lcom/android/internal/policy/impl/PhoneWindowManager$KillConcept;->(Lcom/android/internal/policy/impl/PhoneWindowManager;)V
    iput-object v0, p0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBackLongPress:Ljava/lang/Runnable;

上面增加的代码翻译过来就是下面两行

boolean mBackKillTimeout;  Runnable mBackLongPress = new KillConcept();

第二步:这步是最复杂,也是最关键的一步

在.method public interceptKeyBeforeDispatching方法中增加

   #Modify by wayne   :cond_37e    const/16 v28, 0x4    move/from16 v0, v28    move/from16 v1, v13    if-ne v1, v0, :cond_47e    .line 1863    move-object/from16 v0, p0    iget-boolean v0, v0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBackKillTimeout:Z    move/from16 v28, v0    if-nez v28, :cond_47e    if-eqz v6, :cond_47e    if-nez v18, :cond_47e    .line 1864    move-object/from16 v0, p0    iget-object v0, v0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mHandler:Landroid/os/Handler;    move-object/from16 v23, v0    move-object/from16 v0, p0    iget-object v0, v0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBackLongPress:Ljava/lang/Runnable;    move-object/from16 v24, v0    invoke-static {}, Landroid/view/ViewConfiguration;->getGlobalActionKeyTimeout()J    move-result-wide v25    invoke-virtual/range {v23 .. v26}, Landroid/os/Handler;->postDelayed(Ljava/lang/Runnable;J)Z    .line 1865    const/16 v28, 0x1    move/from16 v0, v28    move-object/from16 v1, p0    iput-boolean v0, v1, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBackKillTimeout:Z    #end modify


    这里的插入点是在下面这段代码后:

    

if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {                final long now = SystemClock.uptimeMillis();final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;                if (now < timeoutTime) {                    return timeoutTime - now;                }      }

      插入的代码应该是:

   

if((keyCode == KeyEvent.KEYCODE_BACK) && (!down) && ((flags & KeyEvent.FLAG_CANCELED) == 0)) {        this.mHandler.removeCallbacks(this.mBackLongPress);        KeyEvent.changeFlags(paramKeyEvent, m + 32);        this.mBackKillTimeout = false;     }

        


接下来,我们还需要插入一段代码:

     #Modify by wayne    :cond_37e    const/16 v28, 0x4    move/from16 v0, v28    move/from16 v1, v13    if-ne v1, v0, :cond_47e    .line 1863    move-object/from16 v0, p0    iget-boolean v0, v0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBackKillTimeout:Z    move/from16 v28, v0    if-nez v28, :cond_47e    if-eqz v6, :cond_47e    if-nez v18, :cond_47e    .line 1864    move-object/from16 v0, p0    iget-object v0, v0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mHandler:Landroid/os/Handler;    move-object/from16 v23, v0    move-object/from16 v0, p0    iget-object v0, v0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBackLongPress:Ljava/lang/Runnable;    move-object/from16 v24, v0    invoke-static {}, Landroid/view/ViewConfiguration;->getGlobalActionKeyTimeout()J    move-result-wide v25    invoke-virtual/range {v23 .. v26}, Landroid/os/Handler;->postDelayed(Ljava/lang/Runnable;J)Z    .line 1865    const/16 v28, 0x1    move/from16 v0, v28    move-object/from16 v1, p0    iput-boolean v0, v1, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBackKillTimeout:Z    #end modify


插入点是:

// Handle application launch keys.        if (down && repeatCount == 0 && !keyguardOn) {            String category = sApplicationLaunchKeyCategories.get(keyCode);            if (category != null) {                Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                try {                    mContext.startActivity(intent);                } catch (ActivityNotFoundException ex) {                    Slog.w(TAG, "Dropping application launch key because "                            + "the activity to which it is registered was not found: "                            + "keyCode=" + keyCode + ", category=" + category, ex);                }                return -1;            }        }


插入的代码是:

   

 if(down && repeatCount == 0 && !this.mBackKillTimeout && keyCode == KeyEvent.KEYCODE_BACK) {this.mHandler.postDelayed(this.mBackLongPress, ViewConfiguration.getGlobalActionKeyTimeout());        this.mBackKillTimeout = true;}

 第三步:新增一个内部类KillConcept,点击链接下载,解压缩后将得到的文件放在你反编译后的目录里。最后回编译为dex文件,检查没有错误后直接拖进并替换到android.policy.jar里,最后就是推送到系统里面啦。

下载地址:http://pan.baidu.com/share/link?shareid=436238&uk=3104024337

整个移植过程中,第二步是最复杂的地方。任何一个错误都可能会引起编译不通过,特别是使用的寄存器地址,因为不能保证每一台机器反编译出来的代码中都是使用的同样的寄存器地址,具体情况要具体分析。

更多相关文章

  1. 我在51CTO的第一篇博客--关于6个小时调试一个小类
  2. Android(安卓)productFlavors 差异化打包
  3. 为什么我们可以在非UI线程中更新UI
  4. 基于web的android图像处理示例(Win7+Apache+PHP+Matlab+Android)
  5. Android实现使用微信登录第三方APP的方法
  6. Android(安卓)Studio 单元测试入门
  7. 如何编写高效的Android代码
  8. Android(安卓)Async HTTP Clients: Volley vs Retrofit
  9. android application类和全局数据使用

随机推荐

  1. travis-ci如何配置android
  2. Android(安卓)屏幕滑动事件
  3. Android(安卓)listview分割线的颜色设置
  4. android service 实例
  5. Android的NDK开发(5)————Android(安
  6. android仿ios弹性页
  7. Android利用tcpdump抓包
  8. 操作 Calendar事件
  9. android 编译内核
  10. Android版本检测\自动更新 (转的别人的)