AppWidgetを指定した間隔ごとに実行するには
AppWidgetを指定した間隔ごとに実行するには、android:updatePeriodMillisを用いる処理方法があります。サンプルの「SlideShow」というウィジェットがこの方法を用いています。
![]() |
| 図8 指定期間ごとにイメージを再表示 |
ソースコードは、以下のようになっています。
public class SlideShow extends AppWidgetProvider {
static int index = 0;
int[] images = {
R.drawable.g0,
R.drawable.g1,
R.drawable.g2,
R.drawable.g3,
R.drawable.g4,
R.drawable.g5,
R.drawable.g6,
R.drawable.g7,
};
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.slide_show);
remoteViews.setImageViewResource(R.id.ImageView01, images[index]);
index = ++index % images.length;
ComponentName thisWidget = new ComponentName(context, SlideShow.class);
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
- - PR -
まず、必要なのがAppWidgetProviderクラスを継承して作らなければならないということです。そして、繰り返し呼び出されるonUpdate()メソッドをオーバーライドする必要があります。
やっていることは、onUpdate()メソッドが呼び出されるたびに、リソース内の画像をRemoteViesクラスを経由して順番に設定しています。画像を指定するindexがなぜstaticかというと、onUpdate()メソッドが呼び出されるたびに、このクラスのインスタンスが再生成されるためです。
■ AppWidgetでサービスを用いるには
通常は、コールバックメソッドではこういった処理は行わずに、サービスを起動して、サービス内で処理を行うようにします。サンプルの「WhatTimeIsItNow」というウィジェットがサービスを用いる最も簡単な例です。
![]() |
| 図9 秒刻みのデジタル時計 |
ソースコードは、以下のようになっています。
public class WhatTimeIsItNow extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Intent intent = new Intent(context, MyService.class);
context.startService(intent);
}
public static class MyService 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;
}
}
}
onUpdate()メソッドはサービスを起動するだけ、起動されたサービスは実行後即終了します。処理が軽くても重くても、常にこのようにサービスを起動して処理をするのが望ましいです。このサービスはAndroidManifest.xmlに登録されていなければなりません。サービスの登録方法は、連載第7回の「サービスを使用するための設定」を参照してください。
■ しかし、問題が多い
さて、WhatTimeIsItNowは、ホームスクリーンに1秒刻みのデジタル時計を表示するウィジェットですが、こんなウィジェットを作るのはお勧めできません。
- 1秒ごとにonUpdate()メソッドが呼び出される
- バックグラウンドでも(ウィジェットが隠れていても)1秒ごとにonUpdate()メソッドが呼び出される
- ほかのアプリの動作まで重くなる
- 電池の消耗が激しい
特に3.と4.は大きな問題です。
グーグルが公開しているサンプルは、1日1回だけインターネットに「今日の言葉」を取りにいってそれを表示するウィジェットです。確かに1日1回ぐらいであれば、まったく問題にならないので、私もandroid:updatePeriodMillisを用いるのであれば、多くても1時間に1回ぐらいの更新頻度に収めるのがよいのではないかと思います。
android:updatePeriodMillis以外の方法としてAlarmManagerを用いる方法もあるので、ここからは、AlarmManagerの使い方を説明します。
AppWidgetを指定した時間に実行するには
android:updatePeriodMillisをAlarmManagerに置き換えるメリットはいくつかあります。
- android:updatePeriodMillisと同じことができる(コーディングは必要)
- android:updatePeriodMillisと異なり期間を調整可能(コーディングだから)
要するに、設定ファイルに期間を指定すると、コーディングは必要ないけど細かい動作は変更できず、AlarmManagerを使用すると、コーディングは必要だけど細かく動作を設定できる、ということです。
サンプルの「AlarmManagerSample」というウィジェットが、AlarmManagerを使用する例です。このウィジェットは1時間に1度、0分0秒ちょうどに表示を更新する時報アプリです。
詳しくはソースファイル全体を見ていただくとして、ここではAlarmManagerを使用している個所にフォーカスして説明します。
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);
}
3行目のACTION_START_MY_ALARMは、自分で勝手に定義したアクションです。自分で送って自分で受け取るアクションなので、パッケージ名やクラス名を内部に含み、ユニークになるようにしています。
作成したIntentから「PendingIntent」を作成し、それをAlarmManagerに時刻とともに設定しています。AlarmManager#set(int, long, PendingIntent)メソッドの第1引数には、この場合はAlarmManager.RTCかAlarmManager.ELAPSED_REALTIMEのどちらかの定数を使用するのが望ましいです。これらを使用すると、デバイスをwake upしません。
このサンプルでは1時間おきにしていますが、例えば真夜中は頻度を減らしたり、逆に真夜中だから頻度を増やしたり、ということが、自分でコーディングしているからこそ可能になります。
なお、自分で自分にIntentを時刻指定で送信しているので、受信時に次の自分のためのIntentの準備を忘れないようにしてください。
今回、この連載で初めて出てきたPendingIntentというものは、Intentを文字通りペンディングするための便利な入れ物です。次に説明するクリックを用いた処理方法でも、このPendingIntentを使用します。
コラム 「タイミングを見計らってIntentを発信するPendingIntentとは」 |
||||||||||
PendingIntentは、Intentをタイミングを見計らって発信する便利なツールです。以下のような使い方が可能です。
処理対象があらかじめActivityやServiceに絞り込めている場合、これらを使用するのが効果的です。今回のサンプルではsetBroadcast()メソッドとsetService()メソッドを使用しているので、ソースコード参照して使い方を習得してください。 |
AppWidgetをクリック時に実行するには
サンプルの「ClickSample」というウィジェットが、ウィジェットでクリックイベントを拾う例です。
![]() |
| 図10 ウィジェットでクリックイベントを拾うサンプル |
テキスト部分またはボタンをクリックすると、現在時刻を表示するサンプルです。
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.click_sample);
Intent clickIntent = new Intent();
clickIntent.setAction(ACTION_MY_CLICK);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, clickIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.TextView01, pendingIntent);
remoteViews.setOnClickPendingIntent(R.id.Button01, pendingIntent);
上記コードは、RemoteViews経由でGUIコンポーネントにPendingIntentを設定している個所です。
まず、RemoteViewsを作成し、次にIntentを作成します。作成したIntentにはアクションを設定していますが、これはサービスでフィルタするためにユニークな文字列が必要です。パッケージ名やクラス名を組み合わせるのがよいでしょう。この文字列の内容でAndroidManifest.xmlにもフィルタを設定します。
次に、PendingIntentを作成します。作成したPendingIntentを、任意のGUIコンポーネントに設定すれば完了です。
これだけで、設定したGUIコンポーネントをクリックすれば、サービスにIntentが飛んできて、Service#onStart()メソッドが呼び出されます。
AppWidgetを使う際の2つの注意点
AppWidgetは開発者にとって制限があるものの、ホームスクリーンに常駐できるというメリットが開発者にとっても、エンドユーザーにとっても魅力的です。AppWidgetの設定画面をActivityで作成したり、PendingIntentを使用してActivityと連携させたり、サービスを使い捨てないようにしたりすることで、さらにウィジェットがパワフルになると思います。
最後に、本記事執筆中に気が付いた点を紹介して終わりにしようと思います。
■ ウィジェット起動時に空きスペースがない場合
ホームスクリーンにセルの空きがない状態でウィジェットを起動してしまったら、以下のようなメッセージは出ますが、その後表示がされないまま、ずっと裏で動いていることになります。
![]() |
| 図11 空きスペースがない場合の処理 |
この状態になると、エンドユーザーはこの表示されないウィジェットを削除できず、またプログラム的にも表示させるようにすることはできません。このメッセージが出るのは、最初のonUpdate()メソッドが呼び出される前なので、「プログラム的に事前にチェックする」ということもできません。端末を再起動しても表示されない状態で起動したままです。さらに悪いことに、エンドユーザーは表示されていない状態でウィジェットが起動していることに気が付かないでしょう。
Android 1.5時点での、唯一この状態を打開する策は、該当のウィジェットをアンインストールすることだけです。
■ ほかのウィジェットの不具合の影響を受ける可能性がある
例えば、「Foo」というウィジェットがonUpdate()メソッドでNullPointerExceptionなどの例外などを発生させてしまった場合、「Bar」というウィジェットの動作が不安定になってしまうことがあるようです。
この場合、メッセージが出て、どのウィジェットに問題があるかはエンドユーザーが分かるかもしれないので(メッセージが不親切なので、推測しなければならない)、事態は空きスペースがないときより幾分ましです。
開発時に自分のウィジェットで例外を発生させてしまった場合、やはりその後の開発に支障をきたしてしまうことがあります。そうなった場合は、いったん該当のウィジェットを削除して、エミュレータを再起動すれば修復します。
■ @IT関連記事
| Androidアプリで高速描画チューニングをするコツ インタビュー特集:Google直伝!(1) Googleのさまざまなサービスを使いこなすコツをグーグル担当者に聞くインタビュー。初回は日本で端末販売がせまるAndroidについて 「リッチクライアント & 帳票」フォーラム 2009/4/21 |
||
| 業務用途で本当に“使える”モバイル端末はどれだ? 新時代の業務用モバイルRIAを考える(1) iPhoneやAndroid、ネットブックの登場で盛り上がるモバイル業界。しかし業務での利用には“紛失”や操作性などの問題がある 「リッチクライアント & 帳票」フォーラム 2009/2/26 |
||
| Androidのオープン性でガラパゴスから脱出しよう ものになるモノ、ならないモノ(29) ガラパゴスとやゆされる日本の高機能ケータイ。閉塞感に満ちた国内市場から世界に出るための解は、Androidのオープン性にある 「Master of IP Network」フォーラム 2008/12/1
|
||
| Androidは雇い主の分身として仕事をするエージェント Google Developer Day 2008特集(1) Androidの生みの親、アンディ・ルービン氏が、Androidに込めた思いと展望を語る。「Google Android入門」の著者の嶋氏が聞く 「リッチクライアント & 帳票」フォーラム 2008/6/13 |
||
| Google Android用携帯アプリ作成のための基礎知識 小山博史のJavaを楽しむ(9) 先日公開されたGoogleの携帯端末プラットフォームAndroid。開発環境の整え方やアプリの作り方、作成に便利なツール、SDKの中身などを解説 「Java
Solution」フォーラム 2007/12/3 |
ケータイ分野以外の組み込みデバイス開発の現場でも注目を集めている「Android」。組み込みデバイスへの適用からアプリケーション開発、イベントレポート、ニュースなどAndroidに関するさまざまな技術情報・最新動向をお届けします! |
| Index | ||||||||
|
||||||||
Androidで動く携帯Javaアプリ作成入門 バックナンバー 連載インデックスへ»
- 第1回 Android Market配布を目指しEclipseでHelloWorld!
- 第2回 Androidアプリ作成の基本“Activity”とは何か?
- 第3回 ブラウザや地図、ストリートビューの基、Intentとは?
- 第4回 簡単でワクワクするAndroidウィジェット10連発!
- 第5回 Androidアプリの使いやすさを左右する5つのレイアウト
- 第6回 AndroidでSQLiteのDB操作をするための基礎知識
- 第7回 常駐アプリが作成できるAndroidの“サービス”とは
- 第8回 アプリを国際化してAndroid Marketから世界へ発信
- 第9回 Netbookにも広まるAndroidで、かつてないWeb体験を
- 第10回 Androidのホーム画面に常駐するアプリを作るには
- 第11回 Android 1.6のジェスチャーとテキスト読み上げを使う
- 第12回 SurfaceViewならAndroidで高速描画ゲームが作れる
- 第13回 iPhoneより多彩なAndroidのセンサをアプリで操作
- 第14回 Android 2.1の新機能で作る、美しく燃える“待ち受け”
- 第15回 Android NDKでJNIを使用してアプリを高速化するには
- 第16回 地図/位置情報/GPSを使うAndroidアプリを作るには
- 第17回 もはやケータイに必須のカメラをAndroidで制御しよう
- 第18回 開発者が知っておきたいAndroid 2.2新機能 12連発
- 第19回 XMLレイアウトでAndroidアプリに“設定画面”を追加
- 第20回 Androidアプリで“アニメーション”するための基礎知識
- 第21回 アニメーションでAndroidに独創的な画面エフェクトを
- 第22回 開発者が知って得するAndroid 2.3の新機能18選
- 第23回 Android 3.0の新APIで簡単ドラッグ&ドロップ実装
- 第24回 Androidの画面の大きさの違いを解決するFragments
- 第25回 Compatibility packageで2.x系でもマルチサイズ対応
- 第26回 開発者が知らないと損するAndroid 4.0の新機能44選
- 第27回 Android 4.0でアプリ開発を始めるための環境構築
- 第28回 Android 4.0で注目の顔認識をアプリに組み込むには
- 第29回 Androidのウィジェットにノーティフィケーションするには
- 第30回 Androidアプリでマルチメディアを扱うための基礎知識
- 第31回 Android 4.0のサービス/プロセス間通信の基本
| ご意見、ご感想は Smart&Social 会議室へどうぞ |
| Smart&Social フォーラム トップページへ |
TechTargetジャパン
- JenkinsでCIすればAndroidアプリ開発はもう怖くない (2012/5/23)
Androidアプリ開発における継続的インテグレーションの重要性やJenkinsの利点を解説し、環境構築の仕方や使い方の手順を紹介します - Open Graphアプリを作りApp Centerに登録するには (2012/5/18)
ユーザーの活動を共有できるFacebookの新機能を使ったアプリの開発方法と新しいアプリストアへの登録手順を解説 - Bootstrap、Hogan.js、FinagleなどTwitter系OSS (2012/5/15)
Twitterのアーキテクチャやオープンソースへの取り組みなどの講演模様をお届け。OpenJDKやStorm、Gizzard、Twitter4Jも注目 - ソーシャルゲーム/スマホ開発イベント記事が人気 (2012/5/11)
4月はソーシャルゲームの開発者向けイベントや、Webとネイティブの対決が熱かった! UnityやPerfumeも見逃せない!?
|
|
キャリアアップ
スポンサーからのお知らせ
イベントカレンダー
- - PR -






