Android11 热点设置永不关闭

2023-11-11

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);
具体不做分析!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android11 热点设置永不关闭 的相关文章

随机推荐

  • 如何在 NodeJs 中上传、处理和存储文件:分步手册

    存储文件有三种基本方法 1 直接将其存储在数据库中 2 将其存储在文件系统中并将路径保存到数据库 3 将其存储在某些云存储中 例如 Amazon S3 Google Cloud Storage 或 Microsoft Azure Blob
  • 去除自定义AlertDialog黑边

    http blog csdn net mwj 88 article details 45482421 1 现象描述 html view plain copy View view LayoutInflater from getActivity
  • java学习笔记——day1

    java笔记 字面量 变量 数据类型 命名规则 类型转换 运算符operator API 程序的流程控制 数组 字面量 变量 字面量 计算机用来处理数据的 字面量就是告诉程序员 数据在程序中的书写格式 字符 单引号 一个字符 字符串 双引号
  • python+selenium自动化软件测试(第3章):unittes

    3 1 unittest简介 前言 python基础比较弱的 建议大家多花点时间把基础语法学好 这里有套视频 可以照着练习下 http pan baidu com s 1i44jZdb 密码 92fs 熟悉java的应该都清楚常见的单元测试
  • 分层测试(一):什么是分层测试?

    什么是分层测试 分层测试是通过对质量问题分类 分层来保证整体系统质量的测试体系 模块内通过接口测试保证模块质量 多模块之间通过集成测试保证通信路径和模块间交互质量 整体系统通过端到端用例对核心业务场景进行验证 用户体验通过手工测试确保无妨碍
  • Unity开发(2)建片草地

    文章目录 1 简述 2 创建 2 1 创建项目 2 2 进入开发窗体 3 建个地面 3 1 新建地面 3 2 调整地面大小 3 3 添加草地 3 3 1 初识Unity图片资源 3 3 2 添加图片资源 3 3 3 修改图片在场景中大小 1
  • C语言入门知识1(零基础新手适用)

    C语言入门知识1 零基础新手适用 程序语言 1 机器语言 机器语言是低级语言 是用01码来编写的二进制代码语言 2 汇编语言 汇编语言也是低级语言 是用英文字母和符号串编写的 3 高级语言 由于汇编语言依赖于硬件体系且符合较多 为了方便高级
  • Go中 defer的使用

    文章目录 简介 示例 使用场景 捕获异常 文件操作 简介 defer 是 Golang 中的一个非常有用的关键字 它用于注册延迟调用 也就是一个函数的执行被延迟到调用它的函数返回之后 常用于资源清理 异常处理等场景 示例 defer 是注册
  • python实现电子邮件编程

    一 几个专业名词 MUA MTA MDA 假设我们自己的电子邮件地址是me 163 com 对方的电子邮件地址是friend sina com 注意地址都是虚构的哈 现在我们用Outlook或者Foxmail之类的软件写好邮件 填上对方的E
  • C++提高8: 类模板成员函数类外实现和类模板分文件编写

    1 类模板成员函数类外实现 类外实现主要有三个关键点 作用域 识别T的数据类型 告诉编译器这是一个类模板 剩下的 就还是基础的类内声明类外定义实现了 直接上代码观察一下 include
  • redis后台实现投票功能

    原创文章 转载请注明出处https blog csdn net qq 41969845 article details 108406059 一 前言 本文以投票功能为例 从实际例子中熟练掌握redis的应用 阅读本文需要有一定的Java基础
  • SparkStreaming与Kafka010之05之01 Consumer

    package Kafka010 import Kafka010 Utils MyKafkaUtils import org apache kafka clients consumer ConsumerRecord import org a
  • 常用网络数据帧格式

    常用网络数据帧格式 1 ARP帧格式 2 ICMP帧格式 3 UDP帧格式 4 TCP帧格式 本文主要介绍ARP ICMP UDP TCP等常用网络数据帧格式 1 ARP帧格式 当一个应用层的数据在网络中传输时 会被逐步封装成链路层的帧 而
  • ffplay源码解析-main入口函数

    main入口函数 初始化 变量 缓存区 SDL窗口初始化等 int main int argc char argv int flags VideoState is av log set level AV LOG TRACE init dyn
  • L1-086 斯德哥尔摩火车上的题(15分) Python

    上图是新浪微博上的一则趣闻 是瑞典斯德哥尔摩火车上的一道题 看上去是段伪代码 s a 1112031584 for i 1 i lt length a i if a i 2 a i 1 2 s max a i a i 1 goto url
  • 2020-11-24-ElasticSearch7.x学习笔记

    笔记记录 B站狂神说Java的ElasticSearch课程 https www bilibili com video BV17a4y1x7zq 在学习ElasticSearch之前 先简单了解一下Lucene Doug Cutting开发
  • 根据PV或者QPS来计算需要多少台机器

    QPS 单个进程每秒请求服务器成功的次数 req sec 总请求数 进程总数 请求时间 一般使用http load进行统计 每台服务器每天的PV QPS x 3600 x 6 或者乘以8小时 一天按照6或者8小时计算 晚上可能没人访问 服务
  • Conda环境 下载Jupyter Lab并使用

    1 下载Jupyter Lab conda 安装方式 conda install jupyterlab conda install c conda forge jupyterlab python 安装方式 pip install jupyt
  • python waitress_python 角度理解web服务器

    概述 web服务器实际上就是一个运行在物理机上的网络服务器 它等待客户端给他发送请求 成功接收后将客户端请求的资源响应给它 客户端与服务端的通信通过http协议实现 客户端可以是浏览器或者可以发送请求的一段程序 一 一个简单的web服务器
  • Android11 热点设置永不关闭

    Android11 热点设置永不关闭 文章目录 Android11 热点设置永不关闭 一 前言 二 framework设置热点永不超时关闭 三 基于 SoftApManager java 研究超时逻辑 三 总结 1 设置热点不关闭的方法 1