1

I am attempting to send an intent to update a home screen widget. I am unable to successfully send the intent and get the error

android.content.ActivityNotFoundException: Unable to find explicit activity class {com.stream.homewidgets/com.stream.homewidgets.Parking}; have you declared this activity in your AndroidManifest.xml?

which comes from the startActivity(intent) line from my fragment.

I have looked at multiple Stack Overflow posts like the following:

These have not quite been able to fix the issue for me, my code looks to be very similar.

Here is a snippet from my widget:

class Parking : AppWidgetProvider() {

    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray
    ) {
        // There may be multiple widgets active, so update all of them
        for (appWidgetId in appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId, currentFloor)

            val intent = Intent(context, Parking::class.java)
            intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)

            PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
        }
    }

...

}

Here is a snippet from the calling fragment:

class HomeFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        ...

        spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
            override fun onNothingSelected(parent: AdapterView<*>?) {}

            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {

                context?.let {
                    val componentName = ComponentName(it, Parking::class.java)
                    val intent = Intent(context, Parking::class.java)
                    intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
                    val ids = AppWidgetManager.getInstance(it).getAppWidgetIds(componentName)
                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
                    startActivity(intent)
                }
            }

        }
        return root
    }
}

Here is my AndroidManifest.xml

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <receiver android:name=".Parking">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

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

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

So I would like to be able to send an intent to update my widget. I am not sure how to solve this problem. My ".Parking" receiver is in the manifest although it is a receiver and not an activity. I do not know if there is a better way to broadcast an intent. If you know of a more correct way to send the intent to a widget, please let me know.

Spencer Stream
  • 616
  • 2
  • 6
  • 22

1 Answers1

3

Tactically, you are trying to start an activity using a broadcast Intent, which will not work. Use sendBroadcast(), not startActivity().

However, it would be faster and more efficient to just update the app widget directly, using AppWidgetManager and one of its updateAppWidget() methods. Your Parking class is merely a way for the system to request updates. If you wish to push an update, you can do that without involving Parking. Move your app-widget-update code into another class that can be used from both your HomeFragment and Parking.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thank you for your suggestion. Can you help point me in the right direction for common conventions of separating the app-widget-update code into its own class? – Spencer Stream Nov 04 '19 at 16:11
  • @SpencerStream: App widgets are not widely implemented, and so I do not know what the common conventions might look like. – CommonsWare Nov 04 '19 at 17:03