博主又來更新文章了,有點墨跡哈,好久纔來一篇文章,不講究文章量的大小,只在意內容的實用性,幫助每個開發者,避過一些沒必要要的坑,廢話很少說了,文章的內容就是說各類版本手機經過代碼如何開啓熱點,文章也比較簡潔,不會有太多的囉嗦話java
首先呢,經過Android 對應Api的源碼(哈哈哈上來就源碼,不看源碼怎麼知道開熱點啊)就能夠找到如何開熱點的,在咱們手機的設置頁面確定會有開啓熱點的功能,而後呢 就去找對於版本號的Api, 代碼我就貼出來了,簡潔的代碼 有興趣的同窗能夠去源碼官網查看TetherSettings.java 源碼android
public void onClick(DialogInterface dialogInterface, int button) {
if (button == DialogInterface.BUTTON_POSITIVE) {
mWifiConfig = mDialog.getConfig();
if (mWifiConfig != null) {
/**
* if soft AP is stopped, bring up
* else restart with new config
* TODO: update config on a running access point when framework support is added
*/
if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
mWifiManager.setWifiApEnabled(null, false);
mWifiManager.setWifiApEnabled(mWifiConfig, true);
} else {
mWifiManager.setWifiApConfiguration(mWifiConfig);
}
int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig);
mCreateNetwork.setSummary(String.format(getActivity().getString(CONFIG_SUBTEXT),
mWifiConfig.SSID,
mSecurityType[index]));
}
}
}
複製代碼
從源碼上能夠看到 開啓熱是經過wifimanager setWifiApEnabled的方式走的shell
public void onClick(DialogInterface dialogInterface, int button) {
if (button == DialogInterface.BUTTON_POSITIVE) {
mWifiConfig = mDialog.getConfig();
if (mWifiConfig != null) {
/**
* if soft AP is stopped, bring up
* else restart with new config
* TODO: update config on a running access point when framework support is added
*/
if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
Log.d("TetheringSettings",
"Wifi AP config changed while enabled, stop and restart");
mRestartWifiApAfterConfigChange = true;
mCm.stopTethering(TETHERING_WIFI);
}
mWifiManager.setWifiApConfiguration(mWifiConfig);
int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig);
mCreateNetwork.setSummary(String.format(getActivity().getString(CONFIG_SUBTEXT),
mWifiConfig.SSID,
mSecurityType[index]));
}
}
}
複製代碼
從上面的代碼能夠看到變了,變得不認識了,不是經過wifiManager的方式走的了,而是經過更新config 文件而後經過別的方式來開啓熱點的,下面的代碼就是開啓熱點的方式。api
private void startTethering(int choice) {
if (choice == TETHERING_BLUETOOTH) {
// Turn on Bluetooth first.
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter.getState() == BluetoothAdapter.STATE_OFF) {
mBluetoothEnableForTether = true;
adapter.enable();
mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
mBluetoothTether.setEnabled(false);
return;
}
}
mCm.startTethering(choice, true, mStartTetheringCallback, mHandler);
}
複製代碼
經過上面代碼能夠看到 開啓的方式是走ConnectivityManager方式來開啓熱點的。而不是經過wifimanager了。bash
在說如何開啓熱點的代碼時候,仍是會帶你們看一點點的源碼。而後看看如何在本身項目中用代碼進行開啓。app
/**
* Start AccessPoint mode with the specified
* configuration. If the radio is already running in
* AP mode, update the new configuration
* Note that starting in access point mode disables station
* mode operation
* @param wifiConfig SSID, security and channel details as
* part of WifiConfiguration
* @return {@code true} if the operation succeeds, {@code false} otherwise
*
* @hide Dont open up yet
*/
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
try {
mService.setWifiApEnabled(wifiConfig, enabled);
return true;
} catch (RemoteException e) {
return false;
}
}
複製代碼
能夠看到這個Api已經被隱藏了。大兄弟們,大家是無法玩耍的。只能乾瞪眼ide
/**
* Start AccessPoint mode with the specified
* configuration. If the radio is already running in
* AP mode, update the new configuration
* Note that starting in access point mode disables station
* mode operation
* @param wifiConfig SSID, security and channel details as
* part of WifiConfiguration
* @return {@code true} if the operation succeeds, {@code false} otherwise
*
* @hide
*/
@SystemApi
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
try {
mService.setWifiApEnabled(wifiConfig, enabled);
return true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
複製代碼
看到沒有變成了系統級別的Api 不緊隱藏了,還變成了系統級別的Api,並且發現出現exec的時候直接返回exception而不是返回false 直接返回false 這個可有可無工具
/**
* This call is deprecated and removed. It is no longer used to
* start WiFi Tethering. Please use {@link ConnectivityManager#startTethering(int, boolean,
* ConnectivityManager#OnStartTetheringCallback)} if
* the caller has proper permissions. Callers can also use the LocalOnlyHotspot feature for a
* hotspot capable of communicating with co-located devices {@link
* WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)}.
*
* @param wifiConfig SSID, security and channel details as
* part of WifiConfiguration
* @return {@code false}
*
* @hide
* @deprecated This API is nolonger supported.
* @removed
*/
@SystemApi
@Deprecated
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
String packageName = mContext.getOpPackageName();
Log.w(TAG, packageName + " attempted call to setWifiApEnabled: enabled = " + enabled);
return false;
}
複製代碼
也就是說這個api啊 在8.1的時候已經被徹底廢棄了。直接給你返回false。只能經過8.0的方式進行開啓wifi 熱點了ui
因爲都是隱藏的api 因此開啓熱點的方式幾乎都是經過反射來進行的google
public boolean createAp(boolean isOpen) {
StringBuffer sb = new StringBuffer();
try {
mWifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
if (mWifiManager.isWifiEnabled()) {
mWifiManager.setWifiEnabled(false);
}
sb.append(1);
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.SSID = "xiaomeng";
netConfig.preSharedKey = "11111111";
Log.d("oye", "WifiPresenter:createAp----->netConfig.SSID:"
+ netConfig.SSID + ",netConfig.preSharedKey:" + netConfig.preSharedKey + ",isOpen=" + isOpen);
netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
sb.append(2);
if (isOpen) {
netConfig.allowedKeyManagement.set(4);
sb.append(3);
} else {
netConfig.allowedKeyManagement.set(4);
sb.append(4);
}
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
sb.append(5);
Method method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
sb.append(9);
return (boolean) method.invoke(mWifiManager, netConfig, true);
} catch (NoSuchMethodException e) {
sb.append(10 + (e.getMessage()));
e.printStackTrace();
} catch (InvocationTargetException e) {
sb.append(11 + (e.getMessage()));
e.printStackTrace();
} catch (IllegalAccessException e) {
sb.append(12 + (e.getMessage()));
e.printStackTrace();
}
log.setText(sb.toString());
return false;
}
複製代碼
第一種直接調用系統提供的Api 可是不穩定 不靠譜(並且熱點的名稱和密碼都是隨機的)
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
@TargetApi(Build.VERSION_CODES.O)
@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
WifiConfiguration wifiConfiguration = reservation.getWifiConfiguration();
ssid = wifiConfiguration.SSID;
//能夠經過config拿到開啓熱點的帳號和密碼
mHandler.obtainMessage(2018, wifiConfiguration).sendToTarget();
}
@Override
public void onStopped() {
super.onStopped();
}
@Override
public void onFailed(int reason) {
super.onFailed(reason);
}
}, mHandler);
複製代碼
第二種開啓的方式 有些機型會報NoSuchMethodException的異常 是由於有些機型他會多出來一個參數
private void startTethering() {
mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (mWifiManager != null) {
int wifiState = mWifiManager.getWifiState();
boolean isWifiEnabled = ((wifiState == WifiManager.WIFI_STATE_ENABLED) || (wifiState == WifiManager.WIFI_STATE_ENABLING));
if (isWifiEnabled)
mWifiManager.setWifiEnabled(false);
}
if (mConnectivityManager != null) {
try {
Field internalConnectivityManagerField = ConnectivityManager.class.getDeclaredField("mService");
internalConnectivityManagerField.setAccessible(true);
WifiConfiguration apConfig = new WifiConfiguration();
apConfig.SSID = "cuieney";
apConfig.preSharedKey = "12121212";
StringBuffer sb = new StringBuffer();
Class internalConnectivityManagerClass = Class.forName("android.net.IConnectivityManager");
ResultReceiver dummyResultReceiver = new ResultReceiver(null);
try {
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
Method mMethod = wifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
mMethod.invoke(wifiManager, apConfig);
Method startTetheringMethod = internalConnectivityManagerClass.getDeclaredMethod("startTethering",
int.class,
ResultReceiver.class,
boolean.class);
startTetheringMethod.invoke(internalConnectivityManagerClass,
0,
dummyResultReceiver,
true);
} catch (NoSuchMethodException e) {
Method startTetheringMethod = internalConnectivityManagerClass.getDeclaredMethod("startTethering",
int.class,
ResultReceiver.class,
boolean.class,
String.class);
startTetheringMethod.invoke(internalConnectivityManagerClass,
0,
dummyResultReceiver,
false,
context.getPackageName());
} catch (InvocationTargetException e) {
sb.append(11 + (e.getMessage()));
e.printStackTrace();
} finally {
log.setText(sb.toString());
}
} catch (Exception e) {
Log.e("WifiApManager.startTethering", Log.getStackTraceString(e));
}
}
}
複製代碼
經過ConnectivityManager的startTethering方式進行開啓wifi熱點。能夠配置名稱和密碼。是以系統級別的熱點開啓方式。
7.1方式開啓wifi熱點
首先呢,7.1的方式比較奇葩 有的機型能夠經過Wifimanager的方式進行開啓,也能正常鏈接,可是有的能開啓可是沒法正常鏈接。
下面有幾種方式能夠成功的開啓7.1熱點同時也能鏈接上網
java -jar signapk.jar platform.x509.pem platform.pk8 src.apk dst.apk
進行簽名 adb push 到你的手機裏的/system/app/ 目錄下 。別忘了chmod更改 apk權限 同時reboot 最後能夠經過adb shell dumpsys package 包名 查看你的app全部權限。自此 7.1版本的熱點就能夠啓動了。 具體操做能夠給老鐵們一份鏈接花了個把小時寫的東西,但願給老鐵們帶來的是知識的儲備而不是時間的浪費。不早了不早了下班了,