Gradle混淆+打包Jar包基礎,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/18
12 * 版本:V1.0
13 * 說明:與服務端Http通信
14 */
15 public class HttpUtils implements Parent {
16 private static final String TAG = "HttpUtils";
17
18 /**
19 * 發送Post請求到服務器 HTTP
20 *
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 @Override
39 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/16
14 * 版本: V1.0
15 * 說明:
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 @Override
38 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 @Override
19 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 @Override
37 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 @Override
51 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模擬第三方項目)。