Android 综合技术

栏目: Android · 发布时间: 5年前

内容简介:本篇主要介绍 Android 应用异常捕获、DEX 方法数越界、动态加载技术以及反编译相关的知识点。通过设置完整的 CrashHandler 示例可以点击

本篇主要介绍 Android 应用异常捕获、DEX 方法数越界、动态加载技术以及反编译相关的知识点。

使用 CrashHandler 来获取应用的 crash 信息

通过设置 Thead.setDefaultUncaughtExceptionHandler(handler) 的默认异常处理器就可以实现应用的异常捕获:

public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
         defaultUncaughtExceptionHandler = eh;
}

完整的 CrashHandler 示例可以点击 这里

使用 multidex 来解决方法数越界

Android 中单个 DEX 文件内可引用的方法总数限制在 65,536,如果方法数超过了最大值,那么编译会报 DexIndexOverflowException 。此外,在 Android 2.x 版本上由于 LinearAlloc 缓冲区分配过小也有可能导致安装失败。

解决 64K 限制

使用 Google 2014 年提出 multidex 解决方案,步骤如下:

  1. 如果 minSdkVersion 设置为 21 或更高值,只需在模块级 build.gradle 文件中将 multiDexEnabled 设置为 true 即可,如下所示:

    android {
        defaultConfig {
            ...
            minSdkVersion 21 
            targetSdkVersion 28
            multiDexEnabled true
        }
        ...
    }
    
  2. 如果 minSdkVersion 低于 21,除了将 multiDexEnabled 设置为 true ,还需要添加对 multidex jar 包的依赖:

    dependencies {
        compile 'com.android.support:multidex:1.0.3'
    }
    
  3. 同时还需要修改代码以适配 multidex,以下方式三选一:

    • AndroidManifest.xml 中指定 ApplicationMultiDexApplication

      <?xml version="1.0" encoding="utf-8"?>
      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.myapp">
          <application
              android:name="android.support.multidex.MultiDexApplication" >
          ...
          </application>
      </manifest>
      
    • 让应用的 Application 继承 MultiDexApplication

      public class MyApplication extends MultiDexApplication { ... }
      
    • 此外,还可以重写 ttachBaseContext 方法:

      public class MyApplication extends SomeOtherApplication {
          @Override
          protected void attachBaseContext(Context base) {
              super.attachBaseContext(base);
              MultiDex.install(this);
          }
      }
      

声明主 DEX 文件中需要的类

为 Dalvik 分包构建每个 DEX 文件时,构建 工具 会执行复杂的决策制定来确定主 DEX 文件中需要的类,以便应用能够成功启动。如果启动期间需要的某个类未在主 DEX 文件中提供,那么应用将崩溃并出现错误 java.lang.NoClassDefFoundError 。针对这种情况,我们可以使用构建类型中的 multiDexKeepFilemultiDexKeepProguard 属性声明它们,以手动将这些类指定为主 DEX 文件中的必需项,当然《Android 开发艺术探索》中提到的 --main-dex-list 方式也是同样的原理。

  1. multiDexKeepFile 属性

    创建一个名为 multidex-config.txt 的文件,如下所示:

    com/example/MyClass.class
    com/example/MyOtherClass.class
    

    然后在构建类型声明该文件即可:

    android {
        buildTypes {
            release {
                multiDexKeepFile file 'multidex-config.txt'
                ...
            }
        }
    }
    
  2. multiDexKeepProguard 属性

    建一个名为 multidex-config.pro 的文件,如下所示:

    -keep class com.example.MyClass
    -keep class com.example.MyClassToo
    

    如果想要指定包中的所有类,文件可以如下所示:

    -keep class com.example.** { *; }
    

    最后在构建类型声明该文件:

    android {
        buildTypes {
            release {
                multiDexKeepProguard 'multidex-config.pro'
                ...
            }
        }
    }
    

Multidex 方案可能带来的问题:

  1. 应用启动速度会降低。因为应用启动的时候会加载额外的 DEX 文件,所以要尽量避免生成较大的 DEX 文件;
  2. 由于 Dalvik LinearAlloc 的 bug,可能导致采用 multidex 方案的应用无法在 Android 4.0 以前的手机上运行,当然这种现象极少遇到。

Android 的动态加载技术

动态加载技术(插件化技术),即通过插件化减轻应用的内存和 CPU 占用,还可以在不发布新版本的情况下更新某些模块。不同的插件化方案各有特色,但是都需要解决三个基础性问题:资源访问,Activity 生命周期管理和插件 ClassLoader 的管理。

资源访问

宿主程序调起未安装的插件 apk,插件中凡是 R 开头的资源都不能访问了,因为宿主程序中并没有插件的资源,通过 R 来访问插件的资源是行不通的。由于 Activity 的资源访问都是通过 ContextImpl 来完成的,它有两个方法 getAssets()getResources() ,它们是用来加载资源的。 具体实现方式是通过反射,调用 AssetManager 的 addAssetPath 方法添加插件的路径,然后将插件 apk 中的资源加载到 Resources 对象中即可。

Activity 生命周期管理

管理 Activity 生命周期的方式各种各样,有两种常见的方式:反射方式和接口方式。反射方式就是通过反射去获取 Activity 的各个生命周期方法,然后在代理 Activity 中去调用插件 Activity 对应的生命周期方法即可。使用反射方式代码复杂,性能开销大。接口方式将 Activity 的生命周期方法提取出来作为一个接口,然后通过代理 Activity 去调用插件 Activity 的生命周期方法,这样就完成了插件 Activity 的生命周期管理。

插件 ClassLoader 的管理

为了更好地对多插件进行支持,需要合理地去管理各个插件的 DexClassLoader,这样同一个插件就可以采用同一个 ClassLoader 去加载类,从而避免了多个 ClassLoader 加载同一个类时所引起的类型转换错误。

更多信息可以参考开源项目 DL-Apk动态加载框架

反编译初步

三个常用的反编译工具如下:

  1. Apktoolhttps://ibotpeaches.github.io/Apktool/
  2. dex2jarhttps://github.com/pxb1988/dex2jar
  3. JD-GUIhttp://jd.benow.ca/

反编译流程:一种方式是将 apk 解压,提取出 classes.dex 文件,接着通过 dex2jar 反编译,然后通过 JD-GUI 打开反编译后的 jar 包。或者直接使用 apktool 对 apk 进行解包/二次打包,以及使用 jarsigner 完成 apk 的签名。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PHP经典实例(第3版)

PHP经典实例(第3版)

David Sklar、Adam Trachtenberg / 苏金国、丁小峰 / 中国电力出版社 / 2015-7 / 128.00

想要掌握PHP编程技术?或者想要学习如何完成一个特定的任务?那么一定要先看看《PHP经典实例(第3版)》。本书介绍了专门为PHP 5.4和5.5修订的350个经典技巧,并提供了丰富的示例代码。特别是对生成动态Web内容的解决方案做了全面更新,从使用基本数据类型到查询数据库,从调用RESTful API到测试和保护网站安全都有涵盖。 各个技巧都提供了示例代码,可以免费使用,另外还讨论了如何解决......一起来看看 《PHP经典实例(第3版)》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具