Android Java 修改jar包里面的內(nèi)容(一波騷操作)

簡(jiǎn)介

有時(shí)候我們集成第三方SDK時(shí),其中某個(gè)類(lèi)不符合我們的邏輯或者出現(xiàn)某個(gè)bug,而我們又沒(méi)有源碼,這個(gè)時(shí)候本篇博客就能解決你的問(wèn)題下翎。

通常純Java代碼會(huì)這樣操作,比如修改一個(gè)jar中的Test.class文件宝当,首先將jar包內(nèi)容解壓到一個(gè)目錄下面视事,然后使用jd-gui工具,反編譯目錄下Test.class文件庆揩,然后在該目錄下新建Test.java文件俐东,將反編譯的內(nèi)容拷貝入其中,修改完成之后執(zhí)行javac Test.java订晌,會(huì)在同一目錄生成Test.class虏辫,再將新的Test.class替換之前的Test.class,再重新打包成jar包锈拨。但是在Android中jar中就不好這么修改砌庄,因?yàn)槔锩姘珹ndroid SDK內(nèi)容,以下我們來(lái)介紹Android中修改jar中內(nèi)容奕枢。

原理

生成jar包

首先我們生成一個(gè)演示jar包娄昆,在Android Studio項(xiàng)目中新建一個(gè)library,其中添加兩個(gè)類(lèi)缝彬。

JarClassTest.java

public class JarClassTest {
    private static JarClassTest jarClassTest;

    private JarClassTest() {
    }

    /**
     * 實(shí)例化對(duì)象
     *
     * @return JarClassTest
     */
    public static JarClassTest getInstance() {
        if (jarClassTest == null) {
            jarClassTest = new JarClassTest();
        }
        return jarClassTest;
    }

    /**
     * 彈出toast
     */
    public void showToast(Context context) {
        ToastUtil.showTip(context);
    }
}

ToastUtil.java

public class ToastUtil {
    /**
     * @param context 上下文
     */
    public static void showTip(Context context) {
        Toast.makeText(context, "替換之前彈出的提示", Toast.LENGTH_LONG).show();
    }
}

在library的gradle中添加:

task makeJar(type: Copy) {
    delete 'build/libs/TestJar_V1.0.jar' //刪除之前的舊jar包
    from('build/intermediates/packaged-classes/release/') //從這個(gè)目錄下取出默認(rèn)jar包
    into('build/libs/') //將jar包輸出到指定目錄下
    include('classes.jar')
    rename('classes.jar', 'TestJar_V1.0.jar') //自定義jar包的名字
}
makeJar.dependsOn(build)

生成jar包:


makeJar

或者在 Android Studio 終端窗口中輸入 gradlew makeJar 命令萌焰。

在build/libs/文件下找到TestJar_V1.0.jar文件,將jar文件拷貝到項(xiàng)目中使用谷浅。

修改jar

新建一個(gè)項(xiàng)目扒俯,將jar包拷貝到libs中族购,添加jar依賴(lài)。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnToast = findViewById(R.id.btn_toast);
        btnToast.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                JarClassTest.getInstance().showToast(MainActivity.this);
            }
        });
    }
}
運(yùn)行結(jié)果
修改之前

這個(gè)時(shí)候我需要修改ToastUtil.class里面的內(nèi)容陵珍,假設(shè)在沒(méi)有源碼的情況下,我們要修改中文提示违施。

新建ToastUtil.java
class文件

首先在我們項(xiàng)目的java包文件下創(chuàng)建與需要修改class一樣的包名互纯,重要的事情說(shuō)三遍:
保持包名一致!
保持包名一致磕蒲!
保持包名一致留潦!
在新建的包下新建一個(gè)相同類(lèi)名.java文件,將class文件下的內(nèi)容考入.java文件中辣往,修改不合理的地方兔院,自己還可以添加一下代碼。

圖例

執(zhí)行程序站削,報(bào)如下錯(cuò)誤坊萝,這就是由于項(xiàng)目中存在兩個(gè)相同的class文件導(dǎo)致的。


報(bào)錯(cuò)

這個(gè)時(shí)候我們把jar中的class文件刪除许起。


刪除jar中class
修改之后

在執(zhí)行程序十偶,如下圖:

修改成功提示
合成jar包

當(dāng)我們調(diào)試完成之后,可以以這種形式存在項(xiàng)目中园细,這樣隨時(shí)可以修改.java文件里面的代碼惦积,當(dāng)然為了jar的完整性,我們還是考慮將修改完的.class文件拷貝到j(luò)ar包中猛频,替換之前的class文件狮崩,合成一個(gè)完整的jar包。

在Android Studio中執(zhí)行build->make project后在app/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes路徑下


class文件

將相關(guān)的class文件拷貝出導(dǎo)入之前的jar包鹿寻,刪除項(xiàng)目中.java文件睦柴,OK 這時(shí)候就可愉快的運(yùn)行了。

注意:以上刪除烈和、添加爱只、覆蓋建議直接在壓縮軟件中進(jìn)行,方便

進(jìn)階jar包混淆

首先在library中proguard-rules.pro添加常規(guī)混淆規(guī)則

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class com.android.vending.licensing.ILicensingService


#忽略警告
-ignorewarnings
#保證是獨(dú)立的jar,沒(méi)有任何項(xiàng)目引用,如果不寫(xiě)就會(huì)認(rèn)為我們所有的代碼是無(wú)用的,從而把所有的代碼壓縮掉,導(dǎo)出一個(gè)空的jar
-dontshrink
#保護(hù)泛型
-keepattributes Signature


-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

需要注意的問(wèn)題招刹,因?yàn)槲覀冃枰猨ar包被別人使用恬试,因此我們需要對(duì)外提供接口需要暴露出來(lái),不需要混淆疯暑,可在配置文件加上添加如下過(guò)濾規(guī)則训柴。

-keep public class com.zhj.jartest.JarClassTest{
    #保持了類(lèi)mylibrary里面public 修飾的成員變量和public修飾的方法。
    public <fields>;
    public <methods>;
}

將混淆打開(kāi)

  buildTypes {
        release {
            //開(kāi)啟關(guān)閉混淆
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

這個(gè)時(shí)候生成的jar包有點(diǎn)那么羞澀了


混淆之后的jar

這個(gè)時(shí)候我們修改與之前步驟一樣妇拯,里面添加代碼直接寫(xiě)邏輯就行了幻馁,但是修改混淆的代碼還是有點(diǎn)難度洗鸵,需要了解這種a、b仗嗦、c代表什么才能寫(xiě)邏輯膘滨。


混淆的修改

總結(jié)

可見(jiàn)修改jar包內(nèi)容是非常簡(jiǎn)單,aar包中的jar的修改道理相似稀拐,所以提供給別人jar包時(shí)火邓,為了保護(hù)好jar包價(jià)值,需要對(duì)代碼進(jìn)行混淆德撬,或者添加一些不相關(guān)的代碼铲咨,增加修改、破解代碼邏輯的難度蜓洪。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纤勒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子隆檀,更是在濱河造成了極大的恐慌摇天,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恐仑,死亡現(xiàn)場(chǎng)離奇詭異闸翅,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)菊霜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)坚冀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鉴逞,你說(shuō)我怎么就攤上這事记某」辜瘢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵滑凉,是天一觀的道長(zhǎng)髓废。 經(jīng)常有香客問(wèn)我耕捞,道長(zhǎng),這世上最難降的妖魔是什么卢肃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任若未,我火速辦了婚禮倾鲫,結(jié)果婚禮上粗合,老公的妹妹穿的比我還像新娘萍嬉。我一直安慰自己,他們只是感情好隙疚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著大诸,像睡著了一般贯卦。 火紅的嫁衣襯著肌膚如雪焙贷。 梳的紋絲不亂的頭發(fā)上撵割,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天辙芍,我揣著相機(jī)與錄音,去河邊找鬼庶灿。 笑死吃衅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的徘层。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼瘦癌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼跷敬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起斤寇,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拥褂,失蹤者是張志新(化名)和其女友劉穎抡驼,沒(méi)想到半個(gè)月后肿仑,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體碎税,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡馏锡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匪煌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片党巾。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖驳规,靈堂內(nèi)的尸體忽然破棺而出署海,到底是詐尸還是另有隱情,我是刑警寧澤砸狞,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站踱启,受9級(jí)特大地震影響研底,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜飘哨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一芽隆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧胚吁,春花似錦、人聲如沸腕扶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)炼幔。三九已至,卻和暖如春乃秀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背跺讯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工刀脏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人火本。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓聪建,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親擎析。 傳聞我的和親對(duì)象是個(gè)殘疾皇子挥下,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容