您的位置:首页 > 移动开发 > Android开发

Android proguard遇到的若干问题以及解决思路

2016-04-25 14:50 639 查看
      做毕业设计的时候有一部分工作是对已经编写好的安卓代码进行代码混淆,一般的选择是使用eclipse自带的混淆器proguard。下面简单介绍一下自己从零开始使用proguard的经验。

      我使用的eclipse版本是工程中自带proguard-project.txt的,所以打开eclipse,直接编辑这个文档就好。关于proguard-project.txt基本配置,此处不做详细讲解,资料可见一下链接:
http://blog.csdn.net/hudashi/article/details/9016805 http://blog.csdn.net/lovexjyong/article/details/24652085 http://blog.csdn.net/z157794218/article/details/40039785
      以上三个链接讲的基本很详细了,做好基本配置之后,尝试打包,打包过程可见链接:
http://blog.csdn.net/pi9nc/article/details/11352863
      这篇文章把APK打包讲的很详细,此处不重复说明。

      这步进行后,会出现两种情况:1.打包失败,提示错误信息。这种情况下具体问题具体对待。常见问题:①第三方包没列完全,补上就好;②因为第三方包被混淆提示can't referrenced,这种情况下如果代码中没有用到这个第三方包,选择-ignorewarnings或者-dontwarn java.beans.**(这是一个栗子)这部分详细内容可见链接:

 http://blog.csdn.net/marshalchen/article/details/9928801
http://blog.csdn.net/lvxiangan/article/details/17911623
      2.打包成功,下载apk文件到机子上。出现问题,崩溃,打不开,app功能不对。如果app崩溃,查看崩溃日志,参考文档:
http://blog.csdn.net/dong_xinguang/article/details/11237849 以及参考第一个解决案例,查看出错位置,出错变量,取消混淆即可。

如果是功能问题,参考第二个解决案例。

1.解决案例一:下面看一下部分的代码。

public abstract class Model {

    @Column(name = "Id")

    private Long mId = null;

   //下面这个函数是另一个类里面的

    private Field getIdField(Class<?> type) {

        if(type.equals(Model.class)) {

           try{

                  return type.getDeclaredField("mId");

            }

           catch(NoSuchFieldException e) {

                Log.e("Impossible!", e);

            }

        }

        else if(type.getSuperclass() != null) {

             return  getIdField(type.getSuperclass());

         } 

        return null;

      }

如果我们直接的混淆的话,那么mId肯定会变成了abcd之类的词汇。
而在下面的方法中出现了反射方法。

type.getDeclaredField("mId");

那么我们在混淆之后肯定会报错的。并且返回一个null,笔者当时就是报了个空指针异常,程序的主要作用是查找指定类,发现它的id,并把具有该性质的类放入集合中。
很好,我们发现了这个错误。下面我们就开始添加如下的配置:
-keepclassmembernames class *******************.Model{
java.lang.Long mId;
}
上面的一连串*号是我的包名。
笔者一开始是这么写的。
-keepclassmembernames class *******************.Model{
Long mId;
}
后来查看了proguard文件夹下面examples文件夹下面的许多pro文件,发现了他们的共性,发现不是基本类型是不能这么写的。

后来在混淆之后,在项目中发现了这么个文件夹proguard。这个文件夹是混淆过程中产生的相关的日志文件。
大家可以再mapping.txt文件中找到proguard究竟给你混淆了什么,同时保留了什么。我对上面的Model类尝试了搜索,看看mId是不是混淆了,还是说保留了。

***********.Model -> com.a.d:
    java.lang.Long mId -> mId

结果搜索到这些语句
可以看到Model类已经被混淆成com.a.d了。而我们希望保留的mId,也确实没有混淆了。

2.解决案例二:
由于笔者的项目使用了fastjson框架,发现在解析从服务器下来的数据的时候发生了异常。
大家都知道json数据里面的成员变量是有具体的含义的,比如{username:'xiaoming',password:'dddddddd'};
而我自己写的model,里面对应的username肯定是混淆的。因此我们要解析json数据,肯定是不希望它被混淆的。
因此我们可以在配置文件中添加如下:
-keep class com.xxxx.json.model.**{
*;
}
把json包下的实体类全部保留。

上面描述了两个解决案例:更多的配置例子可以查看sdk的proguard文件夹下面的examples目录。(我觉得这些例子是很有价值的,可以学习观摩)

以上就是我做混淆时遇到的问题,汇总找到的资料来造福大家~

参考文档链接:http://my.oschina.net/zxcholmes/blog/312627
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: