You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开机完成后Http请求失效问题排查与解决求助

问题描述

设备:小米Mi 9T(Android 10 API 29)
此前应用通过OkHttp调用Java后端服务正常,重启设备后,注册的BootCompletedReceiver触发正常,但服务器调用抛出超时异常:

java.net.SocketTimeoutException: failed to connect to mydomain/XXX.XXX.238.40 (port 80) from /192.168.1.9 (port XXXXXX) after 20000ms

Manifest中注册的Receiver:

<receiver android:enabled="true" android:exported="true" android:name="com.mysomain.receiver.BootCompletedReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
        <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
        <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
    </intent-filter>
</receiver>

Receiver的实现逻辑:通过Timer定时轮询网络状态,判断连接后启动服务:

public class BootCompletedReceiver extends BroadcastReceiver {
    private static final String TAG = BootCompletedReceiver.class.getSimpleName();
    private static long TIMER_INTERVAL = 10000;
    private Timer timer = new Timer();

    public void onReceive(Context context, Intent intent) {
        timerStart(context);
    }

    private void timerStart(Context context) {
        this.timer.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
                boolean connected = activeNetworkInfo != null && activeNetworkInfo.isConnected();
                if (connected) {
                    timer.cancel();
                    context.startService(new Intent(context, StartWorksService.class));
                }
            }
        }, 0, TIMER_INTERVAL);
    }

}
问题原因
  1. 网络状态判断不准确:activeNetworkInfo.isConnected()仅能判断设备与网络的物理连接状态,无法验证网络是否能正常访问公网。比如WiFi已连接但尚未完成IP分配、网络需要门户认证,或者系统后台网络限制导致请求无法发出,此时该API仍会返回true。
  2. API过时与系统限制:getActiveNetworkInfo()在Android 10(API29)已被标记为过时,且Android 10加强了后台应用的网络访问限制,即使网络连接状态正常,后台应用也可能被限制发起网络请求。
  3. 小米MIUI的额外管控:MIUI有独立的后台权限策略,重启后应用处于后台状态,可能被默认限制了后台联网权限或自启动权限,导致服务启动后无法正常发起网络请求。
  4. Timer轮询的局限性:固定间隔的轮询无法精准捕捉网络真正可用的时机,可能在网络尚未完全就绪时就启动了服务,进而引发连接超时。
解决方案

1. 替换为精准的网络可用性监听

使用ConnectivityManager.NetworkCallback替代轮询,监听网络的真正可用性(而非仅连接状态):

public class BootCompletedReceiver extends BroadcastReceiver {
    private ConnectivityManager.NetworkCallback networkCallback;

    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        
        networkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(@NonNull Network network) {
                super.onAvailable(network);
                // 网络真正可用时启动服务
                context.startService(new Intent(context, StartWorksService.class));
                // 取消监听
                cm.unregisterNetworkCallback(this);
            }
        };

        // 注册网络监听,要求网络可访问公网
        NetworkRequest request = new NetworkRequest.Builder()
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
                .build();
        cm.registerNetworkCallback(request, networkCallback);
    }
}

2. 适配Android 10+的权限与后台任务

  • 在Manifest中添加必要权限:
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    
  • 改用WorkManager处理后台任务,它会自动适配系统的后台限制,并支持网络条件约束:
    // 在Receiver中触发WorkManager
    public void onReceive(Context context, Intent intent) {
        Constraints constraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED) // 网络连接时执行
                .build();
    
        OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(StartWorksWorker.class)
                .setConstraints(constraints)
                .build();
    
        WorkManager.getInstance(context).enqueue(workRequest);
    }
    
    对应的Worker类:
    public class StartWorksWorker extends Worker {
        public StartWorksWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
            super(context, workerParams);
        }
    
        @NonNull
        @Override
        public Result doWork() {
            // 执行原StartWorksService中的任务逻辑
            return Result.success();
        }
    }
    

3. 适配小米MIUI权限

引导用户开启以下权限:

  • 应用的「自启动权限」:小米手机设置→应用设置→应用管理→目标应用→权限管理→自启动,设置为允许。
  • 应用的「后台联网权限」:同样在权限管理中找到后台联网,开启允许。

4. 优化OkHttp配置(可选)

适当调整超时时间并开启重试,应对网络不稳定场景:

OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .retryOnConnectionFailure(true)
        .build();

内容的提问来源于stack exchange,提问作者araraujo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:32:37