你的位置:首页 > 操作系统

[操作系统]Gradle混淆+打包Jar包基础


本文为原创文章,转载请注明出处。  

文章最后会附带源码下载地址,有需要的朋友可下载。

通常我们编写Android APP时有这样的需求:(1)代码混淆;(2)模块化;(3)向第三方提供JAR包。下面将以实例的形式向初学Android或开始使用AndroidStudio(AS)的朋友介绍下这几部分。

引述:

(1)AS采用了Gradle的构建工具,可以让我们很方便的对我们的APP进行配置,比如版本、支持最低API level 、代码混淆文件、第三方库等等,具体语法请查考其他朋友的文章。

(2)AS提供了模块编程,便于我们对APP进行分层和理清架构,个人推荐初学者可以参考下这篇文章。

实例正文:

本文实例仅作为演示使用,重点是演示代码混淆和打包JAR,所以功能都进行了简化并省略了很多逻辑代码。

基本需求:接受用户的登录请求,模拟完成向服务端发起登录请求,并提示登录结果。

一、创建项目

项目目录结构:

个人习惯将各模块创建为平级,模块(android library)描述:

app:用户模块,用户交互界面、用户资源等   model:实体模块     player:核心业务模块  utils:辅助类模块。

提示:创建模块时注意模块类型为Android Library,否则会对后面的一些功能会有影响。

 

二、代码编写

(1)model模块

用户登录信息实体:

 

 1 package xiaoshubao.model; 2  3 /** 4  * 作者: 小书包 5  * 日期: 2016/6/16 6  * 版本: V1.0 7  * 说明: 8 */ 9 public class UserModel {10   String userName;11   String pwd;12 13   public void setUserName(String userName) {14     this.userName = userName;15   }16 17   public void setPwd(String pwd) {18     this.pwd = pwd;19   }20 21   public String getUserName() {22     return userName;23   }24 25   public String getPwd() {26     return pwd;27   }28 }

View Code

 

  其他实体不再贴代码,model层最终的代码结构如下:

HttpMsgCallback:http回调请求接口

Parent:无实际意义类,代码混淆时需要

UserLoginCallback:用户登录结果回调接口

(2)utils模块:

网络访问辅助类(HttpUtils):

 1 package xiaoshubao.utils; 2  3 import java.util.HashMap; 4 import java.util.Map; 5  6 import xiaoshubao.model.HttpMsgCallback; 7 import xiaoshubao.model.Parent; 8  9 /**10  * 作者: 小书包11  * 日期: 2015/12/1812  * 版本:V1.013  * 说明:与服务端Http通信14 */15 public class HttpUtils implements Parent {16   private static final String TAG = "HttpUtils";17 18   /**19    * 发送Post请求到服务器 HTTP20    *21    * @param strUrlPath 服务器地址22    * @param params   请求体参数23    * @return 错误码24   */25   private static String httpPostData(String strUrlPath, Map<String, String> params) {26 27     return "true";28   }29 30   /**31    * 向http服务器发出注册消息32    * @param serverUrl 服务器地址33    * @param params 请求体参数34    * @param httpMsgCallback 执行结果回调35   */36   public static void sendPostMsgToServer(final String serverUrl, final HashMap params, final HttpMsgCallback httpMsgCallback) {37     Thread thread = new Thread(new Runnable() {38       @Override39       public void run() {40         try {41           Thread.sleep(2*1000);//当前线程睡眠两秒钟模拟发送网络请求42         } catch (InterruptedException e) {43           e.printStackTrace();44         }45         String result = HttpUtils.httpPostData(serverUrl, params);46         httpMsgCallback.httpPostCallBack(result);47       }48     });49     thread.start();50   }51  }

View Code

 

(3)player模块

 UserLogin类(用户登录业务类):

 

 1 package xiaoshubao.player; 2  3 import java.util.HashMap; 4  5 import xiaoshubao.model.HttpMsgCallback; 6 import xiaoshubao.model.Parent; 7 import xiaoshubao.model.UserLoginCallback; 8 import xiaoshubao.model.UserModel; 9 import xiaoshubao.utils.HttpUtils;10 11 /**12  * 作者: 小书包13  * 日期: 2016/6/1614  * 版本: V1.015  * 说明:16 */17 public class UserLogin implements Parent {18   UserLoginCallback userLoginCallback;19   public UserLogin(UserLoginCallback userLoginCallback){20     this.userLoginCallback=userLoginCallback;21   }22 23   /**24    * 用户登录25    * @param user 用户信息26   */27   public void login(UserModel user){28     userLogin(user);29   }30   private void userLogin(UserModel user){31     HashMap hashMap=new HashMap();32     hashMap.put("userName",user.getUserName());33     hashMap.put("pwd",user.getPwd());34     HttpUtils.sendPostMsgToServer("XXXXX", hashMap, httpMsgCallback);35   }36   HttpMsgCallback httpMsgCallback=new HttpMsgCallback() {37     @Override38     public void httpPostCallBack(String json) {39       if (json.contains("true")&&null!=userLoginCallback){40         userLoginCallback.loginResult(true);41       }else if (null!=userLoginCallback){42         userLoginCallback.loginResult(false);43       }44     }45   };46   private void fun1(){}47   private void fun2(){}48 }

View Code

 

三、代码混淆

  AS中进行代码混淆需要在build.gradle文件和proguard-rules.pro文件中进行设置(可以通过jd-gui工具对比混淆前后效果):

(1)build.gradle文件

minifyEnabled:表示是否开启混淆,默认为false

proguardFiles:混淆配置文件,一般就采用项目中默认的proguard-rules.pro文件。

(2)proguard-rules.pro文件

混淆设置,具体可参考progurad官网。

注意图中红框部分,因为所有jar包都要求有对外接口(没有对外接口的模块一般也没什么意义),有多种种方式设置对外接口类:

a:-keep public class *,例如:

-keep public class * {
public protected *;
}

b:如图所示。

因为一个模块一般有很多类文件,混淆时我们希望除对外接口类的其他所有类文件的类名也进行混淆,那么就可以单独创建一个基类或接口,让对外的接口类继承该基类或接口。

c:-keep public class XXX,特定类不混淆,例如:

-keep public class xiaoshubao.player.UserLogin{
public protected *;
}

四、打包JAR包

(1)proguard-rules.pro配置

配置生成JAR包的基本属性,如下:

上述代码很简单不再叙述。

(2)生成JAR包

CMD命令行中切换到当前项目目录下,执行gradlew makeJar 命令。

顺利的话会生成JAR包,如果是第一次采用gradlew生成,可能需要在线更新相关包,大约几分钟时间。

如果配置、类引用出现错误,CMD窗口会提示,请根据具体的错误提示做修改。

(3)JAR包合并

gradlew makeJar命令会在model、uitls、palyer目录下分别生成这三个模块的JAR包,那么如果我们需要向第三方提供SDK,三个JAR包可能会不太方便,所以就有了合并为一个JAR包的需求。

我们知道JAR包其实就是普通的压缩包而已,所以对三个JAR包进行解压后文件如下:

注意:META-INF配置文件,该项目对palyer、utils模块进行了混淆而model模块未混淆(也可通过配置进行混淆),所以只有一个META-INF文件生成,如果有多个模块未混淆时生成了多个META-INF文件,采用本文方法进行JAR包合并会出问题。

xiaoshubao文件夹下的目录文件如下:

 

 一起压缩META-INF、xiaoshubao文件生成zip文件,重命名为.jar文件,结果如下:

五、第三方使用

 将MyUserManager.jar包导入测试项目(非JAR包源码项目)中,如下:

提示:有时在JAR包前面没有向下的三角符号也无法点开JAR包查看里面的类文件,且使用JAR包里的类时会报错,此时重启该项目应该就可以出现如上图所示的效果。

(1)登录界面:

(2)登录代码:

 1 package xiaoshubao.jartest; 2  3 import android.content.Context; 4 import android.os.Bundle; 5 import android.os.Message; 6 import android.support.v7.app.AppCompatActivity; 7 import android.view.View; 8 import android.widget.EditText; 9 import android.widget.Toast;10 11 import xiaoshubao.model.UserLoginCallback;12 import xiaoshubao.model.UserModel;13 import xiaoshubao.player.UserLogin;14 15 public class MainActivity extends AppCompatActivity {16   Context context;17   MyHandler handler;18   @Override19   protected void onCreate(Bundle savedInstanceState) {20     super.onCreate(savedInstanceState);21     setContentView(R.layout.activity_main);22     context = this;23     handler = new MyHandler();24   }25   public void btn_loginClick(View v) {26     UserLogin userLogin = new UserLogin(userLoginCallback);27     UserModel userModel = new UserModel();28     String userName = ((EditText) findViewById(R.id.etUserName)).getText().toString().trim();29     userModel.setUserName(userName);30     String pwd = ((EditText) findViewById(R.id.etPwd)).getText().toString().trim();31     userModel.setPwd(pwd);32     userLogin.login(userModel);33   }34 35   UserLoginCallback userLoginCallback = new UserLoginCallback() {36     @Override37     public void loginResult(boolean result) {38       Message msg = Message.obtain();39       msg.what = 7634;40       if (result) {41         msg.obj = "登录成功!";42       } else {43         msg.obj = "登录失败!";44       }45       handler.sendMessage(msg);46     }47   };48 49   public class MyHandler extends android.os.Handler {50     @Override51     public void handleMessage(Message msg) {52       switch (msg.what) {53         case 7634:54           Toast.makeText(context, msg.obj.toString(), Toast.LENGTH_LONG).show();55       }56     }57   }58 }

View Code

 

(3)运行效果

 

代码混淆是最简单、最基础的Android APP安全保障,后续将还会介绍其他的关于APP安全相关技术。

本实例DEMO下载地址(MyApplication4 源码项目,JarTest模拟第三方项目)。