※画像は弊社『電卓』のウィジェットです。
Androidのウィジェットで2つのボタンを検知する方法。
1つだとサンプルソースがネット上に沢山ありますが、2つ以上だと無く、3時間程ハマったので。
ボタンのクリックイベントを拾う方法は色々ありますが、
今回は、ProviderでSerciseを起動。
ServiseでボタンのActionを紐付け。
という方法です。
縦画面固定であれば、ここまででOKです。
が、今回は横画面に切り替えた際もクリックイベントを検知したい。
ここで若干ハマりました。(というか良いサンプルが見つからなかった)
先ずはAppWidgetProviderでServiceを実行します。
public class SampleWidgetProvider extends AppWidgetProvider {
public SampleWidgetProvider() {
}
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
// ホームウィジェットを処理するサービスの実行
Intent service = new Intent(context, SampleWidgetService.class);
context.startService(service);
}
public void onDisabled(Context context, Intent intent) {
super.onDisabled(context);
// サービスの停止
Intent service = new Intent(context, SampleWidgetService.class);
context.stopService(service);
}
}
ServiceのonStart()で紐付けする際は、1つのIntentに複数追加しても正常動作します。
が、横画面に切り替えた際、on〜Changed()で同じように1つのIntentに複数追加すると、最後に追加したボタンしか検知できません。
クリックのActionはIntent毎に紐付けしています。
なのでボタンの数だけIntentを発行すればOK。
ソースはこんな感じ。
onStart()でボタンクリックを紐付けして、onConfigurationChanged(Configuration newConfig)で画面回転時など再度紐付けしています。
public class SampleWidgetService extends Service {
private static final String ACTION_1 = "com.example.samplewidget.SampleWidgetService.ACTION_1";
private static final String ACTION_2 = "com.example.samplewidget.SampleWidgetService.ACTION_2";
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// 画面回転時等
Context context = getBaseContext();
Intent buttonIntent1 = new Intent(context, SampleWidgetService.class);
Intent buttonIntent2 = new Intent(context, SampleWidgetService.class);
PendingIntent pendingIntent1 = PendingIntent.getService(context, 0, buttonIntent1, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntent2 = PendingIntent.getService(context, 0, buttonIntent2, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
remoteViews.setOnClickPendingIntent(R.id.btn1, pendingIntent1);
remoteViews.setOnClickPendingIntent(R.id.btn2, pendingIntent2);
// AppWidgetの画面更新
ComponentName thisWidget = new ComponentName(context, SampleWidgetProvider.class);
AppWidgetManager manager = AppWidgetManager.getInstance(SampleWidgetService.this);
manager.updateAppWidget(thisWidget, remoteViews);
}
@Override
public void onStart(Intent intent, int startId) {
Context context = getBaseContext();
Intent buttonIntent1 = new Intent(context, this);
Intent buttonIntent2 = new Intent(context, this);
buttonIntent1.setAction(ACTION_1);
buttonIntent2.setAction(ACTION_2);
PendingIntent pendingIntent1 = PendingIntent.getService(this, 0, buttonIntent1, 0);
PendingIntent pendingIntent2 = PendingIntent.getService(this, 0, buttonIntent2, 0);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.widget);
remoteViews.setOnClickPendingIntent(R.id.btn1, pendingIntent1);
remoteViews.setOnClickPendingIntent(R.id.btn2, pendingIntent2);
if (ACTION_1.equals(intent.getAction())) {
setVal("1", remoteViews);
}
if (ACTION_2.equals(intent.getAction())) {
setVal("2", remoteViews);
}
// AppWidgetの画面更新
thisWidget = new ComponentName(this, SampleWidgetProvider.class);
manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, remoteViews);
}
}
分かってしまえば(というかソースをちゃんと理解すれば)簡単なことなのですが。
ネットにソースを公開してる人って、ちゃんと理解してないんでしょうね。
ソースのコメントやエントリー内容に惑わされました。
※もちろん俺もとりあえず書いて期待通りの動作をすればOKで、細部まで深く理解しようとなんて思っていません。時間の無駄。
株式会社woodsmallの小林でした。
https://woodsmall.co.jp
コメント