TextView 値を頻繁に変更するアプリ ウィジェット (ストップウォッチ ウィジェット) を作成しようとしています。これを行うには、ハンドラーで開始して値を更新し、テキストビューをそれらの値に設定するランナブルを使用しています。なんらかの理由で、テキストビューは更新されません。すべてが正常に機能しますが、テキストビューは更新されません。
Handler と Runnable のコードは次のとおりです。
RemoteViews remoteViews;
long sStart, elapsedTime;
private final int REFRESH_RATE = 100;
private Handler sHandler = new Handler();
private Runnable startStopwatch = new Runnable() {
@Override
public void run() {
final long start = sStart;
elapsedTime = System.currentTimeMillis() - start;
updateStopwatch(elapsedTime);
sHandler.postDelayed(this, REFRESH_RATE);
}
};
private void updateStopwatch(long time) {
int seconds = (int) time / 1000;
int minutes = seconds / 60;
int hours = minutes / 60;
long millis = time % 1000;
seconds = seconds % 60;
remoteViews.setTextViewText(R.id.tvStopwatchWidget, String.format("%d : %02d : %02d", hours, minutes, seconds));
remoteViews.setTextViewText(R.id.tvStopwatchMillisWidget, String.format(". %03d", millis));
}
onUpdate メソッドですべてを設定しましたが、すべて正常に動作します。ボタンのクリックでテキストビューを更新する必要がある onReceive メソッドは次のとおりです。
@Override
public void onReceive(Context context, Intent intent) {
remoteViews = new RemoteViews(context.getPackageName(), R.layout.stopwatch_widget_layout);
if (intent.getAction().equals(ACTION_STOPWATCH_WIDGET_START)) {
if (sStart == 0L) {
sStart = System.currentTimeMillis();
} else {
sStart = System.currentTimeMillis() - elapsedTime;
}
sHandler.removeCallbacks(startStopwatch);
sHandler.postDelayed(startStopwatch, REFRESH_RATE);
}
ComponentName widget = new ComponentName(context, StopwatchWidgetProvider.class);
AppWidgetManager.getInstance(context).updateAppWidget(widget, remoteViews);
super.onReceive(context, intent);
}
これは、実際のアプリの更新に使用するコードと同じです。これは機能しますが、アプリ ウィジェット用に変更されているのはこれだけです。時刻が正しく更新されていることはわかっています。ログに表示すると、時刻が正しく更新されます。onReceive メソッドで直接変更すると、テキストビューが適切に変更されることもわかっています。すべてが機能しているように見えますが、何らかの理由で Runnable で試行する時間が更新されないため、これを修正する方法が本当にわかりません。
私もサービスを使って試してみましたが、うまくいきませんでした。そのコードは次のとおりです。
public class SWStartService extends Service {
RemoteViews remoteViews;
long sStart = 0;
long elapsedTime;
private final int REFRESH_RATE = 100;
private Handler sHandler = new Handler();
private Runnable startStopwatch = new Runnable() {
@Override
public void run() {
final long start = sStart;
elapsedTime = System.currentTimeMillis() - start;
updateStopwatch(elapsedTime);
sHandler.postDelayed(this, REFRESH_RATE);
}
};
String sMain, sMillis;
private void updateStopwatch(long time) {
int seconds = (int) time / 1000;
int minutes = seconds / 60;
int hours = minutes / 60;
long millis = time % 1000;
seconds = seconds % 60;
remoteViews.setTextViewText(R.id.tvStopwatchWidget, String.format("%d : %02d : %02d", hours, minutes, seconds));
remoteViews.setTextViewText(R.id.tvStopwatchMillisWidget, String.format(". %03d", millis));
Intent i1 = new Intent(getApplicationContext(), SWStartService.class);
sMain = String.format("%d : %02d : %02d", hours, minutes, seconds);
sMillis = String.format(". %03d", millis);
// Log.d("TEST TIME", String.format("%d : %02d : %02d . %03d", hours, minutes, seconds, millis));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
remoteViews = new RemoteViews(getApplicationContext().getPackageName(), R.layout.stopwatch_widget_layout);
if (sStart == 0L) {
sStart = System.currentTimeMillis();
} else {
sStart = System.currentTimeMillis() - elapsedTime;
}
sHandler.removeCallbacks(startStopwatch);
sHandler.postDelayed(startStopwatch, 100);
intent.putExtra("sMainWidget", sMain);
intent.putExtra("sMillisWidget", sMillis);
sendBroadcast(intent);
return START_REDELIVER_INTENT;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
そのサービスは、次のように onReceive メソッドで呼び出されます。
Intent intent1 = new Intent(context, SWStartService.class);
context.startService(intent1);
サービスを開始するために他のいくつかの手法を試しましたが、それでも TextView を更新できません。
私はそれがかなりずさんであることを知っています。私はそれを機能させるためにいくつかの異なる手法を試しましたが、どれも機能せず、古い手法をクリーンアップしませんでした. remoteViews を直接変更したり、インテントからエクストラを取得して appwidget クラスで変更したりしても機能しませんでした。すべてが空白/nullを返すだけです-何らかの理由でサービス内外のインテントエクストラまたはリモートビュー。そして、これはバッテリーにあまり良くないか、非常に効率的ではないかもしれないことを認識していますが、TextView をまったく更新することさえできないのが気になります。
助言がありますか?
編集:誰かが解決策を望むかもしれないので、ここに:
//Global Variables
ComponentName widget;
AppWidgetManager awManager;
//Set them up in onReceive method
remoteViews = new RemoteViews(context.getPackageName(), R.layout.stopwatch_widget_layout);
widget = new ComponentName(context, StopwatchWidgetProvider.class);
awManager = AppWidgetManager.getInstance(context);
if (intent.getAction().equals(ACTION_STOPWATCH_WIDGET_START)) {
//showStopButton();
if (sStart == 0) {
sStart = System.currentTimeMillis();
} else {
sStart = System.currentTimeMillis() - elapsedTime;
}
sHandler.removeCallbacks(startStopwatch);
sHandler.postDelayed(startStopwatch, REFRESH_RATE);
}
awManager.updateAppWidget(widget, remoteViews);
super.onReceive(context, intent);
//update appwidget in runnable
final long start = sStart;
elapsedTime = System.currentTimeMillis() - start;
updateStopwatch(elapsedTime);
sHandler.postDelayed(this, REFRESH_RATE);
awManager.updateAppWidget(widget, remoteViews);