Widget на Android: считаем дни до дня X Android 07.10.2010

android_widget.png Сегодня мы продолжим экспериментировать с Android и напишем виджет, который будет считать количество оставшихся дней до определенного события. Я предполагаю, что у вас уже настроен SDK и среда разработки, если нет, то читайте первую часть повествования - Установка и настройка Android SDK. Первое приложение.

Определенным событием будет PyCon Ukaraine, который начнется 23.10.2010.

Создадим новый проект, все этапы описаны в предыдущем посте, в этот раз мы только поменяем имя на PyConWidget, и снимем отметку с Create Activity, у меня получилось так:

Project name: PyConWidget
Build Target: [x] Android 2.1-update1
Application name: PyConWidget
Package name: com.example.pyconwidget
[ ] Create Activity: 
Min SDK Version: 7

Изображение с фоном для виджета и логотипом pycon'a можно найти в файле проекта, прикрепленного в конце поста.

Для начала опишем внешний вид виджета, за это отвечает файл /res/layout/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/bg">
    >
<ImageView
    android:src="@drawable/pylogo"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:paddingTop="1dip"   
/>
<TextView  
    android:id="@+id/text"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    android:textSize="17sp"
    android:gravity="center"
    android:textColor="@android:color/white"
    />
</LinearLayout>

У нас есть: главный layout (LinearLayout), с вертикальным расположением элементов и фоном (атрибут android:background); визуальный компонент ImageView, содержащий логотип; TextView - в котором будем выводить количество дней до pycon.

Файл /res/values/strings.xml содержит строчные константы: название виджета и текст, отображаемый по-умолчанию:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Loading</string>
    <string name="app_name">PyCon Widget</string>
    <string name="widget_name">PyCon Widget</string>
</resources>

Создадим файл /res/xml/widget.xml, в котором опишем параметры виджета:

  • атрибуты android:minWidth и android:minHeight отвечают за размер виджета в dip (density-independent pixel);
  • android:updatePeriodMillis - как часто будет обновляться виджет, в нашем случаи - раз в день. В Android SDK 1.6. минимальное значение было 30 мин., в новых версиях это ограничение сняли. Желательно выставляет разумное значение, иначе чем меньше интервал тем меньше будет жить батарейка;
  • android:initialLayout - layout для виджета;
<?xml version="1.0" encoding="UTF-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="50dip"
android:minHeight="50dip"
android:updatePeriodMillis="86400000"
android:initialLayout="@layout/main"
/>

В файле AndroidManifest.xml добавим тег receiver (внутрь тега application) который отвечает за Broadcast Receiver и указывает, что виджет будет реагировать на событие (intent) - APPWIDGET_UPDATE (т.е. обновляться). Также указываем на layout виджета:

...
<receiver android:name=".PyConWidget" android:label="@string/widget_name">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget" />
</receiver>
...

Осталось только реализовать логику виджета и добавить это все в обработчик события - обновление виджета.

package com.example.pyconwidget;

import java.util.Date;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.widget.RemoteViews;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class PyConWidget extends AppWidgetProvider {
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        Date today = new Date();
        Calendar calendar = new GregorianCalendar(2010, 9, 23);
        long days = (((calendar.getTimeInMillis() - today.getTime())/1000))/86400;
        String txt;

        if (days > 1) {
            txt = days + "\ndays";
        } else if (days == 1) {
            txt = days + "\nday";
        } else if (days == 0 || days == -1) {
            txt = "online";
        } else {
            txt = "closed";
        }

        RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.main);
        updateViews.setTextViewText(R.id.text, txt);
        appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }
}

Класс AppWidgetProvider является базовым для класса нашего виджета PyConWidget, мы переопределяем метод onUpdate, который вызывается при обновлении виджета. Для изменения параметров визуальных компонентов внутри виджетов используются объекты класса RemoteViews. После изменения текста внутри TextView мы говорим WidgetManager что надо бы обновить и сам виджет.

Скриншот виджета:

pycon_widget.jpg

Виджет проверен на HTC Wildfire - все чудесно отображается! :)

Проект в Eclipse для приведенного виджета - pycon_widget.tar.gz

Apk файл с виджетом - PyConWidget.apk

Дополнительное чтиво

Цитата
Если вы не добились успеха сразу, попытайтесь еще и еще раз. А потом успокойтесь и живите в свое удовольствие.
Уильям Клод Филдс
Категории
Архив