千葉 (2011年11月 4日 12:00) システム開発事業部 / Android
public class Main extends AppWidgetProvider { private static final String ACTION_CLICK = "sample.widget.animation.ACTION_CLICK"; private static final String ACTION_DRAW = "sample.widget.animation.ACTION_DRAW"; // 描画間隔(ms) private static final long INTERVAL_DRAWING = 30; // 画像のID private static final int[] aiResourceId = new int[]{ R.drawable.image_1, R.drawable.image_2, R.drawable.image_3, R.drawable.image_4, R.drawable.image_5, R.drawable.image_6, R.drawable.image_7, R.drawable.image_8, R.drawable.image_9 }; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // AlermManagerのセット setAlarm(getBaseContext(), ACTION_DRAW, INTERVAL_DRAWING, 0); super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onReceive(Context context, Intent intent) { String sAction = intent.getAction(); String[] sTmp = sAction.split(":"); int iNo; if(sTmp[0].equals(ACTION_DRAW)){ // 次に表示する画像の番号を取得 iNo = Integer.valueOf(sTmp[1]); if(iNo < aiResourceId.length){ // 表示する画像の変更 ComponentName thisWidget = new ComponentName(context, Main.class); AppWidgetManager manager = AppWidgetManager.getInstance(context); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main); remoteViews.setImageViewResource(R.id.imgView, aiResourceId[iNo]); manager.updateAppWidget(thisWidget, remoteViews); // AlermMangerの再セット setAlarm(context, ACTION_DRAW, INTERVAL_DRAWING, (iNo + 1)); } } super.onReceive(context, intent); } /** * AlarmManagerのセット * @param context * @param sAction - 描画するアニメーションを特定する一意のACTION_ID * @param iInterval - 次回描画までの間隔 * @param iFrameNo - 描画フレーム数 */ public static void setAlarm(Context context, String sAction, long iInterval, int iFrameNo){ Intent intent = new Intent(context, Main.class); intent.setAction(sAction + ":" + iFrameNo); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0); AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); long now = System.currentTimeMillis() + 1; long nextTime = now + iInterval; // 古いアラームを削除して再セット am.cancel(sender); am.set(AlarmManager.RTC, nextTime, sender); } /*** * ウィジェット削除時の処理 */ @Override public void onDisabled(Context context) { // ウィジェットが削除されたタイミングでアラームを停止する AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, Main.class); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0); am.cancel(sender); super.onDisabled(context); } }
Androidのホームウィジェットでアニメーション
千葉 (2011年11月 4日 12:00)
システム開発事業部 / Android
タイトル通り、ウィジェットでアニメーションを行うサンプルをご紹介します。
ウィジェットの更新間隔は、設定ファイルに記載することもできますが、
30分未満は指定することができません。
アニメーションを行わせるためには、30分以下の間隔で更新を行うよう、
別途実装を行う必要があります。
但し、設定が可能な時間より短い間隔で更新する、ということからも分かる通り、
今回のサンプルはあくまでこんな事もできるんじゃないかという試みであり、
電池の消費が極端に早くなるなど、実用的なものではない、という事は先に述べておきます。
やっている事は簡単で、AlermManagerを使って数十ms毎に処理を呼び出し、
パラパラ漫画のように画像を順に切り替えているだけです。
サンプルコードは以下の通りです。
public class Main extends AppWidgetProvider { private static final String ACTION_CLICK = "sample.widget.animation.ACTION_CLICK"; private static final String ACTION_DRAW = "sample.widget.animation.ACTION_DRAW"; // 描画間隔(ms) private static final long INTERVAL_DRAWING = 30; // 画像のID private static final int[] aiResourceId = new int[]{ R.drawable.image_1, R.drawable.image_2, R.drawable.image_3, R.drawable.image_4, R.drawable.image_5, R.drawable.image_6, R.drawable.image_7, R.drawable.image_8, R.drawable.image_9 }; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // AlermManagerのセット setAlarm(getBaseContext(), ACTION_DRAW, INTERVAL_DRAWING, 0); super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onReceive(Context context, Intent intent) { String sAction = intent.getAction(); String[] sTmp = sAction.split(":"); int iNo; if(sTmp[0].equals(ACTION_DRAW)){ // 次に表示する画像の番号を取得 iNo = Integer.valueOf(sTmp[1]); if(iNo < aiResourceId.length){ // 表示する画像の変更 ComponentName thisWidget = new ComponentName(context, Main.class); AppWidgetManager manager = AppWidgetManager.getInstance(context); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main); remoteViews.setImageViewResource(R.id.imgView, aiResourceId[iNo]); manager.updateAppWidget(thisWidget, remoteViews); // AlermMangerの再セット setAlarm(context, ACTION_DRAW, INTERVAL_DRAWING, (iNo + 1)); } } super.onReceive(context, intent); } /** * AlarmManagerのセット * @param context * @param sAction - 描画するアニメーションを特定する一意のACTION_ID * @param iInterval - 次回描画までの間隔 * @param iFrameNo - 描画フレーム数 */ public static void setAlarm(Context context, String sAction, long iInterval, int iFrameNo){ Intent intent = new Intent(context, Main.class); intent.setAction(sAction + ":" + iFrameNo); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0); AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); long now = System.currentTimeMillis() + 1; long nextTime = now + iInterval; // 古いアラームを削除して再セット am.cancel(sender); am.set(AlarmManager.RTC, nextTime, sender); } /*** * ウィジェット削除時の処理 */ @Override public void onDisabled(Context context) { // ウィジェットが削除されたタイミングでアラームを停止する AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, Main.class); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0); am.cancel(sender); super.onDisabled(context); } }26行目、ウィジェットが更新されたタイミングで、AlermManagerの設定を行っています。
ここでは、30ms後に再度処理を呼び出すよう、アラームをセットしています。
32~62行目がAlermManagerにより30ms後に呼び出されたときに行う処理です。
ここで、画像の変更とAlermMangerの再セットを行なっています。
規定の枚数分、画像を変更して30ms後にAlermのセットする、という処理を繰り返します。
90~101行目は、ウィジェットが画面から削除されたときの処理です。
今後呼び出しを行わないよう、設定済みのAlermManagerのキャンセルを行なっています。