• Android编程之常识


    1,什么是混淆编译
    ProGuard是一个免费的java类文件压缩,优化,混淆器.它探测并删除没有使用的类,字段,方法和属性.它删除没有用的说明并使用字节码得到最大优化.它使用无意义的名字来重命名类,字段和方法.
    ProGuard的使用是为了:
    1.创建紧凑的代码文档是为了更快的网络传输,快速装载和更小的内存占用.
    2.创建的程序和程序库很难使用反向工程.
    3.所以它能删除来自源文件中的没有调用的代码
    4.充分利用java6的快速加载的优点来提前检测和返回java6中存在的类文件.
     
    ProGuard支持那些种类的优化:
    除了在压缩操作删除的无用类,字段和方法外,ProGuard也能在字节码级提供性能优化,内部方法有:
    1 常量表达式求值
    2 删除不必要的字段存取
    3 删除不必要的方法调用
    4 删除不必要的分支
    5 删除不必要的比较和instanceof验证
    6 删除未使用的代码
    7 删除只写字段
    8 删除未使用的方法参数
    9 像push/pop简化一样的各种各样的peephole优化
    10 在可能的情况下为类添加static和final修饰符
    11 在可能的情况下为方法添加private, static和final修饰符
    12 在可能的情况下使get/set方法成为内联的
    13 当接口只有一个实现类的时候,就取代它
    14 选择性的删除日志代码
    实际的优化效果是依赖于你的代码和执行代码的虚拟机的。简单的虚拟机比有复杂JIT编译器的高级虚拟机更有效。无论如何,你的字节码会变得更小。
     
    需要优化的不被支持技术: 
    1 使非final的常量字段成为内联
    2 像get/set方法一样使其他方法成为内联
    3 将常量表达式移到循环之外
    4 Optimizations that require escape analysis 
     
    2,启动android中的混淆功能
    在需要混淆的工程目录下(package/apps/下的工程)添加proguard.flags文件,该文件即为网络传说中的proguard.cfg,只是命名不一样而已,然后再Android.mk中添加如下两句:
    LOCAL_PROGUARD_ENABLED := full
    LOCAL_PROGUARD_FLAG_FILES := proguard.flags
    上面的full 也可以是custom,如果不写这句,那还得添加如下一句:
    TARGET_BUILD_VARIANT := user或者TARGET_BUILD_VARIANT := userdebug
    这样后在工程目录下执行mm便可以看到在out目录下生成了形如proguard.classes.jar的东东,这就说明已在编译中启动了proguard
    但反编译一看,并未出现网络云说的abcd替代符号,其实代码并未真正混淆:
    android在编译时默认关闭了混淆选项,有去研究build/core目录的同志会发现这里也有个proguard.flags文件,其实在proguard的过程中,编译器会调用包括本地目录下和系统定义了的多个proguard.flags文件,而在这个文件中混淆的选项被禁止了,故而编译出来的apk仍未混淆。因此将如下句子注释掉便可实现真正的混淆编译:
    # Don't obfuscate. We only need dead code striping.
    -dontobfuscate(将该句加个#号注释掉)
     
    为什么TARGET_BUILD_VARIANT := user和LOCAL_PROGUARD_ENABLED := full二选一即可,详见build/core/package.mk:
     
    LOCAL_PROGUARD_ENABLED:=$(strip $(LOCAL_PROGUARD_ENABLED))
    ifndef LOCAL_PROGUARD_ENABLED
    ifneq ($(filter user userdebug, $(TARGET_BUILD_VARIANT)),)
    # turn on Proguard by default for user & userdebug build
    LOCAL_PROGUARD_ENABLED :=full
    endif
    endif
    ifeq ($(LOCAL_PROGUARD_ENABLED),disabled)
    # the package explicitly request to disable proguard.
    LOCAL_PROGUARD_ENABLED :=
    endif
    proguard_options_file :=
    ifneq ($(LOCAL_PROGUARD_ENABLED),custom)
    ifneq ($(all_resources),)
    proguard_options_file := $(package_expected_intermediates_COMMON)/proguard_options
    endif # all_resources
    endif # !custom
    LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
     
    3,混淆代码含义
    参数解释:
    -include {filename}    从给定的文件中读取配置参数
    -basedirectory {directoryname}    指定基础目录为以后相对的档案名称
    -injars {class_path}    指定要处理的应用程序jar,war,ear和目录
    -outjars {class_path}    指定处理完后要输出的jar,war,ear和目录的名称
    -libraryjars {classpath}    指定要处理的应用程序jar,war,ear和目录所需要的程序库文件
    -dontskipnonpubliclibraryclasses    指定不去忽略非公共的库类。
    -dontskipnonpubliclibraryclassmembers    指定不去忽略包可见的库类的成员。
    保留选项
    -keep {Modifier} {class_specification}    保护指定的类文件和类的成员
    -keepclassmembers {modifier} {class_specification}    保护指定类的成员,如果此类受到保护他们会保护的更好
    -keepclasseswithmembers {class_specification}    保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。
    -keepnames {class_specification}    保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除)
    -keepclassmembernames {class_specification}    保护指定的类的成员的名称(如果他们不会压缩步骤中删除)
    -keepclasseswithmembernames {class_specification}    保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后)
    -printseeds {filename}    列出类和类的成员-keep选项的清单,标准输出到给定的文件
    压缩
    -dontshrink    不压缩输入的类文件
    -printusage {filename}
    -whyareyoukeeping {class_specification}    
    优化
    -dontoptimize    不优化输入的类文件
    -assumenosideeffects {class_specification}    优化时假设指定的方法,没有任何副作用
    -allowaccessmodification    优化时允许访问并修改有修饰符的类和类的成员
    混淆
    -dontobfuscate    不混淆输入的类文件
    -printmapping {filename}
    -applymapping {filename}    重用映射增加混淆
    -obfuscationdictionary {filename}    使用给定文件中的关键字作为要混淆方法的名称
    -overloadaggressively    混淆时应用侵入式重载
    -useuniqueclassmembernames    确定统一的混淆类的成员名称来增加混淆
    -flattenpackagehierarchy {package_name}    重新包装所有重命名的包并放在给定的单一包中
    -repackageclass {package_name}    重新包装所有重命名的类文件中放在给定的单一包中
    -dontusemixedcaseclassnames    混淆时不会产生形形色色的类名
    -keepattributes {attribute_name,...}    保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.
    -renamesourcefileattribute {string}    设置源文件中给定的字符串常量

    4,问题集

    Proguard returned with error code 1. See console
    Warning: com.baidu.mapapi.utils.h: can't find referenced class android.os.storage.StorageManager
    Warning: com.baidu.mapapi.utils.h: can't find referenced method 'boolean isExternalStorageRemovable()' in class android.os.Environment
    Warning: com.nostra13.universalimageloader.core.decode.ImageDecodingInfo: can't find referenced field 'boolean inPreferQualityOverSpeed' in class android.graphics.BitmapFactory$Options
    Warning: com.nostra13.universalimageloader.core.decode.ImageDecodingInfo: can't find referenced field 'android.graphics.Bitmap inBitmap' in class android.graphics.BitmapFactory$Options
    Warning: com.nostra13.universalimageloader.core.decode.ImageDecodingInfo: can't find referenced field 'boolean inMutable' in class android.graphics.BitmapFactory$Options
          You should check if you need to specify additional program jars.
    Warning: there were 1 unresolved references to classes or interfaces.
             You may need to specify additional library jars (using '-libraryjars').
    Warning: there were 4 unresolved references to program class members.
             Your input classes appear to be inconsistent.
             You may need to recompile them and try again.
             Alternatively, you may have to specify the option 
             '-dontskipnonpubliclibraryclassmembers'.
    java.io.IOException: Please correct the above warnings first.
    	at proguard.Initializer.execute(Initializer.java:321)
    	at proguard.ProGuard.initialize(ProGuard.java:211)
    	at proguard.ProGuard.execute(ProGuard.java:86)
    	at proguard.ProGuard.main(ProGuard.java:492)
    

      问题1:

    com.baidu.mapapi.utils.h: can't find referenced class android.os.storage.StorageManager

    其实找不到引用的这个类是第三方包里面的,而且很多时候我们只需要打乱自己的代码就行了,第三方包的代码就是否要打乱就不要管了。

    我们可以使用:

    -dontwarn com.xx.bbb.**
    -keep class com.xx.bbb.** { *;}

    参数来保持第三方库中的类而不乱,-dontwarn和-keep 结合使用,意思是保持com.xx.bbb.**这个包里面的所有类和所有方法而不混淆,接着还叫ProGuard不要警告找不到com.xx.bbb.**这个包里面的类的相关引用。

    http://www.vcoo.cc/blog/android-proguard-cant-find-class/

    问题2:怎么不混淆注解

    -keepattributes *Annotation*
    -keep class * extends java.lang.annotation.Annotation { *; }

    问题3:Afinal

    http://www.tuicool.com/articles/7rmmUr

    问题4:混淆后,点击事件被禁

     点击事件的代码

    @ViewInject(id = R.id.login_check_btn, click = "onCheckLoginShow") Button mLoginBtn;
    public void onCheckLoginShow(View view) {
    
    }

     原以为是因为点击事件的方法被混淆掉导致代码不能正常运行,

    http://stackoverflow.com/questions/7796190/androidonclick-not-working-with-proguard

    相关blog

    http://blog.csdn.net/lovexjyong/article/details/24652085

    http://blog.sina.com.cn/s/blog_5f1ebb8f0101lkqz.html

  • 相关阅读:
    Git工具提交github.com
    小程序-setData方法使用--改变默认数据data初始值方法
    小程序-全局变量
    小程序--获取openid
    小程序--错误{"errcode":40125,"errmsg":"invalid appsecret, view more at http://t.cn/RAEkdVq, hints: [ req_id: lE8J30972ns32 ]"}
    小程序-获取openid
    微信小程序--简易table表格
    微信小程序--简单页面跳转
    小程序禁止下拉更新
    小程序--登录获取code
  • 原文地址:https://www.cnblogs.com/royi123/p/4758025.html
Copyright © 2020-2023  润新知