最近写了一个局域网文件传输的小app,涉及到开关wifi的有关知识,在这里分享一下关于Android8.0热点管理的一些小知识点!!相信看到这篇文章的应该都能很好地解决Android8.0以前版本的热点管理,这里就不一一讲述了,下面进入关键。
/*
* 适配于Android_O上创建HotSpot的方法
*/
public void setWifiApEnabledForAndroidO(){
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiManager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
/*
*这里是成功开启wifi后回调的方法,此处的reservation中可以通过.getWifiConfiguration().获取
*到WifiConfiguration,同样的,在WifiConfiguration中可以获取到开启热点的SSID和preSharedKey,
*此方法开启的热点的名称和密码是系统随机生产的,无法自定义名称和密码,至少我到目前为止
没有找到可用于设置8.0名称和密码的方法哈哈哈。
*/
@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
String SSID = reservation.getWifiConfiguration().SSID;
String preSharedKey = reservation.getWifiConfiguration().preSharedKey;
}
@Override
public void onStopped() {
super.onStopped();
}
@Override
public void onFailed(int reason) {
super.onFailed(reason);
}
}, null);
}
保存开启热点方法中的回调参数reservation,可以通过reservation.close();关闭上述所开启的热点,不过个人觉得如果要关闭用户本身的自己开的热点的话,此方法应该不可行,不过第二种方法亲测可以关闭用户自己本身开启的热点。???
/*
* 适配于Android_O上关闭HotSpot的方法
*/
public void closeHotSpotForAndroid_O(){
ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
Field iConnMgrField;
try {
iConnMgrField = connManager.getClass().getDeclaredField("mService");
iConnMgrField.setAccessible(true);
Object iConnMgr = iConnMgrField.get(connManager);
Class<?> iConnMgrClass = Class.forName(iConnMgr.getClass().getName());
Method stopTethering = iConnMgrClass.getMethod("stopTethering", int.class);
stopTethering.invoke(iConnMgr, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
到目前为止,上述的开启和关闭热点应该可以实现了,不过我发现有一些问题还是需要解决的。
1.在如下图工作文件夹中找到与"java"文件夹同级任意文件夹,右键–>New–>AIDL–>AILD File后输入名字Finish,会自动生产aidl文件夹和所创建的aidl文件。
// IMyAidlInterface.aidl
package com.example.zzzzzzzzzzzzzzz.networktransmission;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void setWifiApEnabledForAndroidO();
void closeHotSpotForAndroid_O();
}
3.Clean或ReBuild项目,随后创建一个继承于Service的类,在其中编写远程服务中的本地Binder。
@RequiresApi(api = Build.VERSION_CODES.O)
private final IMyAidlInterface.Stub mBuilder = new IMyAidlInterface.Stub() {
@Override
public void setWifiApEnabledForAndroidO(){
//开启热点的方法代码段
}
@Override
public void closeHotSpotForAndroid_O(){
//关闭热点的方法代码段
};
4.在创建继承于Service的类中,重写onBind()方法,返回builder对象。
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
System.out.println("onBind service");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return mBuilder;
}else{
return null;
}
}
5.在AndroidManifest.xml配置文件中注册该远程服务。
<service
android:name=".service.AndroidOApServer"
android:process=":ap">
<intent-filter>
<action android:name=".service.AIDL_SERVICE"/>
</intent-filter>
</service>
这里的android:process很关键,关系到其是否是单独进程运行
android:process:是否需要在单独的进程中运行,当设置为android:process=”:remote”时,代表Service在单独的进程中运行。注意“:”很重要,它的意思是指要在当前进程名称前面附加上当前的包名,所以“remote”和”:remote”不是同一个意思,前者的进程名称为:remote,而后者的进程名称为:App-packageName:remote。
6.在要开启wifi的activity中声明定义ServiceConnection和编写初始化Service方法。
private IMyAidlInterface apService;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
apService = IMyAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
apService = null;
}
};
private void initApService(){
Intent intent = new Intent();
intent.setAction(".service.AIDL_SERVICE");
bindService(new Intent(MainActivity.getExplicitIntent(SendActivity.this,intent)),serviceConnection, Service.BIND_AUTO_CREATE);
}
apService.setWifiApEnabledForAndroidO();//开启
apService.closeHotSpotForAndroid_O();//关闭
到这里为止,远程服务基本上可以正常开启了,但是Android 8.0对后台服务有限制,这里又需要用到前台服务的相关知识了,即转为前台服务保活,具体前台服务参考这里,转为前台服务后,基于Android 8.0 的app开启热点后切换到后台也不会出现6s热点断开的情况了
开启热点后,所产生的SSID和preSharedKey如何传回UI线程。
通过BoradCastReciver机制,把要传的数据放入Intent中传送即可。
感谢广大csdn博主们发表的有关android8.0热点文章!关于这方面有不懂的问题可以在评论区留言,如果我有看到也第一时间回复你哈!
启发我过河的文章(感谢感谢!!):
https://blog.csdn.net/qq_35986042/article/details/83658581