サービスを作成し、フォアグラウンドで実行するようにします。
ほとんどのサンプルコードには通知があります。しかし、通知を表示したくありません。それは可能ですか?
例を挙げてもらえますか?代替手段はありますか?
私のアプリサービスはmediaplayerを実行しています。 アプリがそれ自体を殺す以外にシステムが私のサービスを殺さないようにする方法(ボタンで音楽を一時停止または停止するように)。
Androidプラットフォームのセキュリティ機能として、cannot、anyの状況では、通知もせずにフォアグラウンドサービスがあります。これは、フォアグラウンドサービスはバックグラウンドサービスと比べてより多くのリソースを消費し、異なるスケジューリングの制約を受ける(つまり、すぐに殺されない)ため、ユーザーはバッテリーを消費している可能性があるものを知る必要があるためです。 しないこれを行います。
ただし、それはis「偽の」通知を持つことが可能です。つまり、透明な通知アイコン(iirc)を作成できます。これはユーザーにとって非常に不誠実なものであり、バッテリーを破壊してマルウェアを作成する以外に、それを行う理由はありません。
更新:これはAndroid 7.1。 https://code.google。 com/p/Android/issues/detail?id = 213309
4.3アップデート以降、通知を表示せずにstartForeground()
でサービスを開始することは基本的に不可能です。
ただし、公式のAPIを使用してアイコンを非表示にすることができます。透明なアイコンは必要ありません(古いバージョンをサポートするにはNotificationCompat
を使用します)
_NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setPriority(Notification.PRIORITY_MIN);
_
私は通知自体がまだ必要であるという事実に和解しましたが、まだそれを隠したい人のために、私はそれに対する回避策も見つけたかもしれません:
startForeground()
で偽のサービスを開始します。startForeground()
(同じ通知ID)を使用して、実行する実際のサービスを開始しますstopSelf()
を呼び出し、onDestroyでstopForeground(true)
を呼び出します)。ほら!通知はまったくなく、2番目のサービスは引き続き実行されます。
これはAndroid 7.1以降では機能せず、違反する可能性があります Google Playの開発者ポリシー 。
代わりに、 ユーザーにサービス通知をブロックさせる をお勧めします。
答え by Lior Iluz での私のテクニックの実装です。
public class ForegroundService extends Service {
static ForegroundService instance;
@Override
public void onCreate() {
super.onCreate();
instance = this;
if (startService(new Intent(this, ForegroundEnablingService.class)) == null)
throw new RuntimeException("Couldn't find " + ForegroundEnablingService.class.getSimpleName());
}
@Override
public void onDestroy() {
super.onDestroy();
instance = null;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class ForegroundEnablingService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (ForegroundService.instance == null)
throw new RuntimeException(ForegroundService.class.getSimpleName() + " not running");
//Set both services to foreground using the same notification id, resulting in just one notification
startForeground(ForegroundService.instance);
startForeground(this);
//Cancel this service's notification, resulting in zero notifications
stopForeground(true);
//Stop this service so we don't waste RAM.
//Must only be called *after* doing the work or the notification won't be hidden.
stopSelf();
return START_NOT_STICKY;
}
private static final int NOTIFICATION_ID = 10;
private static void startForeground(Service service) {
Notification notification = new Notification.Builder(service).getNotification();
service.startForeground(NOTIFICATION_ID, notification);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
<service Android:name=".ForegroundEnablingService" />
<service Android:name=".ForegroundService" />
テスト済みおよび作業中:
Android 7.1。以降は動作していません
これを使用できます(@Kristopher Micinskiが示唆するとおり):
Notification note = new Notification( 0, null, System.currentTimeMillis() );
note.flags |= Notification.FLAG_NO_CLEAR;
startForeground( 42, note );
更新:
これは、Android KitKat +リリースではもう許可されません。これは、バックグラウンドを作成するAndroid @Kristopher Micinskiが言及したユーザーに見える操作
通知のIDをゼロに設定するだけです:
// field for notification ID
private static final int NOTIF_ID = 0;
...
startForeground(NOTIF_ID, mBuilder.build());
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.cancel(NOTIF_ID);
...
得ることができる利点は、Service
が、メモリの負荷が高い場合を除き、Androidシステムによって破壊されることなく、高優先度で実行できることです。
[〜#〜] edit [〜#〜]
Pre-HoneycombおよびAndroid 4.4以降で動作するようにするには、NotificationCompat.Builder
ではなく、サポートライブラリv7が提供するNotification.Builder
を使用してください。
1つの回避策があります。アイコンを設定せずに通知を作成してみてください。通知は表示されません。それがどのように機能するのか分からないが、それは:)
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Title")
.setTicker("Title")
.setContentText("App running")
//.setSmallIcon(R.drawable.picture)
.build();
startForeground(101, notification);
Notificationのコンストラクターにiconパラメーターをゼロに設定し、結果の通知をstartForeground()に渡しました。ログにエラーも通知も表示されません。ただし、サービスが正常にフォアグラウンド化されたかどうかはわかりません。チェックする方法はありますか?
編集:dumpsysでチェックしました。実際、2.3システムではサービスがフォアグラウンドになっています。他のOSバージョンではまだ確認していません。
Android 9で通知を非表示にするには、layout_height = "0dp"のカスタムレイアウトを使用します
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationUtils.CHANNEL_ID);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.custom_notif);
builder.setContent(remoteViews);
builder.setPriority(NotificationCompat.PRIORITY_LOW);
builder.setVisibility(Notification.VISIBILITY_SECRET);
custom_notif.xml
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="0dp">
</LinearLayout>
Pixel 1でテスト済みAndroid 9.このソリューションは、Android 8以下では動作しません
Android 8.0で、通知チャネルを使用しないことで引き続き可能です。
public class BootCompletedIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if ("Android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent notificationIntent = new Intent(context, BluetoothService.class);
context.startForegroundService(notificationIntent);
} else {
//...
}
}
}
}
そしてBluetoothService.classで:
@Override
public void onCreate(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent notificationIntent = new Intent(this, BluetoothService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new Notification.Builder(this)
.setContentTitle("Title")
.setContentText("App is running")
.setSmallIcon(R.drawable.notif)
.setContentIntent(pendingIntent)
.setTicker("Title")
.setPriority(Notification.PRIORITY_DEFAULT)
.build();
startForeground(15, notification);
}
}
永続的な通知は表示されませんが、Android 'xアプリがバックグラウンドで実行されています'という通知が表示されます。
Android 7.1以降を悪用して通知を隠すことはできません。代わりに、ユーザーにブロックさせます。
唯一の方法は、アプリからのall通知をブロックすることです:
ユーザーをアプリの詳細画面に送ります:
Uri uri = Uri.fromParts("package", getPackageName(), null);
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri);
startActivity(intent);
ユーザーにアプリの通知をブロックさせる
これはアプリのトーストもブロックすることに注意してください。
Android Oの通知をブロックする価値はありません。OSは単に「バックグラウンドで実行中」または「バッテリー」通知。
通知チャネル を使用して、サービス通知のみをブロックします。
ユーザーを通知チャネルの設定に送信します
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName())
.putExtra(Settings.EXTRA_CHANNEL_ID, myNotificationChannel.getId());
startActivity(intent);
ユーザーにチャンネルの通知をブロックさせる
バージョン4.3(18)以上ではサービス通知を非表示にすることはできませんが、アイコンを無効にすることはできますが、バージョン4.3(18)以下では通知を非表示にすることができます
Notification noti = new Notification();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
noti.priority = Notification.PRIORITY_MIN;
}
startForeground(R.string.app_name, noti);