Android 实现热点开机后自动开启

2023-12-21 22:06:38

Android 实现热点开机后自动开启

一、前言

Android 热点是有api设置永久开启,热点名称,热点密码等接口,但是“永久开启”实际上是不自动关闭,重启设备后热点并不会自动开启。

Android Wifi实现开关状态记忆是基于Settings.GLOBAL.WIFI_ON属性,

所以热点如果要实现状态记忆那么也是要设置一个Settings属性或者prop属性,

系统启动后判断属性决定是否启动热点就可以实现热点状态记忆了。

Android Wifi有自己的服务WifiService和服务实现WifiServiceImpl,

热点是没有对应服务的,那怎么办呢?大致有两种方法可以解决。

二、实现方式

1、在 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

2、在开机广播中开启热点

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、热点开机自启动方式总结

(1)系统服务启动的时候启动热点

(2)开机广播启动热点

怎么设置自己定义的属性,上面并没有讲,因为我这边的系统一般都是自己的设置应用,在设置应用点击开关的时候设置那个属性就行了。

但是如果全是用的原生的应用呢,并且要保证其他app开关热点能够同步信息,就要在热点启动流程里面设置那个属性了, 代码:TetheringManager startTethering 和 stopTethering ,具体流程可以往下看看。

2、热点开启流程

https://blog.csdn.net/wenzhi20102321/article/details/128473734

3、热点启动相关日志

看了上面启动流程,可以发现热点最重要的日志是在 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}

4、其他热点相关知识分享

都是一些自己开发中遇到的知识记录:

Android11 热点设置永不关闭

Android11 设置默认热点名称和热点密码、密码长度

Android11 热点配置信息保存分析

Android13分享热点设置安全性为wpa3

Android11 热点Band值为3

Android11 Wifi 加密类型详解

文章来源:https://blog.csdn.net/wenzhi20102321/article/details/135139745
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。