web-dev-qa-db-ja.com

サービス内からのスナックバーの表示

SnackBarの内部からActivityを表示する場合、rootViewを使用できます。しかし、SnackBarが利用できない場合はServiceの内部からViewを表示する必要があります。どうすればこれを達成できますか?

裏話として:アクティビティは、タスクを実行するためのサービスを開始します。 Serviceは、状況に応じてSnackBarを表示する必要があります。そのためだけにServiceにバインドしたくありません。では、どうすればこれを達成できますか?通常はToastを表示できますが、ユーザーがメッセージを読んで確認できるようにする必要があります。

10
Nouvel Travay

Snackbar を表示するには、 View が必要です。したがって、状態に応じてアプリにスナックバーを表示する場合は、 Service を表示します。 Activity にバインドするか、 LocalBroadcastManager を介してメッセージをブロードキャストし、Viewにメッセージを表示する必要があります。

それを回避する方法は他にないと思います。何らかの方法でActivityまたはFragmentと通信する必要があります。

スナックバーはコンテキストのみを必要とするトーストとは異なりますので、アプリから表示したい場合は、クラスではできないと思いますAndroidによって提供されます。

設計ガイドライン から:

配置

スナックバーは画面上のほとんどの要素の上に表示され、高さはフローティングアクションボタンと同じです。ただし、ダイアログ、ボトムシート、ナビゲーションドロワーよりも標高が低くなります。

明示的ではありませんが、アプリビュー内にのみ表示されるという結論に達することができます。したがって、繰り返しになりますが、visibleビューと何らかの方法で通信する必要があります。


メッセージのブロードキャストに関するスニペット:

送信者(サービス上)

private void doSendBroadcast(String message) {
    Intent it = new Intent("EVENT_SNACKBAR");

    if (!TextUtils.isEmpty(message))
        it.putExtra(EXTRA_RETURN_MESSAGE,message);

    LocalBroadcastManager.getInstance(mContext).sendBroadcast(it);
}

受信者(アクティビティ上)

private BroadcastReceiver mMessageReceiver = null;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Other stuff.

    mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Do something
        }
    };
}

@Override
public void onResume() {
    super.onResume();

    LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("EVENT_SNACKBAR"));
}

バインドされたサービスの詳細 ここ

そしてLocalBroadcastManagerについて この質問について

更新:EventBus を使用してvisibleパブリッシャー/サブスクライバーの方法で機能するビュー。 スティッキーイベント の概念を利用して、アプリが再び表示されたらSnackbarが表示されるようにすることもできます。

イベントバスの使い方については、私の この回答 をご覧ください。

15
Mauker

LocalBroadcastManager内の Service を介していつでもブロードキャストを送信できます

_LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("SERVICE_DID_SOMETHING"));
_

次に、ActivityBroadcastReceiver を使用してSnackbarを表示します

_private final ServiceReceiver _serviceReceiver = new ServiceReceiver();

@Override
protected void onResume() {
    super.onResume();

    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("SERVICE_DID_SOMETHING");

    LocalBroadcastManager.getInstance(this).registerReceiver(_serviceReceiver, intentFilter);
}

@Override
protected void onPause() {
    super.onPause();

    try {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(_serviceReceiver);
    } catch (Exception ex) {
        Log.e(TAG, "Error unregistering ServiceReceiver", ex);
    }
}

// region ServiceReceiver
private class ServiceReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: Show your Snackbar here...
    }
}
// endregion
_

送信したIntentを使用して、必要に応じて追加のデータを渡し、それをBroadcastReceiver.onReceive(Context context, Intent intent)で引き出すことができます。

5
Cory Charlton

SDKが提供するデフォルトのSnackBarを使用してこれを行うことはできません。これは、常にビューが必要になるためです。

目的を果たすために、 これ のようなSnackBarを模倣する外部ライブラリを使用できます。

複数のアクティビティにまたがって表示されるアプリケーションコンテキストでスナックバーを作成する方法: https://stackoverflow.com/a/37707741/1185087

0
user1185087