Android 热点是有api设置永久开启,热点名称,热点密码等接口,但是“永久开启”实际上是不自动关闭,重启设备后热点并不会自动开启。
Android Wifi实现开关状态记忆是基于Settings.GLOBAL.WIFI_ON属性,
所以热点如果要实现状态记忆那么也是要设置一个Settings属性或者prop属性,
系统启动后判断属性决定是否启动热点就可以实现热点状态记忆了。
Android Wifi有自己的服务WifiService和服务实现WifiServiceImpl,
热点是没有对应服务的,那怎么办呢?大致有两种方法可以解决。
热点操作其实同样在 WifiServiceImpl 判断处理即可,因为热点的api实现很多也是封装在WifiServiceImpl 里面的。
packages\modules\Wifi\service\java\com\android\server\wifi\WifiServiceImpl.java
import android.os.SystemProperties; //记得导包
/**
* WifiService handles remote WiFi operation requests by implementing
* the IWifiManager interface.
*/
public class WifiServiceImpl extends BaseWifiService {
//系统服务启动后判断Wifi的逻辑方法
public void checkAndStartWifi() {
//根据wifi 属性判断是否启动wifi
mWifiThreadRunner.post(() -> {
。。。
// Check if wi-fi needs to be enabled
boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
Log.i(TAG,"WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled")); //可以看到这里是有个打印的
。。。
}
}
//根据热点 属性判断是否启动热点
mWifiThreadRunner.postDelayed(() -> {
boolean isHotspotEnable = SystemProperties.getBoolean("persist.skg.hotspot.enable", false);
Log.d(TAG, "checkAndStartWifi start ap isHotspotEnable = " + isHotspotEnable);
if (isHotspotEnable) {
startTetheredHotspot(getSoftApConfiguration(), mContext.getPackageName());
}
},
100);//延时一下比较好,避免wifi启动未处理完成
}
}
开机后抓的WifiService 关键字的 logcat 日志:
console:/ # logcat | grep WifiService
12-14 17:34:21.258 639 639 I SystemServiceManager: Starting com.android.server.wifi.WifiService
12-14 17:34:21.289 639 639 I WifiService: Registering wifi
//wifi是否启动日志
12-14 17:34:21.910 639 803 I WifiService: WifiService starting up with Wi-Fi enabled
...
//自己添加的热点是否需要启动的日志
12-14 18:33:35.902 639 803 D WifiService: checkAndStartWifi start ap isHotspotEnable = true
12-14 18:33:35.903 639 803 I WifiService: startTetheredHotspot uid=1000
...
12-14 18:33:36.011 639 803 D WifiService: updateInterfaceIpState: ifaceName=ap0 mode=1 previous LOHS mode= -1
12-14 18:33:36.636 639 863 I WifiService: acquireMulticastLock uid=1000
12-14 18:33:39.621 639 803 D WifiService: handleBootCompleted---mIsBootComplete---true
Android 原生广播:
Intent.ACTION_BOOT_COMPLETED = android.intent.action.BOOT_COMPLETED
应用接收到开机广播后,开启热点:
boolean isHotspotEnable = SystemProperties.getBoolean("persist.skg.hotspot.enable", false);
Log.d(TAG, "checkAndStartWifi start ap isHotspotEnable = " + isHotspotEnable);
if (isHotspotEnable) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mConnectivityManager.startTethering(TETHERING_WIFI, true, null, new Handler(Looper.getMainLooper()));
}
但是开机广播有些方案上会比较慢,有些要界面显示后还要等半分钟左右才才收到开机广播。
这种情况一般是静态接收开机广播的情况,广播优先级并未提高,系统多个接收广播的地方有耗时处理导致。
开机广播慢解决的方法:
1、自定义开机广播,不用等所有的系统服务启动完成就发出该广播
BOOT_COMPLETED 也是在 UserController.java 里面发出的,可以在之前发出自定义广播,
会比所有的 BOOT_COMPLETED 广播都快,但是需要对系统启动有一定的了解,避免写出bug
frameworks\base\services\core\java\com\android\server\am\UserController.java
2、静态广播提高优先级
<receiver android:name=".MyReceiver">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
3、动态注册开机广播
开机广播也是可以动态注册的,一般是在自己定义的系统服务内进行监听,会比静态广播收到更早。
(1)系统服务启动的时候启动热点
(2)开机广播启动热点
怎么设置自己定义的属性,上面并没有讲,因为我这边的系统一般都是自己的设置应用,在设置应用点击开关的时候设置那个属性就行了。
但是如果全是用的原生的应用呢,并且要保证其他app开关热点能够同步信息,就要在热点启动流程里面设置那个属性了, 代码:TetheringManager startTethering 和 stopTethering ,具体流程可以往下看看。
https://blog.csdn.net/wenzhi20102321/article/details/128473734
看了上面启动流程,可以发现热点最重要的日志是在 SoftApManager 里面
logcat -c ;logcat | grep -E "TetheringManager|SoftApManager"
//(1)调用开启热点接口和应用包名
12-19 14:38:01.748 1902 7767 I TetheringManager: startTethering caller:com.my.settings
//(2)热点开启成功
12-19 14:38:01.966 949 1267 D SoftApManager[ap0]: Soft AP is started
//(3)热点部分信息
12-19 14:38:02.430 949 1267 D SoftApManager[ap0]: SoftApInfo update SoftApInfo{bandwidth= 3, frequency= 5745,bssid=be:05:dc:cb:ae:86, wifiStandard= 5, mApInstanceIdentifier= ap0, mIdleShutdownTimeoutMillis= 600000}, isRemoved: false
12-19 14:38:02.431 949 1267 D SoftApManager[ap0]: rescheduleTimeoutMessageIfNeeded ap0, timeoutEnabled=true, isChargingfalse, clientNumber=0
//(4)热点10分钟后自动关闭
12-19 14:38:02.434 949 1267 D SoftApManager[ap0]: Timeout message scheduled, on ap0, delay = 600000
//(5)调用热点关闭和应用包名
12-19 14:38:11.244 1902 1902 I TetheringManager: stopTethering caller:com.my.settings
//(6)热点关闭成功
12-19 14:38:11.556 949 1267 D SoftApManager[ap0]: Soft AP is stopped
12-19 14:38:11.559 949 1267 D SoftApManager[ap0]: Timeout message canceled on ap0
12-19 14:38:11.569 949 1267 V WifiActiveModeWarden: ModeManager removed SoftApManager{id=547203 iface=null role=null}
都是一些自己开发中遇到的知识记录: