Android11 热点设置永不关闭

Posted 峥嵘life

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android11 热点设置永不关闭相关的知识,希望对你有一定的参考价值。

android11 热点设置永不关闭

文章目录

一、前言

Android 热点默认是10 分钟后没有设备关联是会自动关闭,如果需要设置默认不关闭热点可以有几种方式。

二、framework设置热点永不超时关闭

查阅网上资料Android 的做法:

找到:
CMD_NO_ASSOCIATED_STATIONS_TIMEOUT //超时后触发消息,关闭热点 
修改:
case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT: 
break;这样永远就走不到关闭热点的逻辑

在Android11 framwrok grep 遍历发现CMD_NO_ASSOCIATED_STATIONS_TIMEOUT 有的。

所以在 case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT: 添加 break;跳过关闭逻辑同样是生效的

代码位置:

frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\SoftApManager.java

//找到如下代码进行修改即可:


case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT:
    //添加break 即可完成跳过自动关闭热点逻辑。
    if (true) 
        Log.i(TAG, "timeout but no to close hotspot ap!");
        break;
    
    if (mConnectedClients.size() != 0) 
        Log.wtf(TAG, "Timeout message received but has clients. Dropping.");
        break;
    
    mSoftApNotifier.showSoftApShutDownTimeoutExpiredNotification();
    Log.i(TAG, "Timeout message received. Stopping soft AP.");
    updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
    WifiManager.WIFI_AP_STATE_ENABLED, 0);
    transitionTo(mIdleState);
    break;

其实最好还是添加一个系统属性,可以动态设置是否自动关闭热点。


import android.os.SystemProperties;

//获取
boolean isSanitizeChannel = SystemProperties.getBoolean("persisit.hotspot_auto_close", false);

//设置
SystemProperties.set("key", bool + "");

三、基于 SoftApManager.java 研究超时逻辑

从热点开启ConnectivityManager.startTethering 到 SoftApManager.start(),
这个流程不在这里描述,有兴趣可以自己看看。
这里只看超时相关的代码。


public class SoftApManager implements ActiveModeManager 

    //内部类,不用在意里面真正消息处理,父类内部有Handler处理。
    private class SoftApStateMachine extends StateMachine 
        // Commands for the state machine.
        public static final int CMD_START = 0;
        public static final int CMD_STOP = 1;
        public static final int CMD_FAILURE = 2;
        public static final int CMD_INTERFACE_STATUS_CHANGED = 3;
        public static final int CMD_ASSOCIATED_STATIONS_CHANGED = 4;
        public static final int CMD_NO_ASSOCIATED_STATIONS_TIMEOUT = 5; //超时消息
。。。

        //内部类的内部类!
        private class StartedState extends State 
            private WakeupMessage mSoftApTimeoutMessage;

            private void scheduleTimeoutMessage() 
            if (!mTimeoutEnabled || mConnectedClients.size() != 0) 
                    cancelTimeoutMessage();
                    return;
                
                long timeout = mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis();
                if (timeout == 0) 
                    timeout = mDefaultShutDownTimeoutMills;
                
                //(2)发送延时消息,成功打开热点会触发
                //可以看到这里是当前时间+timeout时间,重点是研究timeout时间
                mSoftApTimeoutMessage.schedule(SystemClock.elapsedRealtime()+ timeout);
                Log.d(TAG, "Timeout message scheduled, delay = "+ timeout);
            

            private void cancelTimeoutMessage() 
                //(3)关闭延时消息,关闭热点会触发
                mSoftApTimeoutMessage.cancel();
                Log.d(TAG, "Timeout message canceled");
            

            @Override
            public void enter() 
                mIfaceIsUp = false;
                mIfaceIsDestroyed = false;
                onUpChanged(mWifiNative.isInterfaceUp(mApInterfaceName));

                Handler handler = mStateMachine.getHandler();
                mSoftApTimeoutMessage = new WakeupMessage(mContext, handler,
                SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG,
                SoftApStateMachine.CMD_NO_ASSOCIATED_STATIONS_TIMEOUT); //(1)超时Message创建,调用启动热点会触发

                mSarManager.setSapWifiState(WifiManager.WIFI_AP_STATE_ENABLED);

                Log.d(TAG, "Resetting connected clients on start");
                mConnectedClients.clear();
                mEverReportMetricsForMaxClient = false;
                scheduleTimeoutMessage();
            
            
            @Override
            public boolean processMessage(Message message) 
                switch (message.what) 
                case CMD_ASSOCIATED_STATIONS_CHANGED:
                    if (!(message.obj instanceof NativeWifiClient)) 
                    Log.e(TAG, "Invalid type returned for"
                    + " CMD_ASSOCIATED_STATIONS_CHANGED");
                    break;
                    case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT:
                    if (!mTimeoutEnabled) 
                    Log.wtf(TAG, "Timeout message received while timeout is disabled."
                    + " Dropping.");
                break;

                case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT: //真正处理超时关闭热点的代码
                    if (!mTimeoutEnabled) 
                        Log.wtf(TAG, "Timeout message received while timeout is disabled." + " Dropping.");
                        break;
                    
。。。
                    mSoftApNotifier.showSoftApShutDownTimeoutExpiredNotification();
                    Log.i(TAG, "Timeout message received. Stopping soft AP.");
                    updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
                    WifiManager.WIFI_AP_STATE_ENABLED, 0);
                    transitionTo(mIdleState);
                break;
            
            
        



从上面代码看重点是超时设置重点是看:


    long timeout = mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis();
    if (timeout == 0) 
        timeout = mDefaultShutDownTimeoutMills;
    
    //(2)发送延时消息,成功打开热点会触发
    //可以看到这里是当前时间+timeout时间,重点是研究timeout时间
    mSoftApTimeoutMessage.schedule(SystemClock.elapsedRealtime()+ timeout);

1、mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis();
一看就是获取某个long数值,查看一下SoftApConfiguration.java 对象是否有相关方法,

查看确实有set 和 get方法,是hide、SystemApi方法,说明系统应用中是可以设置热点超时时间的。


    /**
    * Delay in milliseconds before shutting down soft AP when
    * there are no connected devices.
    */
    private final long mShutdownTimeoutMillis;

    @NonNull
    public Builder setShutdownTimeoutMillis(@IntRange(from = 0) long timeoutMillis) 
        if (timeoutMillis < 0) 
            throw new IllegalArgumentException("Invalid timeout value");
        
        mShutdownTimeoutMillis = timeoutMillis;
        return this;
    


    /**
    * Returns the shutdown timeout in milliseconds.
    * The Soft AP will shutdown when there are no devices associated to it for
    * the timeout duration. See @link Builder#setShutdownTimeoutMillis(long).
    *
    * @hide
    */
    @SystemApi
    public long getShutdownTimeoutMillis() 
        return mShutdownTimeoutMillis;
    

如果配置对象中没有设置数据的情况,那么就要看mDefaultShutDownTimeoutMills值了。

if (timeout == 0) 
    timeout = mDefaultShutDownTimeoutMills;

还是 SoftApManager.java的代码


    private long mDefaultShutDownTimeoutMills;

    
    //构造方法中:
    public SoftApManager (...) 
        ...
        mDefaultShutDownTimeoutMills = mContext.getResources().getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds);
    



继续追config_wifiFrameworkSoftApShutDownTimeoutMilliseconds定义的文件:

frameworks\\opt\\net\\wifi\\service\\res\\values\\config.xml


<!-- Integer delay in milliseconds before shutting down soft AP when there
are no connected devices. -->
<integer translatable="false" name="config_wifiFrameworkSoftApShutDownTimeoutMilliseconds">600000</integer>

所以 mDefaultShutDownTimeoutMills 的默认值是60000,600秒,即10分钟。

三、总结:

1、设置热点不关闭的方法:

(1)在SoftApManager.java 找到case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT

直接break;或者retrun;跳过后续关闭热点操作。

(2)设置热点开启时间长度

在资源配置文件中设置超时时间为永久:2147483647 (Int的最大数值)


<integer translatable="false" name="config_wifiFrameworkSoftApShutDownTimeoutMilliseconds">2147483647</integer>

####(3)在代码开启热点的对象设置超时时间

    //设置无密码,10信道,2.4G的热点信号
    public void setHotspot2_4(View view) 
        private WifiManager mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        //使用Build形式配置对象
        SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
        configBuilder.setSsid(mHotspotName);
        configBuilder.setChannel(10, SoftApConfiguration.BAND_2GHZ);
        //30 分钟:30*60*1000 = 1800000 或者永久 2147483647
        configBuilder.setShutdownTimeoutMillis(2147483647);
        mWifiManager.setSoftApConfiguration(configBuilder.build());
    

有试过setShutdownTimeoutMillis 方法设置30 分钟的时间,发现过了30分钟没自动关闭!
具体原因,可以再源码中添加打印查看哈。

2、其他

     * 热点配置信息对象
     * Android11 使用 WifiManager.setWifiApConfiguration(config); 已经过期,使用已经不能生效!
     * 需要使用:WifiManager.setSoftApConfiguration(config);

具体实现可以看:
frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\WifiServiceImpl.java

虽然最终都是调用:mWifiApConfigStore.setApConfiguration(softApConfig)
但是 setSoftApConfiguration 有更多的健全逻辑,比如:全局更新配置
mActiveModeWarden.updateSoftApConfiguration(softApConfig);
具体不做分析!

以上是关于Android11 热点设置永不关闭的主要内容,如果未能解决你的问题,请参考以下文章

我用android的手机开便携式Wlan热点!屏幕锁定后就断开网络了,该怎么操作!

我用android的手机开便携式Wlan热点!屏幕锁定后就断开网络了,该怎么操作!

Android 11 WiFi热点打开与关闭接口

Android 11 WiFi热点打开与关闭接口

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

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