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

Android Widget触发NetworkOnMainThreadException问题排查求助

问题分析与解决方案

1. 崩溃原因:NetworkOnMainThreadException

你的代码在updateAppWidget方法里直接执行了网络请求(Jsoup.connect(...).get()),而AppWidgetProvider的回调方法(包括onUpdate和updateAppWidget)是在主线程运行的。Android从API 11开始禁止主线程执行网络操作,否则会抛出NetworkOnMainThreadException,目的是避免主线程阻塞导致应用无响应(ANR)。

修复方案:将网络请求移到后台线程

需要把网页抓取逻辑放到后台线程执行,完成后再回到主线程更新Widget。推荐使用ExecutorService创建后台线程,示例修改如下:

void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_design);
    SharedPreferences preferences = context.getSharedPreferences("PREFS", 0);
    int value = preferences.getInt("value", 1);
    views.setTextViewText(R.id.text, "" + value);

    // 先临时更新Widget显示加载状态(可选)
    appWidgetManager.updateAppWidget(appWidgetId, views);

    // 启动后台线程执行网络请求
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.execute(() -> {
        Document doc = null;
        try {
            // 执行网页抓取
            doc = Jsoup.connect("https://pageWeb...").get();
            // 这里添加解析文档的逻辑,比如提取需要的数据
            String fetchedData = doc.select("目标选择器").text();

            // 回到主线程更新Widget
            new Handler(Looper.getMainLooper()).post(() -> {
                views.setTextViewText(R.id.text, fetchedData);
                appWidgetManager.updateAppWidget(appWidgetId, views);
                Log.d("WIDGET", "Widget更新完成!");
            });
        } catch (IOException e) {
            Log.e("WIDGET", "网页抓取失败", e);
            // 失败时更新Widget显示错误信息(可选)
            new Handler(Looper.getMainLooper()).post(() -> {
                views.setTextViewText(R.id.text, "加载失败");
                appWidgetManager.updateAppWidget(appWidgetId, views);
            });
        }
    });
    executor.shutdown();

    // 重新调度定时刷新
    AlarmHandler alarmHandler = new AlarmHandler(context);
    alarmHandler.cancelAlarmManager();
    alarmHandler.setAlarmManager();
}

需补充导入语句:

import android.os.Looper;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

2. 权限页面显示"无需任何权限"的原因

你在Manifest中声明的INTERNET和WAKE_LOCK都属于正常权限,这类权限不需要用户手动授权,系统会自动授予,因此不会在应用权限信息页面显示。只有危险权限(如位置访问、相机、存储等)才会在权限页面展示并需要用户确认。

这是正常行为,不是代码错误,你的权限声明是有效的。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 21:02:52