AppWidgetManager Example
In this step by step example you will learn how to create a sample widget using the AppWidgetManager
.
Hello. We will learn about App Widget Manager via a simple Example right this moment. Welcome. We utilize Kotlin programming language. This is a mobile app development tutorial via android.
What is AppWidgetManager?
It is an open class defined in the android.appwidget
package that Updates AppWidget state; gets information about installed AppWidget providers and other AppWidget related state.
You can see it's API reference here.
What is AppWidgetProvider?
It is a convenience class to aid in implementing an AppWidget
provider. Everything you can do with AppWidgetProvider
, you can do with a regular BroadcastReceiver
. AppWidgetProvider
merely parses the relevant fields out of the Intent that is received in onReceive(Context,Intent)
, and calls hook methods with the received extras.
Extend this class and override one or more of the onUpdate
, onDeleted
, onEnabled
or onDisabled
methods to implement your own AppWidget
functionality.
Demo
Here is the demo GIF of the example we will create:
Step 1: Create Project
Start by creating an empty Android Studio
project.
Step 2: Dependencies
Because we are using Kotlin we will add the kotlin-stdlib-jdk
dependency:
implementation "androidx.appcompat:appcompat:$buildToolsVer"
implementation "androidx.constraintlayout:constraintlayout:$constraintLayoutVersion"
Step 3: Create Sample Widget XML
Our third step is to Create a Sample Widget XML. First, create a folder in your res
directory known as: XML
, and add the following file: sample_widget_info.xml
.
You can see that its root element is app widget provider. We define various properties like minimum height and width of our widget, it's preview image, update period, widget category and initial layout. sample_widget_info.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="@layout/sample_widget"
android:initialLayout="@layout/sample_widget"
android:minHeight="110dp"
android:minWidth="110dp"
android:previewImage="@mipmap/ic_launcher"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen|keyguard"></appwidget-provider>
Step 4: Design the Layouts
We will need two layouts:
(a). sample_widget.xml
Add the code containing the UI elements for your custom widget here:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/widget_margin"
android:orientation="vertical">
<TextView
android:id="@+id/appwidget_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp"
android:contentDescription="@string/appwidget_text"
android:text="This is widget example"
android:textSize="24sp"
android:textStyle="bold|italic" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="HIT ME"
android:id="@+id/widget_button"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="OPEN GOOGLE PLEASE"
android:id="@+id/google_button"/>
</LinearLayout>
(b). activity_main.xml
Then design the MainActivity layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit_text"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button"
android:text="press"/>
</LinearLayout>
Step 5: Write Widget Code
Start by creating the SampleWidget.kt
file and add the following imports including the android.appwidget.AppWidgetManager
and android.appwidget.AppWidgetProvider
:
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.util.Log
import android.widget.RemoteViews
import android.app.PendingIntent
import android.content.Intent
import android.net.Uri
import android.content.ComponentName
Create a class that extends the AppWidgetProvider
:
Define two strings:
private val ACTION_SIMPLEAPPWIDGET = "ACTION_BROADCASTWIDGETSAMPLE"
private val WIDGET_TAG = "SAMPLE_WIDGET_TAG"
Override the onUpdate()
function.Onto it we will pass the context, the app widget manager and an Integer array of app widget IDs.
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
There may be multiple widgets active, so we loop through them and update all of them. To update we call the updateAppWidget
function.
for (appWidgetId in appWidgetIds) {
Log.d(WIDGET_TAG,"update")
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
We will also Override the onEnabled
and onDisabled
functions:
override fun onEnabled(context: Context) {
// Enter relevant functionality for when the first widget is created
Log.d(WIDGET_TAG,"enabled")
}
override fun onDisabled(context: Context) {
// Enter relevant functionality for when the last widget is disabled
Log.d(WIDGET_TAG,"disabled")
}
onReceive()
callback:
Write code that will be called when the button is clicked:
if ((intent.action.equals(ACTION_SIMPLEAPPWIDGET))) {
val views = RemoteViews(context.packageName, R.layout.sample_widget)
views.setTextViewText(R.id.widget_button, "HIT ME AGAIN!")
val appWidget = ComponentName(context, SampleWidget::class.java!!)
val appWidgetManager = AppWidgetManager.getInstance(context)
appWidgetManager.updateAppWidget(appWidget, views)
}
Also write code that will be called broadcast inside the activity:
else if ((intent.action.equals("ACTIVITY_ACTION"))) {
val views = RemoteViews(context.packageName, R.layout.sample_widget)
val text = intent.getStringExtra("name")
views.setTextViewText(R.id.widget_button, text)
val appWidget = ComponentName(context, SampleWidget::class.java!!)
val appWidgetManager = AppWidgetManager.getInstance(context)
appWidgetManager.updateAppWidget(appWidget, views)
}
}
Finally create the updateAppWidget()
function:
private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
// Construct the RemoteViews object
val views = RemoteViews(context.packageName, R.layout.sample_widget)
views.setTextViewText(R.id.appwidget_text, "WIDGET INITIALIZED")
//Sample intent for action example
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"))
val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
views.setOnClickPendingIntent(R.id.widget_button, pendingIntent)
// Construct an Intent which is pointing this class.
val intentTwo = Intent(context, SampleWidget::class.java)
intentTwo.action = ACTION_SIMPLEAPPWIDGET
val pendingIntentTwo = PendingIntent.getBroadcast(context, 0, intentTwo, PendingIntent.FLAG_UPDATE_CURRENT)
views.setOnClickPendingIntent(R.id.google_button, pendingIntent)
views.setOnClickPendingIntent(R.id.widget_button, pendingIntentTwo)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
Here is the full code:
SampleWidget.kt
package pramonow.com.widgetexample
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.util.Log
import android.widget.RemoteViews
import android.app.PendingIntent
import android.content.Intent
import android.net.Uri
import android.content.ComponentName
/**
* Implementation of App Widget functionality.
*/
class SampleWidget : AppWidgetProvider() {
private val ACTION_SIMPLEAPPWIDGET = "ACTION_BROADCASTWIDGETSAMPLE"
private val WIDGET_TAG = "SAMPLE_WIDGET_TAG"
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
Log.d(WIDGET_TAG,"update")
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onEnabled(context: Context) {
// Enter relevant functionality for when the first widget is created
Log.d(WIDGET_TAG,"enabled")
}
override fun onDisabled(context: Context) {
// Enter relevant functionality for when the last widget is disabled
Log.d(WIDGET_TAG,"disabled")
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
//This will be called when the button is clicked
if ((intent.action.equals(ACTION_SIMPLEAPPWIDGET))) {
val views = RemoteViews(context.packageName, R.layout.sample_widget)
views.setTextViewText(R.id.widget_button, "HIT ME AGAIN!")
val appWidget = ComponentName(context, SampleWidget::class.java!!)
val appWidgetManager = AppWidgetManager.getInstance(context)
appWidgetManager.updateAppWidget(appWidget, views)
}
//This will be called by broadcast inside the activity
else if ((intent.action.equals("ACTIVITY_ACTION"))) {
val views = RemoteViews(context.packageName, R.layout.sample_widget)
val text = intent.getStringExtra("name")
views.setTextViewText(R.id.widget_button, text)
val appWidget = ComponentName(context, SampleWidget::class.java!!)
val appWidgetManager = AppWidgetManager.getInstance(context)
appWidgetManager.updateAppWidget(appWidget, views)
}
}
private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
// Construct the RemoteViews object
val views = RemoteViews(context.packageName, R.layout.sample_widget)
views.setTextViewText(R.id.appwidget_text, "WIDGET INITIALIZED")
//Sample intent for action example
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"))
val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
views.setOnClickPendingIntent(R.id.widget_button, pendingIntent)
// Construct an Intent which is pointing this class.
val intentTwo = Intent(context, SampleWidget::class.java)
intentTwo.action = ACTION_SIMPLEAPPWIDGET
val pendingIntentTwo = PendingIntent.getBroadcast(context, 0, intentTwo, PendingIntent.FLAG_UPDATE_CURRENT)
views.setOnClickPendingIntent(R.id.google_button, pendingIntent)
views.setOnClickPendingIntent(R.id.widget_button, pendingIntentTwo)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
Step 6: Write MainActivity code
Go to MainActivity.kt
and add imports:
import android.os.Bundle
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import android.view.View
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import androidx.core.view.accessibility.AccessibilityEventCompat.setAction
import android.content.Intent
import android.widget.Button
import android.widget.EditText
Extend the AppCompatActivity
and override the onCreate()
:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Reference the editText and button:
var editText = findViewById<EditText>(R.id.edit_text)
var button = findViewById<Button>(R.id.button)
button.setOnClickListener { _ ->
AppWidgetManager.getInstance(application).getAppWidgetIds(ComponentName(application,SampleWidget::class.java))
intent.putExtra("name", editText.text.toString())
sendBroadcast(intent)}
}
}
Here is the full code:
MainActivity.kt
import android.os.Bundle
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import android.view.View
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import androidx.core.view.accessibility.AccessibilityEventCompat.setAction
import android.content.Intent
import android.widget.Button
import android.widget.EditText
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var editText = findViewById<EditText>(R.id.edit_text)
var button = findViewById<Button>(R.id.button)
val intent = Intent(this, SampleWidget::class.java)
intent.action = "ACTIVITY_ACTION"
//This action will send broadcast to update the widget
button.setOnClickListener { _ ->
AppWidgetManager.getInstance(application).getAppWidgetIds(ComponentName(application,SampleWidget::class.java))
intent.putExtra("name", editText.text.toString())
sendBroadcast(intent)}
}
}
Step 7: Register Components
Go to your AndroidManifest.xml
And register your MainActivity
as your launcher activity:
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
Then register our AppWidget:
<receiver android:name=".SampleWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/sample_widget_info" />
</receiver>
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
3. | Code: Apache 2.0 License |