afnf.net

Android 5.0 LollipopでのTicker代替方法

Android Lollipop tickerText 2015/01/03 15:39

Notification Tickerとは

ステータスバーに3秒ぐらい出る、あのテキストです。

20150103_notif_Android4

Android 5.0 Lollipopではこれが表示されなくなりましたが、同じくLollipopで新設されたHeads Up Notificationで、ある程度は代替できます。

20150103_notif_Android5

うっとうしいですけど。

Ticker Textが異なる場合は割合単純です。今回は、Ticker Textが同一の場合でも強制表示させるパターンについて、その方法を探りました。

ソースコードはhttps://github.com/af-not-found/NotifTestにあります。

単発の表示

Heads Up Notificationにすると、10秒ぐらい表示されてしまって邪魔です。2.5秒後に通常のNotificationに変更することで、表示時間を擬似的に短縮できます。

public void doNotify() {
  final NotificationManager nman
     = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

  Intent notificationIntent = new Intent(this, clazz);
  PendingIntent contentIntent
     = PendingIntent.getActivity(this, 0, notificationIntent, 0);

  if (builder == null) {
    builder = new NotificationCompat.Builder(getApplicationContext());
    builder.setContentIntent(contentIntent);
    builder.setSmallIcon(android.R.drawable.ic_dialog_info);
    builder.setContentTitle(getString(R.string.app_name));
    builder.setWhen(System.currentTimeMillis());
  }

  String text = "notification from action";
  builder.setTicker(text);
  builder.setContentText(text);

  // Android5.0以上
  if (Build.VERSION.SDK_INT > 20) {
    // Heads Up Notification
    builder.setCategory(Notification.CATEGORY_SERVICE);
    builder.setPriority(Notification.PRIORITY_HIGH);
    // 実行されないように遅延されたバイブレーション
    builder.setVibrate(new long[]{60000, 100});

    // 2.5秒後に通常のNotificationに変更
    new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        builder.setPriority(Notification.PRIORITY_DEFAULT);
        builder.setVibrate(null);
        nman.notify(NOTIF_ID, builder.build());
      }
    }, 2500);
  }

  // 強制再表示させるために一旦キャンセル
  nman.cancel(NOTIF_ID);
  nman.notify(NOTIF_ID, builder.build());
}

setVibrate(new long[]{60000, 100});していますが、2.5秒後にsetVibrate(null);してますので、実際にはバイブレーションは実行されません。

フォアグラウンドサービスからの表示

Android 4.4 KitKatまでは、フォアグラウンドを一旦キャンセルしてから再度フォアグラウンド化することで、同一のTicker Textでも強制表示できました。

Android 5.0 Lollipopでも同じ方法が使えますが、割り切って別のNotification IDで表示する方法が良さそうです。単発の場合と異なり、2.5秒後にキャンセルします。

public int onStartCommand(Intent intent, int flags, int startId) {
  if (intent.getStringExtra("start") != null) {
    final NotificationManager nman
        = (NotificationManager)
        getSystemService(Context.NOTIFICATION_SERVICE);

    // Android4.4以下
    if (Build.VERSION.SDK_INT <= 20) {
      // 強制再表示させるためにフォアグラウンドをキャンセル
      stopForeground(true);
      startForeground(NOTIF_ID, createNotification(false));
    }
    // Android5.0以上
    else {
      // 初回の場合
      if (builder == null) {
        startForeground(NOTIF_ID, createNotification(false));
      }
      // 内容の更新
      else {
        nman.notify(NOTIF_ID, createNotification(false));
      }
      // Heads Up Notificationを表示
      nman.notify(NOTIF_ID_HEADSUP, createNotification(true));
      // 2.5秒後にキャンセル
      new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
          nman.cancel(NOTIF_ID_HEADSUP);
        }
      }, 2500);
    }
  }
  return super.onStartCommand(intent, flags, startId);
}

private Notification createNotification(boolean headsUp) {

  NotificationCompat.Builder b = null;

  if (builder != null) {
    b = builder;
  }
  else {
    Intent notificationIntent = new Intent(this, clazz);
    PendingIntent contentIntent
        = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    b = new NotificationCompat.Builder(getApplicationContext());
    b.setContentIntent(contentIntent);
    b.setSmallIcon(android.R.drawable.ic_dialog_info);
    b.setContentTitle(getString(R.string.app_name));
    b.setWhen(System.currentTimeMillis());
    builder = b;
  }

  if (headsUp) {
    // Heads Up Notification
    b.setCategory(Notification.CATEGORY_SERVICE);
    b.setPriority(Notification.PRIORITY_HIGH);
    // 実行されないように遅延されたバイブレーション
    b.setVibrate(new long[]{60000, 100});
  }
  else {
    b.setCategory(null);
    b.setPriority(Notification.PRIORITY_DEFAULT);
    b.setVibrate(null);
  }

  String text = "notification from service";
  b.setTicker(text);
  b.setContentText(text);
  b.setTicker(text);
  b.setContentText(text);

  return b.build();
}

2015/01/10追記

new Handler().postDelayed(new Runnable(){...})ですが、UIスレッド以外から実行する場合は、Looper.getMainLooper()を使う必要があります。

これでミスってtwawm2に不具合出してもーた。
https://github.com/af-not-found/twawm2/commit/3fe71d6fcfccebd1831ae3487dd86b13427b0f05

Android Lollipop tickerText 2015/01/03 15:39
comments (0)

blog-java2 engine (build:2019-02-23 17:57 JST)