Android 综合技术

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

内容简介:本篇主要介绍 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 的签名。


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

查看所有标签

猜你喜欢:

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

Java核心技术·卷 I(原书第10版)

Java核心技术·卷 I(原书第10版)

[美] 凯.S.霍斯特曼(Cay S. Horstmann) / 周立新 等 / 机械工业出版社 / 2016-9 / CNY 119.00

Java领域最有影响力和价值的著作之一,由拥有20多年教学与研究经验的资深Java技术专家撰写(获Jolt大奖),与《Java编程思想》齐名,10余年全球畅销不衰,广受好评。第10版根据Java SE 8全面更新,同时修正了第9版中的不足,系统全面讲解了Java语言的核 心概念、语法、重要特性和开发方法,包含大量案例,实践性强。 一直以来,《Java核心技术》都被认为是面向高级程序员的经典教......一起来看看 《Java核心技术·卷 I(原书第10版)》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

MD5 加密
MD5 加密

MD5 加密工具