通過導入系統(tǒng)jar包解決Android7.0以上第三方apk不能打開WiFi熱點的問題(史上最詳)

因為目前在做關(guān)于設(shè)備間通信相關(guān)的開發(fā)适贸,最近發(fā)現(xiàn)一個問題就是在Android7.0上通過第三方apk打不開手機熱點秧倾,可是在以前的設(shè)備上是正常的溜哮。代碼中是通過反射去調(diào)用了WifiManager的hide方法setWifiApEnabled

反射代碼:

 try {
            // 通過反射調(diào)用設(shè)置熱點
            Method method = wifiManager.getClass().getMethod(
                    "setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
            // 返回熱點打開狀態(tài)
            return (Boolean) method.invoke(wifiManager, apConfig, enabled);
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
            return false;
        }

通過排查問題發(fā)現(xiàn)7.0以后打開熱點的方式變了,是通過ConnectivityManager的startTethering打開的,因為這個方法也是hide的,反射的方式?jīng)]試過咱揍,想試試調(diào)用系統(tǒng)jar包的形式。這里的jar包是通過系統(tǒng)源碼編譯得到的棚饵,網(wǎng)上一大推可以去下煤裙,也可以用自己的源碼來編譯(把想要調(diào)用的方法的hide標記去掉)重新編譯生成jar包。把得到的那個jar包拷貝到lib目錄下:

導入jar包1.png

右擊選擇Add As Library:
導入jar包2.png

發(fā)現(xiàn)app/gradle下面已經(jīng)自動生成了代碼:
導入jar包3.png

說明jar包已經(jīng)導入成功了噪漾,如果不確定的話就去這里看一下:
導入jar包4.png

大功告成硼砰,心想現(xiàn)在應(yīng)該可以去調(diào)用系統(tǒng)api為所欲為了吧,開心的擼了代碼:

    private boolean enableAP(String ssid, String pwd) {
        if (Build.VERSION.SDK_INT >= 24) {
            setApConfig(ssid, pwd);

            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            cm.startTethering(ConnectivityManager.TETHERING_WIFI,
                    true, new ConnectivityManager.OnStartTetheringCallback() {
                        @Override
                        public void onTetheringStarted() {
                            super.onTetheringStarted();
                            Log.i(TAG, "熱點開啟成功");
                        }

                        @Override
                        public void onTetheringFailed() {
                            super.onTetheringFailed();
                            Log.e(TAG, "熱點開啟失敗");
                        }
                    });
            return true;
        } else {
            return setWifiApEnabled(true, getApConfig(ssid, pwd));//這個方法是用的反射怪与,針對7.0以下的夺刑,但是沒啥卵用,可以不加這個else
        }
    }

    /**
     * * 設(shè)置熱點信息
     *
     * @param ssid 熱點名稱
     * @param pwd  熱點密碼
     */
    private void setApConfig(String ssid, String pwd) {
        WifiConfiguration config = new WifiConfiguration();

        config.SSID = ssid;
        config.preSharedKey = pwd;
        config.apBand = 0;
        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK);
        config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);

        wifiManager.setWifiApConfiguration(config);

        Log.i(TAG, "熱點信息設(shè)置成功:ssid = " + ssid);
    }

注意:startTethering最后一個參數(shù)是ConnectivityManager內(nèi)回調(diào)的一個抽象內(nèi)部類分别,如果需要得到打開熱點的結(jié)果遍愿,這樣就按上面的代碼一樣傳入,當然也可以傳入null耘斩,建議傳入匿名的回調(diào)類

擼好代碼發(fā)現(xiàn):

找不到方法2.png

startTethering等hide的成員通通找不到沼填!
那么問題來了,為什么呢括授?
思考:因為我導入的jar包是通過定制的系統(tǒng)包坞笙,和android studio SDK中的包的名字是一樣的。都是:import android.net.ConnectivityManager;看樣子這里是優(yōu)先調(diào)用了SDK內(nèi)的方法了荚虚,為了驗證這一猜想去打開項目中的app.iml文件薛夜,發(fā)現(xiàn):
調(diào)換導包順序1.png

果然是這樣(糟老頭子壞得很),那就想辦法把它們調(diào)用的優(yōu)先級順序改一下版述。常理的思維就是直接更改這個文件梯澜,把導入的jar包放到SDK包的前面,可是一想app.iml是ide生成的就沒有嘗試,但是這方法感覺實在是有點low渴析。晚伙。讓Grovy的面子往哪里擱啊(手動滑稽)吮龄,網(wǎng)上查了一下果然可以通過在gradle內(nèi)配置來實現(xiàn)此功能。
build.gradle:
調(diào)換導包順序2.png

代碼:

allprojects {
    repositories {
        jcenter()
        google()
    }

    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            options.compilerArgs.add('-Xbootclasspath/p:app/libs/classes.jar')
        }
    }
}

app/build.gradle:

調(diào)換導包順序3.png

代碼:

preBuild {
    doLast {
        def imlFile = file(project.name + ".iml")
        println 'Change ' + project.name + '.iml order'
        try {
            def parsedXml = (new XmlParser()).parse(imlFile)
            def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
            parsedXml.component[1].remove(jdkNode)
            def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
            new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
            groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
        } catch (FileNotFoundException e) {
            // nop, iml not found
        }
    }
}

編譯gradle咆疗,編譯成功漓帚。打開app.iml發(fā)現(xiàn)順序果然換過來了:

調(diào)換導包順序4.png

代碼中的紅色也消失了,心想這下終于可以為所欲為了吧午磁,可是選擇Build APK后就報錯了:
異常1.png

坑真的多尝抖!沒辦法,解決吧迅皇。主要問題兩個:1牵署、SDK版本問題 2、dex的一個編譯異常喧半,先解決第一個根據(jù)提示是說我的minsdkversion低于24了經(jīng)過更改:
sdk版本1.png

改了這里對應(yīng)的下面的也要改(注意:改了這個之后你只能裝到7.0以上的設(shè)備了):
sdk版本2.png

編譯,發(fā)現(xiàn)還有問題青责,還是剛才的那個問題挺据,改動沒效果! 經(jīng)過反復摸索發(fā)現(xiàn)還要改一個地方:gradle版本脖隶,于是改成了3.0.1:
gradle版本.png

編譯扁耐,發(fā)現(xiàn)第一個問題沒了(為什么改了一下gradle就不會有這個問題了我也不清楚,還望大佬賜教)产阱。然后解決第二個問題以為要是用mutiDex可是試過發(fā)現(xiàn)不行婉称,最后終于在stackFlow上找到了答案,要在gradle.properties中添加:android.enableD8 = true
dex異常解決.png

然后編譯apk构蹬,發(fā)現(xiàn)編譯成功了王暗,成功了,成功了庄敛。俗壹。≡蹇荆可是绷雏!安裝到設(shè)備里后發(fā)現(xiàn)打開熱點時程序崩了(其實我也已經(jīng)在崩潰的邊緣瘋狂試探了),出錯信息:
未簽名異常.png

android.permission.WRITE_SETTINGS這個是讀寫系統(tǒng)ContentResolver的權(quán)限對第三方apk是不開放的怖亭。搜嘎涎显,那就把它變成系統(tǒng)app,繼續(xù)改:在AndroidManifest內(nèi)添加android:sharedUserId="android.uid.system"注意位置:
加入系統(tǒng)id.png

注意:如果做成系統(tǒng)級別的app的話需要一個jar包簽名工具(網(wǎng)上有)和系統(tǒng)簽名文件(在你的系統(tǒng)源碼內(nèi)):
signapk.jar platform.x509.pem platform.pk8
把這三個文件再加未簽名的apk文件(剛才編譯出來的app-debug.apk)放到一個文件夾下兴猩,然后在該文件夾下打開一個控制臺期吓,運行命令:

 java -jar signapk.jar platform.x509.pem platform.pk8  app-debug.apk  yourNameSigned.apk

發(fā)現(xiàn)在此目錄下會生成一個yourNameSigned.apk的文件,這就是經(jīng)過系統(tǒng)簽名過的系統(tǒng)app啦峭跳,大功告成膘婶!
安裝:

adb install -r yourNameSigned.apk

安裝成功缺前,發(fā)現(xiàn)熱點可以正常打開,像極了愛情悬襟。衅码。

后記:此時你的App是系統(tǒng)級別的,真的可以為所欲為哦脊岳,各種權(quán)限逝段,各種接口,再也不需要反射啦割捅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奶躯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子亿驾,更是在濱河造成了極大的恐慌嘹黔,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莫瞬,死亡現(xiàn)場離奇詭異儡蔓,居然都是意外死亡,警方通過查閱死者的電腦和手機疼邀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門喂江,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人旁振,你說我怎么就攤上這事获询。” “怎么了拐袜?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵吉嚣,是天一觀的道長。 經(jīng)常有香客問我蹬铺,道長瓦戚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任丛塌,我火速辦了婚禮较解,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赴邻。我一直安慰自己印衔,他們只是感情好,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布姥敛。 她就那樣靜靜地躺著奸焙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上与帆,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天了赌,我揣著相機與錄音,去河邊找鬼玄糟。 笑死勿她,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的阵翎。 我是一名探鬼主播逢并,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼郭卫!你這毒婦竟也來了砍聊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤贰军,失蹤者是張志新(化名)和其女友劉穎玻蝌,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體词疼,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡灶伊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了寒跳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡竹椒,死狀恐怖童太,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胸完,我是刑警寧澤书释,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站赊窥,受9級特大地震影響爆惧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锨能,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一扯再、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧址遇,春花似錦熄阻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春钾军,著一層夾襖步出監(jiān)牢的瞬間鳄袍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工吏恭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拗小,地道東北人。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓砸泛,卻偏偏與公主長得像十籍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子唇礁,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

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