Skip to content
Related Articles

Related Articles

How to Add Widget of an Android Application?
  • Last Updated : 02 Sep, 2020

It’s known that many of the android apps that have installed on the phone contain widgets. The most common examples are the Calendar and the Clock widget. So what are these Widgets? Widgets are just a mini-app that lives on the home screen and apart from small launcher icons that normally appear on the home screen. Widgets do take up more space and display up to date information of the app. Some of them are user resizable too. The most common use case of the widget is to launch the application or some specific activity of it. 

A widget is basically a broadcast message that communicates with the app using a receiver so you also have to include it into your Manifest File. This seems to be a lot of work, thanks to Android Studio it can do that all for us. So, just go to Android Studio click on app->New->Widget->AppWidget. Give it a name and you are done with setting up the widget. You can even check it that after installation will be having its own widget with a Simple TextView.

Now, after a brief explanation of what a widget is, lets deep dive into how to create it. There are three steps to set up a widget of your app.

  • Step 1: A WidgetProviderClass say, MyWidget, that extends the AppWidgetProvider class.
  • Step 2: A WidgetProviderInfo which is an XML that describes the Widget Metadata including information such as min-height and width.
  • Step 3: A widget layout file that will describe how your widget looks, but it has limitations from other layout files.

MainActivity File

Now let’s come creating our own Custom Widget which requires coding now. Create a MainActivity.xml file in the Layout folder of res directory in the following manner containing a Listview. 

XML






<--!MainActivity.xml-->
<androidx.constraintlayout.widget.ConstraintLayout 
       xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    
     <!--List view to display all food items-->
    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recipies"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
  • Now create a java file initializing all views and setting up the Listview, also populating it with items.
  • Name the Java file as MainActivity.Java.

Java




import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
  
public class MainActivity extends AppCompatActivity {
    ListView recipies;
    public String[] addRecipie
        = new String[] { "Lemonade", "BreadToast" };
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        
        // Attach your aml file with java file here
        setContentView(R.layout.activity_main);
        
        // Creating Java object for List of all food items.
        recipies = findViewById(R.id.recipies);
        
        // Adapter to hold your data of all food items
        ArrayAdapter<String> adapter
            = new ArrayAdapter<String>(
                this, android.R.layout.simple_list_item_1,
                addRecipie);
        recipies.setAdapter(adapter);
        
        // Set a clickListener on each item,so on clicking
        // item an intent will launch.
        recipies.setOnItemClickListener(
            new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(
                    AdapterView<?> adapterView, View view,
                    int i, long l)
                {
                    Intent in
                        = new Intent(MainActivity.this,
                                     DetailsActivity.class);
                    
                    // putExtra method allows you to pass
                    // data between two activities easily
                    in.putExtra("name", addRecipie[i]);
                    in.putExtra("pos", i);
                    startActivity(in);
                }
            });
    }
}

Output:

output screen

DetailsActivity File

Now, we have added two items to our list of recipies and each item contains a clicklistener attached that would navigate to DetailsActivity.java with intended information passing through intent. The following is the layout for DetailsActivity.xml containing two textview and a AddWidget Button(ImageView).

XML




<--!DetailsActivity.xml>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DetailsActivity">
        
    <!--A Textview to display name of food-->
    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
      
    <!--A ImageView to let user add a widget by clicking on it -->
    <ImageView
        android:id="@+id/addToWidget"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"
        android:clickable="true"
        android:contentDescription="@string/addtowidget"
        android:focusable="true"
        android:src="@drawable/not_widget"
        app:layout_constraintBottom_toTopOf="@+id/steps"
        app:layout_constraintStart_toStartOf="parent"/>
        
      <!--A TextView to show steps -->
    <TextView
        android:id="@+id/steps"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/name"
        app:layout_constraintVertical_bias="0.158"/>
  
</androidx.constraintlayout.widget.ConstraintLayout>
  • Create an instance of AppWidgetManager object.
  • Give it an id,i.e AppWidgetId, to make it unique.
  • Use the app->new->vector asset->select a drawable that you want your image to display like we have chosen star vector(R.drawable.addToWidget).

Java




import android.appwidget.AppWidgetManager;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
  
public class DetailsActivity extends AppCompatActivity {
    TextView name, content;
    ImageView addToWidget;
    boolean added = false;
  
    // Take your steps of food processig as String variables
    // recipie1 and recipie2.
    private String recipie1
        = "Step1: Take a Lemon and required no of glasses of water"
          "Step2: Squeeze out the lemon juice into glasses,stir well" +
          "and put iceCubes before serve";
    private String recipie2
        = "Step1: Take a bread and apply some butter on it" +
          "Step2:Put it in the toaster and it is ready";
    ArrayList<String> steps = new ArrayList<String>();
    public static Recipie recipie;
    AppWidgetManager appWidgetManager;
    int appWidgetId;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
  
        // attach xml file for detailsActivity,that will
        // show detail of every food item
        setContentView(R.layout.activity_details);
  
        // Add Steps into step ArrayList
        steps.add(recipie1);
        steps.add(recipie2);
        addToWidget = findViewById(R.id.addToWidget);
  
        // AppWidgetManager manages creating and updating
        // the multiple widgets an application can have.
        appWidgetManager = AppWidgetManager.getInstance(
            DetailsActivity.this);
        appWidgetId = 1;
  
        // Each AppWidget has a different appWidgetId to
        // make it unique.
        name = findViewById(R.id.name);
        content = findViewById(R.id.steps);
        final String heading
            = getIntent().getStringExtra("name");
        final int pos = getIntent().getIntExtra("pos", -1);
        recipie = new Recipie(heading, steps.get(pos));
        name.setText(heading);
        content.setText(steps.get(pos));
  
        // Attach clickListener on ImageView Object so when
        // we will click it will handle the widget adding
        // code.
        addToWidget.setOnClickListener(
            new View.OnClickListener() {
                @Override public void onClick(View view)
                {
                    added
                        = !added; // boolean variable to
                                  // know the state ,if
                                  // widget is added or not.
                    Toast
                        .makeText(DetailsActivity.this,
                                  "Click",
                                  Toast.LENGTH_SHORT)
                        .show();
                    if (added) {
                        // Calling updateAppWidget static
                        // method of RecipieWidget to update
                        // widges of app
                        RecipieWidget.updateAppWidget(
                            DetailsActivity.this,
                            appWidgetManager, appWidgetId,
                            recipie);
                        Toast
                            .makeText(DetailsActivity.this,
                                      "Added to Widegt",
                                      Toast.LENGTH_SHORT)
                            .show();
                        addToWidget.setImageDrawable(
                            getResources().getDrawable(
                                R.drawable.add_widget));
                    }
                    else {
  
                        addToWidget.setImageDrawable(
                            getResources().getDrawable(
                                R.drawable.not_widget));
                        RecipieWidget.updateAppWidget(
                            DetailsActivity.this,
                            appWidgetManager, appWidgetId,
                            null);
                    }
                }
            });
    }
    // This method was created to pass Recipe object
    // information to AppWidget.
    public static Recipie getRecipie() { return recipie; }
}

Output:

output screen

Recipe.Java File

Now, each Recipe contains a Recipe name(String) and a Recipe Steps(String) so for our ease of maintaining we will create a Recipe object.

Java




package com.tanya.widgettutorial;
  
public class Recipe {
    // The recipie include name of food item and steps to
    // cook it.
    private String name;
    private String steps;
    public Recipe(String name, String steps)
    {
        this.name = name;
        this.steps = steps;
    }
    // Getters and Setters
    public String getName() { return name; }
  
    public void setName(String name) { this.name = name; }
  
    public String getSteps() { return steps; }

Three words you must know about a widget:

  • RemoteView: Now, previously I mentioned that widget layout is the same as any other layout. So, basically Widget Layout is based on RemoteView because they are treated as a separate app on your homescreen. RemoteView is used to describe a view hierarchy that will be displayed in another process.
  • onUpdate() method: The onUpdate() method is called when a new Widget is created and also during each update interval which is set in the Widgetinfo.xml file,i.e generated when you have created Widget for your app under the xml directory.
  • AppWidgetManager class: This class consists of all the information about the widgets that are present at home. It also provides access t force updates on all existing widgets.

RecipeWidget.Java

Java




import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.util.Log;
import android.widget.RemoteViews;
  
// Implementation of App Widget functionality.
public class RecipeWidget extends AppWidgetProvider {
  
    public static String TAG = RecipeWidget.class.getName();
  
    static void
    updateAppWidget(Context context,
                    AppWidgetManager appWidgetManager,
                    int appWidgetId, Recipie recipie)
    {
        // Create RemoteView Object to handle your view of
        // widget
        RemoteViews views
            = new RemoteViews(context.getPackageName(),
                              R.layout.recipie_widget);
  
        assert recipie != null;
        // Set what content you want to display on Widget by
        // providing id of view and corresponding content
        views.setTextViewText(R.id.heading_text,
                              recipie.getName());
        views.setTextViewText(R.id.steps_text,
                              recipie.getSteps());
        appWidgetManager.updateAppWidget(appWidgetId,
                                         views);
    }
  
    @Override
    public void onUpdate(Context context,
                         AppWidgetManager appWidgetManager,
                         int[] appWidgetIds)
    {
        // There may be multiple widgets active, so update
        // all of them
        for (int appWidgetId : appWidgetIds) {
            Recipie recipie = DetailsActivity.getRecipie();
            Log.d(TAG, recipie.getName());
            updateAppWidget(context, appWidgetManager,
                            appWidgetId, recipie);
        }
    }
  
    @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
    }
}

Output:

output screen

Want a more fast-paced & competitive environment to learn the fundamentals of Android?
Click here to head to a guide uniquely curated by our experts with the aim to make you industry ready in no time!
My Personal Notes arrow_drop_up
Recommended Articles
Page :