前言:最近项目用到了LocalOnlyHotspot,做Wifi半年了也是第一次接触,在这里把最近俩周的学习内容做个总结。
LocalOnlyHotspot也是一种热点,通过startLocalOnlyHotspot接口打开。打开之后手机的热点图标也会亮起。
下面先看一段官方介绍:
Android P 新增应用API以实现本地协同的多个设备进行内容共享。应用程序可使用该API建立本地SoftAP(不可以共享internet上网),该功能可实现多个应用程序共享同一个LOHS。
通过共享同一个LOHS,多个设备之间不仅可以实现协同播放,还可以进行游戏的局域对战,增强了多个设备之间同个应用程序的互动性。
源码分析
先看startLocalOnlyHotspot代码,参数是LocalOnlyHotspotCallback ,这是一个应用程序的回调类,以接收有关LocalOnlyHotspot状态的更新。
public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback,
@Nullable Handler handler) {
synchronized (mLock) {
Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
LocalOnlyHotspotCallbackProxy proxy =
new LocalOnlyHotspotCallbackProxy(this, looper, callback);
try {
String packageName = mContext.getOpPackageName();
int returnCode = mService.startLocalOnlyHotspot(
proxy.getMessenger(), new Binder(), packageName);
if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) {
// Send message to the proxy to make sure we call back on the correct thread
proxy.notifyFailed(returnCode);
return;
}
mLOHSCallbackProxy = proxy;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
看一下LocalOnlyHotspotCallback 这个类。一共有三个函数,对应热点的状态,相应的处理就写在这三个函数里。它的用法一般是在使用startLocalOnlyHotspot函数时,在startLocalOnlyHotspot参数里直接new一个LocalOnlyHotspotCallback 对象,重写他的方法。
public static class LocalOnlyHotspotCallback {
/** @hide */
public static final int REQUEST_REGISTERED = 0;
public static final int ERROR_NO_CHANNEL = 1;
public static final int ERROR_GENERIC = 2;
public static final int ERROR_INCOMPATIBLE_MODE = 3;
public static final int ERROR_TETHERING_DISALLOWED = 4;
public void onStarted(LocalOnlyHotspotReservation reservation) {};
public void onStopped() {};
public void onFailed(int reason) { };
}
在LocalOnlyHotspotCallback的onStarted函数中,需要LocalOnlyHotspotReservation 参数,它有一个close()函数,用于关闭LocalOnlyHotspot,调用的是stopLocalOnlyHotspot函数。
public class LocalOnlyHotspotReservation implements AutoCloseable {
private final CloseGuard mCloseGuard = CloseGuard.get();
private final WifiConfiguration mConfig;
/** @hide */
@VisibleForTesting
public LocalOnlyHotspotReservation(WifiConfiguration config) {
mConfig = config;
mCloseGuard.open("close");
}
public WifiConfiguration getWifiConfiguration() {
return mConfig;
}
@Override
public void close() {
try {
stopLocalOnlyHotspot();
mCloseGuard.close();
} catch (Exception e) {
Log.e(TAG, "Failed to stop Local Only Hotspot.");
}
}
@Override
protected void finalize() throws Throwable {
try {
if (mCloseGuard != null) {
mCloseGuard.warnIfOpen();
}
close();
} finally {
super.finalize();
}
}
}
LocalOnlyHotspot与普通hotspot区别:
1、LocalOnlyHotspot开启的热点没有网络。
2、LocalOnlyHotspot开启以后,开启它的程序进入后台,热点几秒后就会自动关闭,不管有没有人连。
下面是我写的一个test app。
mainActivity主要代码:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
mWifiConfiguration = new WifiConfiguration();
mSwitch = (Switch) findViewById(R.id.switch_localonlyhotspot);
startState = mWifiManager.isWifiApEnabled();
mSwitch.setChecked(startState);
mLocalOnlyHotspotReservation = mWifiManager.new LocalOnlyHotspotReservation(mWifiConfiguration);
mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
mWifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
@Override
public void onStarted(LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
ssid = reservation.getWifiConfiguration().SSID;
pwd = reservation.getWifiConfiguration().preSharedKey;
ipConfiguration = reservation.getWifiConfiguration().getIpConfiguration();
Log.e("SetLocalOnlyHotSpotController", "ssid and pwd is" + ssid + "and" + pwd + "and" + ipConfiguration);
}
@Override
public void onStopped() {
super.onStopped();
}
@Override
public void onFailed(int reason) {
super.onFailed(reason);
}
}, new Handler());
} else {
mLocalOnlyHotspotReservation.close();
}
}
});
需要定位权限,不仅仅在Androidmainfest中加权限,在手机中还要给这个应用程序定位的权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
续:针对热点自动关闭和无法访问外网的问题,后面做了总结。
https://blog.csdn.net/qq_43804080/article/details/102844381
关注公众号,获取更多开发必备知识