How to create android home screen widget with example


AppWidgetSample

Home widget is Representative of you application, all the home screen widget are listed in widget list and user can choose which ever widget they want to put on there home screen.

app widget provide user necessary information from your application, you can use app widget and increase user engagement with your application.

In Android development of app widget is very much easy, you can build fully function app widget with same line of code.

so, i am not going very much deep in theory, let's do same piratical.  

Pre-requesites
For this app you should be familiar with :
  1. Creating,building and ruining application in android studio.
  2. Sending and receiving broadcast intents.  
  3. Creating and sending pending intents.     

Image:-Widget list 
 Step-1
create new_app_widget_information.xml file under the app/src/main/res/xml/ directory of you project, this file contain all the meta data of the application widget which provide android os all the information necessary for app widget like app widget initial layout and app widget update cycle in milliseconds and other information


app/src/main/res/xml/new_app_widget_information.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
    xmlns:android:="https://schemas.android.com/apk/res/android"
    android:initialKeyguardLayout="@layout/new_appwidget_layout"
    android:initialLayout="@layout/new_appwidget_layout"
    android:minHeight="185dp"
    android:minWidth="120dp"
    android:previewImage="@drawable/appwidget_preview"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="1800000"
    android:widgetCategory="home_screen">
</appwidget-provider> 
  
 


step - 2
Now create the layout as you wish for your app widget.
This layout will display on home screen where the user will place the widget.

app/src/main/res/layout/new_app_widget.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:andorid="http://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#05C"
    android:padding="10dp">

    <LinearLayout>
        android:id="@+id/sectionId"
        style="@style/AppWidgetSection"
        android:layout_width="match_parent"
        android:layout_heigh="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:orientation="horizontal">


        <TextView
            android:id="@+id/appWidgetLabel"
            style="@style/AppWidgetLabel"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:text="@string/widgetIdLabel"
            />
        <TextView
            android:id="@+id/appWidgetId"
            style="@style/AppWidgetText"
            android:layout_width="0dp"
            android:layout_height="wrep_contect"
            android:layout_weight="1"
            android:gravity="end"
            android:text="XX"
            />
    </LinearLayout>

    <!-- Panel for widget update date and number of updates -->
    <LinearLayout
        android:id="@+id/sectionUpdate"
        style="@style/AppWidgetSeciont"
        android:layout_width="match_parent"
        android:layout_height="wrap_contect"
        android:layout_align_parentLeft="true"
        android:layout_align_parentStart="true"
        android:layout_below="@id/sectionId"
        android:orientation="vertical">

        <TextView
            android:id="@+id/appWidgetUpdateLabel"
            style="@style/AppWidgetLabel"
            android:layout_width="match_parent"
            android:layout_height="wrap_contect"
            android:layout_marginBottom="2dp"
            android:text="@string/widgetUpdateLabel"
            />
        <TextView
            android:id="@+id/appWidgetUpdate"
            style="@style/AppWidgetText"
            android:layout_width="match_parent"
            android:layout_height="wrap_contect"
            android:text="@string/dateCountFormat"/>

        </LinearLayout>

        <!-- Button for udpate widget -->
        <Button
            android:id="@+id/buttonUpdate"
            style="@style/AppWidgetButton"
            android:layout_width="wrap_contect"
            android:layout_height="wrap_contect"
            android:layout_centerHorizontal="true"
            android:text="@string/updateWidgetBottom"
            />
    </RelativeLayout>

 

 Step - 3
Create the class which will extends AppWidgetProvider class from android framework, this class will be broadcast receiver which will receive all the update send by app widget when user interact with it.
You have to create RemoteViews class object from layout which we define above and after that you need to create pending intent and bind it with any desired view click event handler.

app/src/main/java/com/example/techbuffalos/appwidgetexample/NewAppWidget.java

package com.example.techbuffalos.appwidgetsample;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.widget.RemoteViews;
import java.text.DateFormat;
import java.util.Date;

/*
* App widget provider class, to handle update broadcast intents and updates
* for the app widget
*/
public class NewAppWidget extends AppWidgetProvider{
   
    //Name of the shared preferances file.
    private static final String SHARE_PREF_FILE_NAME =    "com.example.techbuffalos.appwidgetsample";
    private static final String COUNT_KEY = "count";

/**
*    Update a single app widget.This is a helper method for the standard
*   onUpdate() callback that handles on widget update at a time.

*
*   @param context                 The application context.
*   @param appWidgetManager     The app widget manager.
*   @param appWidgetId          The current app widget id.
*
*/
private void updateAppWidget(Context context,
                            AppWidgetManager appWidgetManager,
                            int appWidgetId){

    // Retrive count from prefs.
    SharedPreferences prefsObj =
            context.getSharedPreferences(SHARE_PREF_FILE_NAME,0);

    int count = prefsObj.getInt(COUNT_KEY + appWidgetId,0);
    count++;

    //Get the current time
    String dateString=
        DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date());

    RemoteViews view = new RemoteViews(context.getPackageName(),R.layout.new_app_widget.xml);

    views.setTextViewText(R.id.appWidgetId,String.valueOf(appWidgetId));
    views.setTextViewText(R.id.appWidgetUpdate,
            context.getResource().getString(
                R.string.data_count_format,count,dateString));   


    //save count back to prefs file
    SharedPreference.Editor prefEditor = prefObj.edit()
    prefEditor.putInt(COUNT_KEY + appWidgetId,count);
    prefEditor.apply();   

    //Setup update button to send update requrest as a pending intent
    Intent intentUpdate = new Intent(context,NewAppWidget.class);

    intentUpdate.setAction(AppWidgetManger.ACTION_APPWIDGET_UPDATE);

    // Include widget id to be update as intent extra
    int[] appWidId = new Int[]{appWidgetId};
    intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,appWidId);

    //wrap it all in intent to send a broadcast.
    //Use app widget id as request code (second argument) so that
    //each intent is unique.

    PendingIntent pendingIntent = PendingIntent.getBroadCast(context,
                appWidgetId,intentUpdate,PendingIntent.FLAG_UPDATE_CURRENT);

    //Assign pending intent to the button on click handler
    views.setOnClickPendingIntent(R.id.buttonUpdate,pendingIntent);


    //instract the app widget manager for update the widget.
    appWidgetManageer.updateAppWidget(appWidgetId,views);               
    }

    /**
    *    Override onUpdate method for handle all widget update request.
    *   
    *   @param context                 The application context.
    *   @param appWidgetManager     The app widget manager.
    *   @param appWidgetIds         An array of the app widget IDs.   
    */
    @Override
    public void onUpdate(Context context,AppWidgetManager appWidgetManager,int[] appWidgetIds){
   
        //There can be multiple widget active, so update all of them.
        for(int appWidgetId : appWidgetIds){
            updateAppWidget(context,appWidgetManager,appWidgetId)
        }
    }
}  


Step - 4 
Now one step to go, you need to register you AppWidgetProvider class to AndroidManifest.xml file as a BroadcastReceiver with android.appwidget.action.APPWIDGET_UPDATE intent action.
And also you must need to provide meta data with resource point to file which we create in step-1

app/src/main/AndoridManifest.xml

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

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


        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <receiver android:name=".NewAppWidget">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/new_app_widget_information"/>
        </receiver>
    </application>
</manifest>

 
Bonus : 
Here is the style.xml file which contain all the style which i used in in this example.

app/src/main/res/values/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resource>

<!-- Base application theme -->
<style name="AppTheme" parent="Theme.AppCompact.Light.DarkActionBar">
    <!-- Customize your theme here -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimartyDark</item>
    <item name="colorAccent">@color/colorAccent
</style>

<!-- style for widget's panle - linear layout with white backgournd -->
<style name="AppWidgetSection" parent="@android:style/widget">
   <item name="android:padding">8dp</item>
   <item name="android:layout_marginTop">12dp</item>
   <item name="android:layout_marginLeft">12dp</item>
   <item name="android:layout_marginRight">12dp</item>
   <item name="android:background">@android:color/white</item>
</style>

<!-- style for app widget for labels and main text -->
<style name="AppWidgetLabel" parent="AppWidgetText">
    <item name="android:textStyle">bold</item>
</style>

<!-- style for app widget button -->
<style name="AppWidgetButton" parent="Base.Widget.AppCompat.Button">
    <item name="android:layout_marginTop">12dp</item>
</style>

<style name="AppWidgetText" parent="Base.TextAppearance.AppCompat.Subhead">
    <item name="android:textColor">@android:color/black</item>
</style>
</resource>


Hope you all like this example,
Please leave you comments And let me know your thoughts about this post.

You can download all the code from here.
 



 

 


No comments:

Post a Comment