Android WiFi開發 (三)Wifi熱點8.0適配

Android 7.0及以前Wifi熱點
Android 8.1、8.0Wifi熱點

apk測試 8.0下載:鏈接:https://pan.baidu.com/s/14mQqiaaz5ik0vht8MSYDpg 提取碼:dwat
apk測試 低版本下載:鏈接: https://pan.baidu.com/s/1dzK3rEiwlaD0QrpWe-Vrgg 提取碼: 1qpr

Demo下載:http://www.demodashi.com/demo/13907.html
最近發現Android8.0以上的手機開啓Wifi熱點後不能正常使用,故研究了一下如何解決次問題。

Android 7.0 開啓Wifi熱點

在Android7.0及以前的版本開啓Wifi熱點的方式如下:

WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Method method = mWifiManager.getClass().getMethod("setWifiApEnabled",
                        WifiConfiguration.class, boolean.class);
//反射
method.invoke(mWifiManager, null, false);

Android 8.0 開啓Wifi熱點

對於Android8.0及以上的設備,通過WifiManager setWifiApEnabled,可以打開Wifi熱點,但是會發現此熱點,連接不上(由於DHCP沒有開啓),所以不會分配ip地址,也就導致不能正常使用。

在Android8.0系統應用Settings,發現其開啓熱點的方式是通過ConnectivityManager的startTethering方法來開啓的。
查看ConnectivityManager的方法
三個參數
四個參數
startTethering 是隱藏的方法,並且第三個參數OnStartTetheringCallback是ConnectivityManager內部抽象類,也是隱藏的。

/**
* Callback for use with {@link #startTethering} to find out whether tethering succeeded.
* @hide
*/
@SystemApi
public static abstract class OnStartTetheringCallback {
    /**
     * Called when tethering has been successfully started.
     */
    public void onTetheringStarted() {};
    /**
	 * Called when starting tethering failed.
     */
	public void onTetheringFailed() {};
}

通過反射的方式並沒有找到方式獲取startTethering方法,以及創建OnStartTetheringCallback子對象。

後來通過另一種方式實現了。

配置jar包

首先修改ConnectivityManager源碼,將TETHERING_WIFI字段、startTethering方法及OnStartTetheringCallback類中隱藏相關的標誌去掉,然後單獨編譯一個jar包。
將jar包拷貝到工程中,如下所示:
wifiap jar包
該jar包會和官方sdk中的android.jar會有衝突,所以需要配置jar包的優先級。
在app的build.gradle中配置

provided files('src/main/libs/WifiAp8.jar')

在工程下的build.gradle中添加如下配置:

allprojects {
    
    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
        //設置jar相對包路徑或絕對路徑
            options.compilerArgs.add('-Xbootclasspath/p:app/src/main/libs/WifiAp8.jar')
        }
    }
}

編寫代碼

開啓熱點

if(getWifiAPState() != WIFI_AP_STATE_ENABLED){
	//Android8.0及以上版本
    if (Build.VERSION.SDK_INT >= 26) {
        mConnectivityManager.startTethering(ConnectivityManager.TETHERING_WIFI,
                true, new ONStartTetheringCallback());
    }
}

在這裏插入圖片描述
在AS中上述代碼會有紅色顯示,但是不影響編譯使用。可以正常編譯生成apk。使用該方法不需要提前關閉wifi。

ONStartTetheringCallback類繼承了OnStartTetheringCallback抽象類。

class ONStartTetheringCallback extends
        ConnectivityManager.OnStartTetheringCallback {
}

關閉熱點

if(getWifiAPState() != WIFI_AP_STATE_DISABLED){
	//Android8.0及以上版本
    if (Build.VERSION.SDK_INT >= 26) {
        mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
    }
}

權限
使用上述功能需要這三個權限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />

還需要在代碼中申請WRITE_SETTINGS權限,否則不能正常使用。

這樣就可以了,不只是系統應用可以使用,平常的應用也可以正常使用。親測:華爲P20(Android 8.1.0)、華爲mate10(Android 8.1.0)、華爲V10(Android 8.0.0)、OnePlus 5T(Android8.1.0)都可以正常使用:。


Android 7.1 開啓Wifi熱點

對於Android7.1、Android7.1.1、Android7.1.2的手機,開啓熱點的方式比較亂,有的手機用老方法
可以正常打開,比如紅米5 plus(Android7.1.2)、堅果pro2(Android7.1.1),有的手機用老方法就不能正常使用(Nexus 5x 7.1.1),可以嘗試用8.0的方法打開試試。

由於Android手機版本和廠家太多,手頭沒有太多手機,並不能做到很好的適配,所以大家可以嘗試使用上述兩種方法來看看哪種方法適合你手上的手機開啓熱點,並且熱點能正常使用。

歡迎大家關注、評論、點贊
你們的支持是我堅持的動力。
歡迎關注我的微信公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章