1

I have an AppWidget with a configuration activity that launches when the widget is added to the home screen. It works perfectly fine on the emulator, but when I load on a physical device, the widget is not added to the home screen after the configuration activity finishes. Both the emulator and the hardware device are a Samsung Galaxy S7, API level 23, with the app's target API set to 26.

Even if I remove all my logic and just have an empty widget and an empty configuration activity, it does not work on my device. But as soon as I remove the activity from the appwidget-provider xml tag, it works fine.

Any ideas? I'm thinking it must be something with the system settings, maybe the storage options?

I notice these errors that appear when running on the device, but they don't look directly related to the problem

E/MotionRecognitionManager: mSContextService = android.hardware.scontext.ISContextService$Stub$Proxy@e5f8725
E/MotionRecognitionManager: motionService = com.samsung.android.motion.IMotionRecognitionService$Stub$Proxy@57800fa
E/MotionRecognitionManager: motionService = com.samsung.android.motion.IMotionRecognitionService$Stub$Proxy@57800fa

Configuration Activity

public class ConfigureActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_configure);
        setResult(RESULT_CANCELED);
    }

    public void onDoneClick(View view) {
        setResult(RESULT_OK);

        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, WidgetActivity.class);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
        sendBroadcast(intent);

        finish();
    }
}

Widget Activity

public class WidgetActivity extends AppWidgetProvider {

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_activity);

        // Instruct the widget manager to update the widget
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        for (int appWidgetId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId);
        }
    }

    @Override
    public void onEnabled(Context context) {
        // Enter relevant functionality for when the first widget is created
    }

    @Override
    public void onDisabled(Context context) {
        // Enter relevant functionality for when the last widget is disabled
    }
}

Android Manifest

<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.widget">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:installLocation="internalOnly"
        android:theme="@style/AppTheme">

        <activity android:name=".ConfigureActivity">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
            </intent-filter>
        </activity>

        <receiver android:name=".WidgetActivity">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widget_activity_info" />
        </receiver>

    </application>

</manifest>

widget_activity_info.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:configure="com.example.widget.ConfigureActivity"
    android:initialKeyguardLayout="@layout/widget_activity"
    android:initialLayout="@layout/widget_activity"
    android:minHeight="110dp"
    android:minWidth="250dp"
    android:previewImage="@drawable/example_appwidget_preview"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="86400000"
    android:widgetCategory="home_screen|keyguard">

</appwidget-provider>
Danny Buonocore
  • 3,731
  • 3
  • 24
  • 46
  • 1
    Are you correctly setting the result before finishing the `Activity`? You have to call `setResult()` with `RESULT_OK`, and an `Intent` with the widget ID that was passed to you on the starting `Intent`. Section 5 here: https://developer.android.com/guide/topics/appwidgets/index.html#UpdatingFromTheConfiguration. – Mike M. Feb 14 '18 at 23:18
  • @MikeM. yup already doing that, wouldn't be working on the emulator if I hadn't – Danny Buonocore Feb 14 '18 at 23:36
  • Well, I've previously come across behavior inexplicably different between emulators and physical devices, and since you haven't provided any code, we just have to guess. Anyway, I just added a configuration `Activity` to a widget I run on my S7, and I have no issues with it. You'll have to provide a [mcve]. – Mike M. Feb 15 '18 at 00:20
  • Added my boilerplate example that works on the emulator and not on the device. Adding in the relevant XML now – Danny Buonocore Feb 15 '18 at 00:35
  • 1
    Please look again at Section 5 of the link I posted above. The `setResult(RESULT_OK)` call needs to have as the second argument an `Intent` with the widget ID attached as an extra. – Mike M. Feb 15 '18 at 00:37
  • Ahhh I see! Seems to be working great, thanks! Now just need to figure out how to broadcast the intent to the widget instead of handling the remote views in the config activity like that manual does. – Danny Buonocore Feb 15 '18 at 01:05
  • 1
    If you're wanting that broadcast to fire `onUpdate()`, the widget ID must be attached to the `Intent` as an `int` array - e.g., `new int[] { appWidgetId }` - and the key is instead `AppWidgetManager.EXTRA_APPWIDGET_IDS`, plural. – Mike M. Feb 15 '18 at 01:14
  • Oh, btw, I just remembered [this issue with Samsungs](https://stackoverflow.com/a/40709721). Basically, you need to include that same `Intent` with the widget ID in the `setResult(RESULT_CANCELED)`, too. Otherwise, TouchWiz can crash. The docs do say that you should always include the `Intent` in any result, and though some/most launchers will just deal with it, I know for a fact that Samsung's TouchWiz often does not handle it gracefully if you don't. Just FYI. – Mike M. Feb 15 '18 at 03:30

0 Answers0