Minimal Android widget, APPWIDGET_DELETED and APPW

2020-04-11 18:28发布

I have a problem very similar to those that have been asked before, but not exactly the same. References: 1, 2, 3, 4

I have coded up a minimal Android widget, and the APPWIDGET_DELETED and APPWIDGET_DISABLED are never being received.

In references 1 and 2 above, the solution presented is to implement onReceive and explicitly look for those intents. However, I inserted a log call in onReceive, and can confirm that neither of those intents are ever appearing, though APPWIDGET_UPDATE and APPWIDGET_ENABLED are appearing in the logs as expected. To double check this, I also inserted minimal implementations of onDeleted and on onDisabled, with their bodies consisting solely of calls to super with breakpoints placed on them, and these are never reached.

Reference 3 seems to have solved his problem by simply uninstalling and reinstalling his app, but this is ineffective in my case. In fact, I have tried this on multiple emulator images as well as on an actual device, some of which were fresh and have never had previous versions before, and this problem still arises.

Based on the responses in the references saying that these workarounds worked for them, and also the plethora of tutorials online that use the onDeleted and onDisabled methods without mentioning they don't actually work, I'm going to assume that I must be doing something wrong, and this is not a bug in Android.

Here is my minimal manifest file:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.testwidgets">

    <application android:allowBackup="true"
        android:label="@string/app_name"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme">

        <receiver android:label="Test Widget"
                  android:name="com.test.testwidgets.TestWidgetProvider"
                  android:exported="false">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                       android:resource="@xml/test_widget_info"/>
        </receiver>
    </application>

</manifest>

Here is my minimal java source:

public class TestWidgetProvider extends AppWidgetProvider {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.w("Schedule", "On receive " + intent.getAction());
        super.onReceive(context, intent);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        for (int widgetId : appWidgetIds) {
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_widget);
            appWidgetManager.updateAppWidget(widgetId, views);
        }
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
    }

    @Override
    public void onDisabled(Context context) {
        super.onDisabled(context);
    }
}

1条回答
做个烂人
2楼-- · 2020-04-11 18:55

An AppWidgetProvider needs to be exported, so that the core OS process that coordinates app widgets (between hosts and providers) can talk to it. Hence, android:exported="false" is inapropos.

To be honest, I would have expected nothing to work with the provider, rather than only some events.

查看更多
登录 后发表回答