Yalantis: iOS, Android And Web App Development Company

Android Widget Development

Mobile application widgets are UI elements that notify users about application updates. They are accessible right from user home screens on Android devices. With the introduction of iOS 8 widgets also came to Today tab in the Notification Center on iPhones. We have already talked about why adding widgets can be beneficial for your application and how can you make use of them when decided to convert iOS app to Android. It's time now to tell you how widgets are developed. We are going to focus on the Android platform for now.

Types of widgets for Android

  • Information widgets. They display information elements that are most crucial for the user. Examples include weather widgets, My Day widget. Essentially the majority of widgets belong to this type.
  • Collection widgets. They display collections of either articles, or emails, or pictures. They are scrollable and when clicked - pull the user to the app.
  • Control widgets. They are remote controls of the main functions of the app. For example, the play button on the music app widget.
  • Hybrid widgets. They combine the elements of different other widgets in one.

how to develop Android widgetsAndroid gives you a possibility to implement widgets for both, the home screen and the lock screen. For example, our app My Day has a free home screen widget and the one for the lock screen, available via in-app purchase. These two types of widgets are implemented similarly.

In this article we are going to focus solely on the information widgets, those with which we have the most experience.

How to make a widget for Android

We are going to describe widgets implementation on the example of the widget for our event countdown timer app My Day. This widget displays the time units until or after the event and the name of the event itself. In order to build it you should take the following steps:

1. Declare an app widget in the manifest file of your Android app:

<receiver
           android:name=".widget.MainWidgetProvider"
        android:icon="@drawable/ic_launcher"
           android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                <action android:name="android.appwidget.action.ACTION_WIDGET_RECEIVER" />
            </intent-filter>
            <meta-data
               android:name="android.appwidget.provider"
               android:resource="@xml/lock_screen_widget" />
        </receiver>

2. Create a configuration file with metadata in the XML directory. Here we define the qualities of our app widget. They may include the following parameters:

  • layout file to let the widget know what it is going to look like
  • size of the widget
  • update intervals
  • resizing possibilities
  • type of the widget -- for home or lock screen
  • preview image in the widget menu and more…

So here is how we configured our My Day widget:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
   android:initialLayout="@layout/widget_days_only_count"
   android:minHeight="@dimen/widget_height"
   android:configure="com.yalantis.myday.activities.MainActivity"
   android:minWidth="@dimen/widget_width"
   android:previewImage="@drawable/widget_preview"
   android:updatePeriodMillis="0" /

Almost all of the attributes in the widget’s configuration are optional and depend on the app itself. As you can see, we didn’t set a resize mode as our app widget doesn’t need resizing, nor did we configure the update time settings. My Day updates depending on the user settings. Therefore, this functionality should be configured differently. How? Keep reading.

3. Implement configuration activity. This activity is launched when user sets the widget to home / lock screen. Configuration screen is optional. It is needed when you want to make widget responsive to user configuration settings, such as fonts, texts, pictures and other elements that the user configures on their own.

4. Create WidgetProvider class. This class has all the widget logics described. We recommend redefining the method onUpdate. It describes what happens when the widget is updated.

@Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                         int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        for (final int appWidgetId : appWidgetIds) {
            updateWidgets(context, appWidgetId);
        }

    }
appWidgetIds here is an array of IDs of all the widgets installed on the user phone. All the app widgets have a unique ID, so you can add as many widgets as you want and create new ones. They get deleted together with the app.

As we have already mentioned, our app widget updates depend on the user settings. To implement this functionality, we create a service that gets launched at a certain time. This time depends on the frequency with which the widget is going to be updated.

My Day user can choose to update the widget every minute, once a month and even once a year, which they define in the app’s settings. The widget works locally and doesn’t need Internet connection.

The service itself contains the following code:

public class WidgetUpdateService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        updateLockAndHomeWidget();
        return START_NOT_STICKY;
    }

    public void updateLockAndHomeWidget() {
        Intent intent = new Intent(this, MainWidgetProvider.class);
        intent.setAction(Constants.IntentActions.WIDGET_UPDATE_ACTION);
        int ids[] = AppWidgetManager.getInstance(this)
                .getAppWidgetIds(new ComponentName(this, MainWidgetProvider.class));
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
        sendBroadcast(intent);
    }
}

The service is launched with the help of AlarmManager.

protected void setWidgetService() {
        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        PendingIntent pi = PendingIntent.getService(this, 0, new Intent(this,
                WidgetUpdateService.class), PendingIntent.FLAG_UPDATE_CURRENT);
        alarmManager.set(AlarmManager.RTC_WAKEUP, App.sharedPrefManager.getUpdateTime(), pi);
    }

Read also: Code Review via GitLab Merge Requests

5. There are several limitations that exist in the widget development process. We can use only the following UI elements:

  • FrameLayout
  • LinearLayout
  • RelativeLayout
  • GridLayout
  • AnalogClock
  • Button
  • Chronometer
  • ImageButton
  • ImageView
  • ProgressBar
  • TextView
  • ViewFlipper
  • ListView
  • GridView
  • StackView
  • AdapterViewFlipper

However, if you look at our My Day app widget, you will see that it has a custom font. We resorted to a little hack in order to make it look the way we wanted it to.

private static Bitmap buildUpdate(String data, Context context, MovingPickerManager movingPickerManager) {
        LayoutInflater layoutInflater = LayoutInflater.from(context);
        LinearLayout linearLayout = (LinearLayout) layoutInflater.inflate(R.layout.event_name_layout, null);
        TextView textView = (TextView) linearLayout.findViewById(R.id.textView);
        textView.setText(movingPickerManager.getSpannedText(data, App.getPickerTextTypeFace()));
        linearLayout.setDrawingCacheEnabled(true);
        linearLayout.measure(
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        linearLayout.layout(0, 0, linearLayout.getMeasuredWidth(),
                linearLayout.getMeasuredHeight());

        linearLayout.buildDrawingCache(true);
        return linearLayout.getDrawingCache();
    }

What we did is create a separate layout without any connection to the widget. Then we predefined the values for this layout and made a bitmap of it. So the Imageview of the widget is the actual bitmap.

6. The widget is ready!

My Day app widget for Android

The whole process of implementation takes about 8 hours if you are experienced enough with widgets development.

Read Android documentation for more information. Will be looking forward to developing widgets for your apps!

 

Tech

Customizable Constructor for Designers of Android Wear

Tech

The Dark Side of Android App Widgets

Tech

Android Studio Plugin Development

Design

How We Developed the Guillotine Menu Animation for Android

Design

Our Experiment Building a Multiselection Solution for Android in Kotlin