Entry: main  << >>
Android widget(アンドロイド ウィジェット アプリ)の基本
JUGEMテーマ:Android


●Android widgetの基本
ウィジェットアプリの作成には、以下が必要です。

・AppWidgetProviderInfo オブジェクト
 画面レイアウト、更新頻度、および AppWidgetProvider クラスといったウィジェットアプリのメタデータを XML で記述します。
・AppWidgetProvider クラスの使用
 ウィジェットアプリがブロードキャストイベントを受信・処理するメソッドを持ったクラスです。
・View レイアウト
 ウィジェットアプリの初期レイアウトを XML 定義します。
さらに、ウィジェットアプリ設定アクティビティを実装することができます。これはオプションの Activity で、あるユーザがウィジェットアプリを追加したときに起動され、そのウィジェットの生成のタイミングでウィジェットアプリの設定をそのユーザに対し許可するものです。
以下にそれぞれ説明します。
(次回は、デジタル時計のウィジェットをつくってみます)

---------------------------------------------------------------------
●AndroidManifest でのウィジェットアプリの宣言
アプリケーションの AndroidManifest.xml で AppWidgetProvider クラスを宣言します。
(AppWidgetProvider 実装クラスをブロードキャストレシーバとして<receiver>要素に設定する)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="jp.example.widget.app">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <receiver android:name="MyWidgetProvider" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                   android:resource="@xml/my_appwidget_info" />
        </receiver>
        <!-- サービスを使用する場合、ここに記載します。 -->
        <service android:name="MyWidgetProvider$MyWidgetService" />
    </application>
</manifest>

●AppWidgetProviderInfo メタデータの追加
 AppWidgetProviderInfo はウィジェットアプリの最小のレイアウト上のディメンションやその初期のレイアウトのリソース、ウィジェットアプリの更新頻度、および ( これはオプション ) 作成のタイミングで起動する設定アクティビティといった必須の属性を定義するものです。
ひとつの <appwidget-provider> 要素で XML リソースに AppWidgetProviderInfo オブジェクトを定義し、プロジェクトの res/xml/ フォルダに保存します。例では、my_appwidget_info.xml としてます。

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dp"  <!-- 横セル数(=4)×74-2 -->
    android:minHeight="72dp"  <!-- 縦セル数(=1)×74-2 -->
    android:updatePeriodMillis="0"  <!-- 更新間隔(ms) -->
    android:initialLayout="@layout/my_appwidget_layout"  <!-- 画面レイアウト -->
    android:configure="jp.example.widget.app.MyWidgetConfigure" >  <!-- AppWidgetが追加されたときに起動する Activity -->
</appwidget-provider>
※アクティビティは、パッケージスコープ外からも参照されるから フルパスで指定します。


●ウィジェットアプリレイアウトの作成
ウィジェットアプリのレイアウトは RemoteViews を基本にしており、これはすべて種類のレイアウトやビューをサポートしているわけではない

・RemoteView オブジェクト ( および、結果的にはウィジェットアプリ ) は以下のレイアウトクラスをサポートしています。
FrameLayout
LinearLayout
RelativeLayout

・以下のウィジェットクラス。
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView

・Honeycomb (Android 3.0) から利用できる Viewは次のものです。
ListView
GridView
StackView

プロジェクトの res/layout/ フォルダに保存します。例では、my_appwidget_layout.xml としてます。
<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/clock01"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center" android:textSize="18pt"
    android:text="Starting..."
    />

---------------------------------------------------------------------
●AppWidgetProvider クラスの使用
AppWidgetProvider クラスは BroadcastReceiver を拡張しており、ウィジェットアプリブロードキャストをハンドリングするクラスです。
ブロードキャストイベントが発生したとき、 AppWidgetProvider が以下のメソッド呼び出し受け取ります。
・onUpdate(Context, AppWidgetManager, int[])
 updatePeriodMillis 属性で定義された間隔でウィジェットアプリが更新されると呼び出されます。
またこのメソッドはユーザがウィジェットアプリを追加したときにも呼び出される。
 ここでは、View に対するイベントハンドラの定義や、Service の開始をするなどのセットアップ処理を実行する必要があります。
しかしながら、設定アクティビティを宣言している場合には、(ユーザがウィジェットアプリを追加したときには、)このメソッドは呼び出されません が、後続の更新処理を実行することにより呼び出されます。設定アクティビティは、その設定処理が完了したときに最初の更新を実行する責任を担います (下の App Widget 設定アクティビティの作成 参照 ) 。

・onDeleted(Context, int[])
 ウィジェットアプリが削除されるたびに毎回呼び出されます。
・onEnabled(Context)
 ウィジェットアプリのインスタンスが初めて作成されたときに呼び出されます。例えば、ユーザが 同じウィジェットアプリのインスタンスを 2 つ追加した場合は、これは最初の 1 回目だけ呼び出されます。
・onDisabled(Context)
 ウィジェットアプリの最後のインスタンスが削除されたときに呼び出されます。
・onReceive(Context, Intent)
 すべてのブロードキャスト時、および上記のコールバックメソッドの呼び出しの前に呼び出されます。

---------------------------------------------------------------------
●ウィジェットアプリブロードキャストインテントの受信
AppWidgetProvider がブロードキャストを直接受信したい場合は、独自に BroadcastReceiver を実装するか、
onReceive(Context, Intent) コールバックをオーバーライドします。
以下が意識しておくべき 4つのインテントです。
・ACTION_APPWIDGET_UPDATE
・ACTION_APPWIDGET_DELETED
・ACTION_APPWIDGET_ENABLED
・ACTION_APPWIDGET_DISABLED

---------------------------------------------------------------------
●ウィジェットアプリの設定アクティビティの作成
 ユーザがアプリケーションを追加したときにユーザに初期設定をさせたい場合、設定アクティビティを作成することで実現できます。
ウィジェットアプリの作成時に、この Activity は、(ウィジェットアプリホスト)により自動的に起動されます。
 設定アクティビティは Android マニフェストファイルで、通常のアクティビティとして宣言されていなければなりません。
しかしながら、これはウィジェットアプリホストにより ACTION_APPWIDGET_CONFIGURE アクションを使って起動されることから、このアクティビティは、以下のインテントを受け付ける必要があります。

<activity android:name=".MyWidgetConfigure">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
    </intent-filter>
</activity>

---------------------------------------------------------------------
●設定アクティビティからのウィジェットアプリの更新
 ウィジェットアプリが設定アクティビティを使用してアプリの動作を(初期)設定する方法は AppWidgetManager から直接、更新要求を行うことにより実現できます。
以下は、ウィジェットアプリを更新して、設定アクティビティをクローズするまでの処理手順の概要です。
1)最初に、ウィジェットアプリID をアクティビティで起動されたインテントから取得します。
    Intent intent = getIntent();
    Bundle extras = intent.getExtras();
    if (extras != null) {
        mAppWidgetId = extras.getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
    }
2)ウィジェットアプリの設定を実行します。
3)設定が完了したら、AppWidgetManager のインスタンスを getInstance(Context) の呼び出して取得します。
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
4)RemoteView レイアウトを使用し、updateAppWidget(int, RemoteViews) を呼び出すことによりウィジェットアプリを更新します。
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget);
    appWidgetManager.updateAppWidget(mAppWidgetId, views);
5)最後に、戻り値となるインテントを作成し、それにアクティビティの結果を設定後、アクティビティを完了させます。
    Intent resultValue = new Intent();
    resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
    setResult(RESULT_OK, resultValue);
    finish();
設定アクティビティが最初にオープンされた時点で、アクティビティの結果に RESULT_CANCELED を設定してください。これにより完了に到達する前にユーザがアクティビティを取り消した場合は、ウィジェットアプリホストにはその設定がキャンセルされたという通知がされ、ウィジェットアプリが追加されません。(キャンセル動作が正しく動作します)

---------------------------------------------------------------------
●MyWidgetProvider と MyWidgetService の実装
public class MyWidgetProvider extends AppWidgetProvider {
   
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Intent intent = new Intent(context, MyWidgetService.class);
        context.startService(intent);
    }

    public static class MyWidgetService extends Service {

        @Override
        public void onStart(Intent intent, int startId) {
            RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.what_time_is_it_now);
            remoteViews.setTextViewText(R.id.TextView01, new Date().toLocaleString());

            ComponentName thisWidget = new ComponentName(this, WhatTimeIsItNow.class);
            AppWidgetManager manager = AppWidgetManager.getInstance(this);
            manager.updateAppWidget(thisWidget, remoteViews);
        }

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

●android:updatePeriodMillisを使用しないで定周期動作させる方法
 android:updatePeriodMillis="0"を指定して AlarmManagerを用いて定周期動作させる方法を紹介します。
以下のようなメソッドを作成します。処理内容は、Intentから「PendingIntent」を作成し、それをAlarmManagerに時刻とともに設定します。
AlarmManager#set(int, long, PendingIntent)メソッドの第1引数には、AlarmManager.RTC か AlarmManager.ELAPSED_REALTIME のどちらかを使用するのが望ましいです。これらを使用すると、デバイスをwake up しません。(updatePeriodMillisを使用すると、その間隔でデバイスを wake up します)

final private int interval = 1000;  // 1000msec後にアラームが通知される
private void setAlarm(Context context) {
    Intent alarmIntent = new Intent(context, AlarmManagerSample.class);
    alarmIntent.setAction(ACTION_START_MY_ALARM);
    PendingIntent operation = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
    AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    long now = System.currentTimeMillis() + 1;  // + 1 は確実に未来時刻になるようにする保険
    long oneHourAfter = now + interval - now % (interval);
    am.set(AlarmManager.RTC, oneHourAfter, operation);
}

| てる | 17:25 | comments(0) | trackbacks(0) | - | - |
Comment








Trackback

Calendar

  12345
6789101112
13141516171819
20212223242526
2728293031  
<< August 2017 >>

Category

Profile

ドメイン取得なら

ブログ・サイト公開なら

強制的な広告が殆ど無い
レンタルサーバーです
★☆★ レンタルサーバー!ロリポップ! ★☆★
☆月額105円〜容量最大30GB!Movable TypeやWordpressの簡単インストール付き!☆

Amazonから購入

STM32マイコン徹底入門 (TECH I Processor)

CPUの創りかた

Archives

Search

Entry

Comment

  • ファミコンのコンポジット化(AV化)
    boy (02/08)
  • ファミコンのコンポジット化(AV化)
    momo (03/08)
  • ファミコンのコンポジット化(AV化)
    てる (02/26)
  • ファミコンのコンポジット化(AV化)
    momo (02/26)

Link

Feed

Others

無料ブログ作成サービス JUGEM

Mobile

qrcode
出会い