【问题标题】:Android Homescreen Widget becomes UnresponsiveAndroid 主屏幕小部件变得无响应
【发布时间】:2014-03-28 13:41:36
【问题描述】:

我正在开发一个 Android 主屏幕小部件,一切正常,除了大约 5 到 6 天后,四个按钮恢复到默认状态并变得无响应。我不明白为什么按钮变得无响应。如果我再次删除并添加小部件,它会再次工作。如果我等待大约 24-48 小时,它会再次开始工作一段时间。

我已尝试删除 android:updatePeriodMillis 以使小部件不会自行更新(它是独立的,只需要在用户交互时才真正需要更新)。这也不起作用。

这就是我在onUpdate 内设置PendingIntents 的方式(模仿this question 的答案):

Intent intent1 = new Intent(context, MyWidgetProvider.class);
intent1.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
intent1.setAction(FIRST_INTENT);
intent1.setData(Uri.parse(first_band_intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, widgetId, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.first_button, pendingIntent1);

然后我在onReceive 方法中更新小部件的视图项:

@Override
public void onReceive(Context context, Intent intent) {
    int widgetID = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
    String preferences = PREFS + Integer.toString(widgetID);
    SharedPreferences values = context.getSharedPreferences(preferences, 0);
    int firstBandValue = values.getInt("first_band_value", 1);
    int secondBandValue = values.getInt("second_band_value", 0);
    int multiplierValue = values.getInt("multiplier_value", 2);
    int toleranceValue = values.getInt("tolerance_value", 1);

    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);

    if (intent.getAction().equals(FIRST_BAND)) {
        // nextBandColor() will set the proper band based on the next value and return an integer that is BandValue + 1
        firstBandValue = getNextBandColor(context, BandType.FIRST, firstBandValue);

        SharedPreferences.Editor editor = values.edit();
        editor.putInt("first_band_value", firstBandValue);
        editor.commit();
    }
    else if (intent.getAction().equals(SECOND_BAND)) {
        // nextBandColor() will return an integer that is BandValue + 1
        secondBandValue = getNextBandColor(context, BandType.SECOND, secondBandValue);

        SharedPreferences.Editor editor = values.edit();
        editor.putInt("second_band_value", secondBandValue);
        editor.commit();
    }
    else if (intent.getAction().equals(MULTIPLIER)) {
        // nextBandColor() will return an integer that is BandValue + 1
        multiplierValue = getNextBandColor(context, BandType.MULTIPLIER, multiplierValue);

        SharedPreferences.Editor editor = values.edit();
        editor.putInt("multiplier_value", multiplierValue);
        editor.commit();
    }
    else if (intent.getAction().equals(TOLERANCE)) {
        // nextBandColor() will return an integer that is BandValue + 1
        toleranceValue = getNextBandColor(context, BandType.TOLERANCE, toleranceValue);

        SharedPreferences.Editor editor = values.edit();
        editor.putInt("tolerance_value", toleranceValue);
        editor.commit();
    }
    else {
        super.onReceive(context, intent);
    }

    //Update the view items based on the new integer values; calls updateAppWidget()
    updateBands(context, widgetID, firstBandValue, secondBandValue, multiplierValue, toleranceValue);

    // Concatenate the integer value of the first band value with the integer value of the second band color
    String value = Integer.toString(firstBandValue) + Integer.toString(secondBandValue);

    // Turn the concatenation of the two integers into a double value
    baseValue = Double.parseDouble(value);

    multiplyBaseValue(multiplierValue);

    String units = getUnitsAndAdjustBaseValue();
    String tolerance = getTolerance(toleranceValue);

    DecimalFormat df = new DecimalFormat("#.#");
    resistance = df.format(baseValue) + units + tolerance;

    remoteViews.setTextViewText(R.id.resistance_value, resistance);


    AppWidgetManager manager = AppWidgetManager.getInstance(context);
    manager.updateAppWidget(widgetID, remoteViews);
}

此小部件设计为独立的,没有任何活动或服务。

更新 1:如果我在 onReceive 的 else 中添加 return 语句到 super.onReceive() 之后,那么它会恢复到原始布局,但不会变得无响应。

更新 2: 我读到 here onReceive() 方法必须在 5 秒内完成处理。问题可能是我的onReceive() 没有在分配的时间内完成,从而导致小部件冻结?

此问题也与设备无关。它发生在 Galaxy Nexus、Nexus 7 2012 和 Galaxy S4 上。

什么可能导致这种无响应的问题?

【问题讨论】:

  • 您需要发布您的 onReceive() 代码以及您在应用程序中拥有的任何活动和服务代码。您的桌面小部件实际上只是一个广播接收器,因此您必须遵循与 BR 相同的规则。 BR 回调以及 Activity 和 Service 回调都发生在主 UI 线程上,所以如果你正在做任何可能阻塞它的事情,就会导致问题。
  • @LarrySchiefer 我已经更新了我的 onReceive 代码。感谢您的建议。我认为问题出在 PendingIntents 上。
  • 没问题,如果有帮助,请告诉我。如果它不只是在上面添加更多您的应用程序代码,我们都可以仔细看看。祝你好运!
  • 你终于找到解决办法了吗?
  • @CarlosHernándezGil 还没有,但我也从这个项目中休息了很长时间......

标签: android android-widget


【解决方案1】:

首先测试您的onReceive() 代码以查看错误是否存在于那里或其他地方 - 在寻找“随机”或“奇怪”错误时最好测试假设。

所以要测试它,绝对简化它,让它 100% 简单。删除所有有趣的代码,并将其更改为简单的文本。不可能有错误的东西。

@Override
public void onReceive(Context context, Intent intent) {
    int widgetID = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);

    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
    remoteViews.setTextViewText(R.id.resistance_value, "1.2 ohms");

    AppWidgetManager manager = AppWidgetManager.getInstance(context);
    manager.updateAppWidget(widgetID, remoteViews);
}

如果这仍然中断,那么您知道该错误不在您的 onReceive() 代码中。这样你就可以去别处看看了。


如果这解决了问题,那么您就知道您的onReceive() 的一部分损坏了小部件。

一点一点地添加代码,添加大量日志记录(Log.d())。

您可能需要查看您的SharedPreferences 访问权限,因为这是文件访问权限。也看看这篇文章,并考虑使用SharedPreferences.Editor.apply()


通常使用这种方法,您将能够找到错误,或者至少将其缩小到真正具体的问题,这样可以更轻松地在此处获得帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-13
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多