Tuesday, 29 August 2017

Android App Widgets tutorial with Example

Android App Widgets

Android widgets are views that can be placed on the home screen and are updated periodically. They could be a great options for frequent user interactions with your application without opening the application. They are basically the broad cast receivers which display some data and interacts with the users.
android app widget - android tech point
Resizable Android App Widget - Android Tech Point

Steps to create the widget

Creating android widgets is a simple task. You only need to follow simple steps:

  • Create the xml layout file.
  • Define the XML file (i.e AppWidgetProviderInfo) which includes properties for the widget like size, updating interval, minimum size, resizability etc.
  • Create the java file which will have the callback methods for the app widget.
  • Define the receiver for the widget in the AndroidManifest.xml.
  • (Optional) Configuration activity which is called when a new instance of the app widget is made.

Available view in Android App Widgets

Widgets has some limitations. You can only use few views in the xml of widgets. They are as follows:
  1. AnalogClock
  2. Button
  3. Chronometer
  4. ImageButton
  5. ImageView
  6. ProgressBar
  7. TextView
  8. ViewFlipper
  9. ListView
  10. GridView
  11. StackView
  12. AdapterViewFlipper
And the layout which are supported by the remote views are:
  1. FrameLayout
  2. LinearLayout
  3. RelativeLayout
  4. GridLayout
The subclasses of these views are not supported.

Creating Android App Widgets

Now let's dive into the code to create the widgets. You can get the complete project at Github Repository. Or you can get the code below in this post. We will follow the steps defined in the above portion.

  1. Create the xml layout file.
    Here we will define the layout for our widget just like the regular android xml layout.
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#55000000"
    android:orientation="vertical">
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <ImageView
    android:id="@+id/icon1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:src="@drawable/icon1" />
    <ImageView
    android:id="@+id/icon2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:src="@drawable/icon2" />
    <ImageView
    android:id="@+id/icon3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:src="@drawable/icon3" />
    <ImageView
    android:id="@+id/icon4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:src="@drawable/icon4" />
    <ImageView
    android:id="@+id/icon5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:src="@drawable/icon5" />
    </LinearLayout>
    <Button
    android:id="@+id/widget_button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Open App" />
    </LinearLayout>
    view raw widget.xml hosted with ❤ by GitHub
  2. Define the XML file (i.e AppWidgetProviderInfo) which includes properties for the widget like size, updating interval, minimum size, resizability etc.
    <?xml version="1.0" encoding="utf-8"?>
    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget"
    android:minHeight="40dp"
    android:minWidth="40dp"
    android:resizeMode="horizontal"
    android:updatePeriodMillis="1800000"
    android:widgetCategory="home_screen|keyguard">
    </appwidget-provider>
    view raw widget_info.xml hosted with ❤ by GitHub
  3. Create the java file which will have the callback methods for the app widget. In some cases onAppWidgetOptionsChanged()  is not called on the creation of app widget as it should according to offical docs, so you need to set the UI of widget in onUpdate()  to be on safer side.
    package com.vd.androidwidget;
    import android.app.PendingIntent;
    import android.appwidget.AppWidgetManager;
    import android.appwidget.AppWidgetProvider;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.RemoteViews;
    import android.widget.Toast;
    /**
    * Created by farooq on 8/10/2017.
    */
    public class WidgetProvider extends AppWidgetProvider {
    private Button button;
    @Override
    public void onEnabled(Context context) {
    super.onEnabled(context);
    Toast.makeText(context, "Widget has been added to your home screen!", Toast.LENGTH_LONG).show();
    }
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    super.onUpdate(context, appWidgetManager, appWidgetIds);
    for (int appWidgetId : appWidgetIds) {
    // Register an onClickListener
    Intent intent = new Intent(context, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(context,
    0, intent, 0);
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
    R.layout.widget);
    remoteViews.setOnClickPendingIntent(R.id.widget_button, pendingIntent);
    appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
    /*
    In some launchers onAppWidgetOptionsChanged() method is not called on first time placement of widget.
    So set the widget here and getAppWidgetOptions() requires api >=16
    You don't need this check if you minimum api >= 16
    */
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
    Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
    int colSize = getCellsForSize(options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH));
    updateUI(context, colSize, appWidgetManager, appWidgetId);
    Log.e("App Widget", "Updating UI for the 1st time placement");
    }
    }
    }
    @Override
    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
    Log.e("App Widget", "onAppWidgetOptionsChanged()");
    int colSize = getCellsForSize(newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH));
    Log.e("App Widget", String.valueOf(colSize));
    updateUI(context, colSize, appWidgetManager, appWidgetId);
    }
    /*
    * update the UI according to the number of cols
    * */
    private void updateUI(Context context, int colSize, AppWidgetManager appWidgetManager, int appWidgetId) {
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
    switch (colSize) {
    case 1:
    remoteViews.setViewVisibility(R.id.icon2, View.GONE);
    remoteViews.setViewVisibility(R.id.icon3, View.GONE);
    remoteViews.setViewVisibility(R.id.icon4, View.GONE);
    remoteViews.setViewVisibility(R.id.icon5, View.GONE);
    remoteViews.setViewVisibility(R.id.icon1, View.VISIBLE);
    break;
    case 2:
    remoteViews.setViewVisibility(R.id.icon5, View.GONE);
    remoteViews.setViewVisibility(R.id.icon4, View.GONE);
    remoteViews.setViewVisibility(R.id.icon3, View.GONE);
    remoteViews.setViewVisibility(R.id.icon2, View.VISIBLE);
    remoteViews.setViewVisibility(R.id.icon1, View.VISIBLE);
    break;
    case 3:
    remoteViews.setViewVisibility(R.id.icon5, View.GONE);
    remoteViews.setViewVisibility(R.id.icon4, View.GONE);
    remoteViews.setViewVisibility(R.id.icon3, View.VISIBLE);
    remoteViews.setViewVisibility(R.id.icon2, View.VISIBLE);
    remoteViews.setViewVisibility(R.id.icon1, View.VISIBLE);
    break;
    default:
    remoteViews.setViewVisibility(R.id.icon5, View.VISIBLE);
    remoteViews.setViewVisibility(R.id.icon4, View.VISIBLE);
    remoteViews.setViewVisibility(R.id.icon3, View.VISIBLE);
    remoteViews.setViewVisibility(R.id.icon2, View.VISIBLE);
    remoteViews.setViewVisibility(R.id.icon1, View.VISIBLE);
    break;
    }
    appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
    }
    /**
    * Returns number of cells needed for given size of the widget.
    *
    * @param size Widget size in dp.
    * @return Size in number of cells.
    */
    private static int getCellsForSize(int size) {
    int n = 2;
    while (70 * n - 30 < size)
    ++n;
    return n - 1;
    }
    }
  4. Define the receiver for the widget in the AndroidManifest.xml. You need to define the receiver inside the activity tag. Also give the meta tag.
    <receiver
    android:name=".WidgetProvider"
    android:label="@string/app_name">
    <intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
    android:name="android.appwidget.provider"
    android:resource="@xml/widget_info" />
    </receiver>

Important

That's all. Enjoy the resizable widget for your application. In case of any queries I am always here, comment below or contact me at farooqahmadkhan003@gmail.com.


12 comments:

  1. HTC Thunderbolt 2 that is additionally called as HTC Vigor is supposed to have a lauch date some place in the beginning of October. tutuapp

    ReplyDelete
  2. I'm here representing the visitors and readers of your own website say many thanks for many remarkable
    java training in marathahalli | java training in btm layout

    java training in jayanagar | java training in electronic city

    ReplyDelete
  3. This is beyond doubt a blog significant to follow. You’ve dig up a great deal to say about this topic, and so much awareness. I believe that you recognize how to construct people pay attention to what you have to pronounce, particularly with a concern that’s so vital. I am pleased to suggest this blog.
    Blueprism training in Pune

    Blueprism training in Chennai

    ReplyDelete
  4. Thanks for information , This is very useful for me.
    Keep sharing Lean Six Sigma Green Belt Training Bangalore


    ReplyDelete
  5. Worth reading! Our experts also have given detailed inputs about these trainings & courses! Presenting here for your reference. Do checkout
    oracle training in chennai & enjoy learning more about it.

    ReplyDelete
  6. Infycle Technologies, the top Infycle Technologies, the top software training institute and placement center in Chennai offers the Best Digital Marketing course in Chennai for freshers, students, and tech professionals at the best offers. In addition to Digital Marketing, other in-demand courses such as DevOps, Data Science, Python, Selenium, Big Data, Java, Power BI, Oracle will also be trained with 100% practical classes. After the completion of training, the trainees will be sent for placement interviews in the top MNC's. Call 7504633633 to get more info and a free demo.

    ReplyDelete