Spencer Stream
Spencer Stream

Reputation: 616

Sending an Intent from a Fragment to a Widget

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.

Upvotes: 1

Views: 716

Answers (1)

CommonsWare
CommonsWare

Reputation: 1007099

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.

Upvotes: 3

Related Questions