1 問題
在Android8.0版本以後,開啓熱點我們採用的下面這種方式,但是跳轉頁面後熱點會斷開,手機不能互相傳文件了
權限說明:Android8.0需要位置權限和GPS權限,同時手機熱點還不能是開啓狀態。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
mWifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
@Override
public void onFailed(int reason) {
super.onFailed(reason);
Log.i(TAG, "onFailed start");
}
@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
Log.i(TAG, "onStarted start");
mReservation = reservation;
WifiConfiguration wifiConfiguration = reservation.getWifiConfiguration();
String ssid = wifiConfiguration.SSID;
String pwd = wifiConfiguration.preSharedKey;
Log.i(TAG, "ssid is:" + ssid);
Log.i(TAG, "pwd is:" + pwd);
}
@Override
public void onStopped() {
super.onStopped();
sendBroadcast(STOP_STATE, "", "");
}
}, new Handler());
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "startLocalOnlyHotspot error");
}
}
2 思考
1)全局靜態保存mReservation變量,跳頁面的時候不執行close方法。
我們看到上面的代碼
mReservation = reservation;
我們關閉,是這樣關閉的
if (mReservation != null) {
mReservation.close();
mReservation = null;
}
爲了防止熱點關閉,我們一開始對mReservation變量做了全局靜態的保存,但是依然存在開啓熱點後,熱點會斷的問題。
2)反編譯"茄子快傳"代碼,分析別人的產品
"茄子快傳" 這個app也是熱點生成後多個手機連接,然後進行文件的發送,我們反編譯“茄子快傳”代碼
搜索關鍵字startLocalOnlyHotspot,如下圖
這裏看起來像用了反射,我們點擊進去看這個函數
的確用了反射,明明有API爲啥用反射呢?現在也搞不懂,到底有沒有蹊蹺現在也不知,然後我再看下在哪裏調用這個函數
很明顯這裏開啓了一個服務,然後在onStartCommand函數裏面傳遞了一個攜帶參數的intent過來,如果是0就是執行關閉函數,如果是1的話就執行開啓熱點函數,然後它也重寫了這個回調LocalOnlyHotspotCallback
把LOHSService作爲構造函數參數傳遞進去,然後開啓熱點成功後,執行this.a.a(1, str, wifiConfiguration.preSharedKey);
這個函數,也就是發送攜帶用戶名和密碼的廣播到其它頁面
然後我也這樣模仿開啓一個服務,在服務裏面開啓熱點去測試,配置如下
<service android:name="**********.LocalHotService" android:exported="false">
<intent-filter>
<action android:name="**********.LocalHotService"/>
</intent-filter>
</service>
發現依然不穩定,只不過我開啓的時候是用API來開啓的,不是用的反射,然後我就採用它的代碼,用反射進行開啓,效果依然不穩定,說明這裏沒區別,由於第一次開啓熱點,非常穩定,第二次開啓熱點會很不穩定,所以思考是不是由於關閉熱點出了問題
if (mReservation != null) {
mReservation.close();
mReservation = null;
}
然後我嘗試,不採用中間變量mReservation保存,用反射進行關閉
@TargetApi(Build.VERSION_CODES.M)
public void stopHotPoint(Context context) {
try {
ConnectivityManager manager = (ConnectivityManager) context.getApplicationContext().getSystemService(ConnectivityManager.class);
Method method = manager.getClass().getDeclaredMethod("stopTethering", int.class);
if (method == null) {
} else {
method.invoke(manager, 0);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
}
這樣掉,還需要申請一個修改系統設置的權限,需要通過startActivity去申請,當然
android.permission.WRITE_SETTINGS
當然在AndroidManifest.xml裏面也要配置好
<uses-permission
android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
這樣程序纔不會奔潰
然後我們再分析下源碼,這裏系統會調用finalize方法,內存不夠就可能執行,然後裏面回調用close方法,然後close裏面會調用stopLocalOnlyHotspot()方法,這裏就會關閉熱點
可能由於內存不夠導致不穩定,然後既然開啓了熱點服務,我們爲什麼不能在開闢一個進程呢?
然後把服務放在另外一個進程裏面,另外一個進程沒有太多其它操作,內存一般不會執行Java垃圾回收
然後在單獨一個進程開啓服務,測試這個熱點就非常穩定了,問題也解決了
3 解決辦法
再開闢一個新的進程裏面開啓熱點服務
<service android:name="*****.LocalHotService" android:exported="false"
android:process=":aptest">
<intent-filter>
<action android:name="*****.LocalHotService"/>
</intent-filter>
</service>