イントロ
アプリウィジェットにカスタムビューを含めることはできません。ドキュメントによると、レイアウトで使用できるのは、事前定義されたビューの小さなサブセットのみです。したがって、あなたが言及しAnalogClock
たように、(私が他の回答で示したように)独自のビューを作成してアプリウィジェットに含めることはできません。
AnalogClock
ただし、アプリウィジェットでカスタムを作成するために使用できる他の手段があります。このような実装では、時間を直接設定するAnalogClock
ことは問題にはなりません。
短い答え
AnalogClock
これを実現する方法の1つは、カスタムを描画することですImageView
(これは、アプリウィジェットで許可されているビューの1つです)。繰り返しは、60秒ごとに描画するためにPendingIntent
使用しています(経由)。Service
ImageView
RemoteViews
電池使用量に関する注意
60秒ごとにアプリウィジェットをService
更新するアクションを呼び出すことは、バッテリーでそれほど軽量ではないことに注意してください。Jelly Beanの実装例では、夜間に2%のバッテリーを使用しました(スクリーンオフ、平均ネットワーク強度)。ただし、15秒ごとに画面を更新しているので、アナログ時計の場合は必要ありません。したがって、大まかな見積もりでは、1分あたり1回の更新を行うアプリウィジェットは、夜間にバッテリージュースの約0.5%を消費します。これは、ユーザーにとって重要な場合があります。RemoteViews
ソリューションの詳細
描画サービスの変更
まず最初に、ビューに表示されるものを作成する必要がありService
ますImageView
。描画コードは、AnalogClock
実装からほとんど取得され、必要に応じて再配置されます。まず第一に、時間が変更されたかどうかのチェックはありません-これはService
、私たちも決定したときにのみ呼び出されるためです(たとえば、60秒ごと)。2番目の変更はDrawable
、メソッド内のリソースからsを作成することです。
もう1つの変更は、コードが以下をBitmap
使用してアナログクロックをローカルに描画することCanvas
です。
// Creating Bitmap and Canvas to which analog clock will be drawn.
Bitmap appWidgetBitmap = Bitmap.createBitmap(availableWidth, availableHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(appWidgetBitmap);
ImageView
更新は経由で引き込まれRemoteViews
ます。変更は集約され、ホーム画面のアプリウィジェットにプッシュされます。詳細については、ドキュメントを参照してください)。私たちの場合、変更は1つだけで、特別な方法で行われます。
remoteViews.setImageViewBitmap(R.id.imageView1, appWidgetBitmap);
コードが機能するためには、アナログ時計を描画するために利用可能なスペースを宣言する必要があることに注意してください。で宣言されている内容に基づいてwidget_provider.xml
、の次元を決定できますImageView
。描画する前に、dp
単位を単位に変換する必要があることに注意してください。px
// You'll have to determine tour own dimensions of space to which analog clock is drawn.
final int APP_WIDGET_WIDTH_DP = 210; // Taken from widget_provider.xml: android:minWidth="210dp"
final int APP_WIDGET_HEIGHT_DP = 210; // Taken from widget_provider.xml: android:minHeight="210dp"
final int availableWidth = (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, APP_WIDGET_WIDTH_DP, r.getDisplayMetrics()) + 0.5f);
final int availableHeight = (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, APP_WIDGET_HEIGHT_DP, r.getDisplayMetrics()) + 0.5f);
ここService
にサブクラスの完全なコードを貼り付けました。
また、上部には、表示される時間を設定するためのコードがあります。必要に応じて変更してください。
mCalendar = new Time();
// Line below sets time that will be displayed - modify if needed.
mCalendar.setToNow();
int hour = mCalendar.hour;
int minute = mCalendar.minute;
int second = mCalendar.second;
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
また、ファイルでこれService
とアプリウィジェットを宣言することを忘れないでください。例:AndroidManifest.xml
<receiver
android:name="TimeSettableAnalogClockAppWidget"
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.APPWIDGET_DISABLED"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_provider"/>
</receiver>
<service android:name="TimeSettableAnalogClockService"/>
サービスを使用してアプリウィジェットを更新することに関する最も重要な情報は、このブログ投稿で簡単に説明されています。
図面の呼び出し
更新のスケジュールは、サブクラスonUpdate()
のメソッドで実行されます。これは、ファイルで宣言されています。アプリウィジェットがホーム画面から削除されたときにも削除する必要があります。これは、オーバーライドされたメソッドで実行されます。各メソッドの1つを呼び出す両方のアクションを宣言することを忘れないでください:および。上からの抜粋を参照してください。AppWidgetProvider
AndroidManifest.xml
PendingIntent
onDisabled()
APPWIDGET_UPDATE
APPWIDGET_DISABLED
AndroidManifest.xml
package com.example.anlogclocksettimeexample;
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
public class TimeSettableAnalogClockAppWidget extends AppWidgetProvider {
private PendingIntent service = null;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// super.onUpdate(context, appWidgetManager, appWidgetIds);
final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final Calendar time = Calendar.getInstance();
time.set(Calendar.SECOND, 0);
time.set(Calendar.MINUTE, 0);
time.set(Calendar.HOUR, 0);
final Intent intent = new Intent(context, TimeSettableAnalogClockService.class);
if (service == null) {
service = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
}
alarmManager.setRepeating(AlarmManager.RTC, time.getTime().getTime(), 1000 * 60 /* ms */, service);
}
@Override
public void onDisabled(Context context) {
final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(service);
}
}
メソッドの最後の行はonUpdate()
、最初の更新がすぐに発生するように、60秒ごとに発生する繰り返しイベントをスケジュールします。
AnalogClock
一度だけ描く
上記のコードを使用して、サービスを1回だけ呼び出す最も簡単な方法は、1つのイベントを繰り返すのではなく、時間内に1つのイベントをスケジュールすることです。alarmManager.setRepeating()
次の行で呼び出しを置き換えるだけです。
alarmManager.set(AlarmManager.RTC, time.getTime().getTime(), service);
結果
以下は、時刻が1回だけ設定されたカスタムアプリウィジェットのスクリーンショットAnalogClock
です(アナログ時計の時刻とステータスバーに表示される時刻の違いに注意してください)。