web-dev-qa-db-ja.com

androidのクリック可能なウィジェット

開発者向けドキュメントは、ここで私を失敗させたようです。私は考えずに静的ウィジェットを作成できます。自分自身を更新するアナログ時計ウィジェットのようなウィジェットを作成することもできますが、私は一生、ユーザーがクリックしたときに反応するウィジェットを作成する方法を理解することはできませんそれ。開発者のドキュメントがウィジェットアクティビティに含めるべき内容を提供する最適なコードサンプルを次に示します(他のヒントは、静的ウィジェットのみを作成するAPIデモです)。

public class ExampleAppWidgetProvider extends AppWidgetProvider {
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        final int N = appWidgetIds.length;

        // Perform this loop procedure for each App Widget that belongs to this provider
        for (int i=0; i<N; i++) {
            int appWidgetId = appWidgetIds[i];

            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

            // Get the layout for the App Widget and attach an on-click listener to the button
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current App Widget
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

from: Android開発者ドキュメントのウィジェットページ

そのため、ウィジェットがクリックされると保留中のインテントが呼び出されるように見えますが、これはインテントに基づいており(インテントと保留中のインテントの違いがよく分からない)、インテントはExampleActivityクラス用です。そこで、サンプルアクティビティクラスを、作成時にmediaplayerオブジェクトを作成して開始する単純なアクティビティにしました(オブジェクトをリリースすることはないため、最終的にクラッシュします。コードは次のとおりです。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.sound);
    mp.start();
}

ただし、ウィジェットをホーム画面に追加してクリックすると、何も再生されませんでした。実際、更新タイマーを数百ミリ秒に設定しても何も再生されませんでした(appwidgetプロバイダーのxmlファイルで)。さらに、ブレークポイントを設定すると、アクティビティに到達しないだけでなく、設定したブレークポイントがトリガーされないことがわかりました。 (それがなぜなのかまだわかりません)、しかし、logcatはアクティビティクラスファイルが実行されていることを示しているようです。

それで、クリックに応答するためにアプリウィジェットを取得するためにできることはありますか? onClickPendingIntent()メソッドは、onClickタイプのメソッドに最も近いものです。

どうもありがとうございました。

61
Leif Andersen

最初に、定数を持つ静的変数を追加します。

public static String YOUR_AWESOME_ACTION = "YourAwesomeAction";

次に、インテントを保留中のインテントに追加する前に、アクションをインテントに追加する必要があります。

Intent intent = new Intent(context, widget.class);
intent.setAction(YOUR_AWESOME_ACTION);

(widget.classは、現在のクラスであるAppWidgetProviderのクラスです)

次に、getBroadcastでPendingIntentを作成する必要があります

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

ウィジェットでクリック可能なビューのonClickPendingIntentを設定します

remoteView.setOnClickPendingIntent(R.id.widgetFrameLayout, pendingIntent);

次に、同じクラスのonReceiveメソッドをオーバーライドします。

@Override
public void onReceive(Context context, Intent intent) {
 super.onReceive(context, intent);

そして、onReceiveメソッド内でアクションに対して返されたインテントを照会することにより、ボタンの押下に応答します。

if (intent.getAction().equals(YOUR_AWESOME_ACTION)) {
   //do some really cool stuff here
}

そして、それでうまくいくはずです!

126
strange quark

onUpdateメソッドをそのままにして、ロジックをpdateAppWidgetにコピーアンドペーストします。

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                            int appWidgetId) {

    // Create an Intent to launch ExampleActivity when clicked
    Intent intent = new Intent(context, ExampleActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
    // Construct the RemoteViews object
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
    // Widgets allow click handlers to only launch pending intents
    views.setOnClickPendingIntent(R.id.button, pendingIntent);
    // Instruct the widget manager to update the widget
    appWidgetManager.updateAppWidget(appWidgetId, views);
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    // There may be multiple widgets active, so update all of them
    for (int appWidgetId : appWidgetIds) {
        updateAppWidget(context, appWidgetManager, appWidgetId);
    }
}

PS。 PendingIntentはIntentの単なる「ボックス」であり、他のアプリケーションがアプリケーションでそのIntentにアクセスして実行できるようにします。

1
Mike