※画像は弊社『電卓』のウィジェットです。
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
コメント