Как начать передний план () без отображения уведомления?
Я хочу создать сервис и заставить его работать на переднем плане.
большинство примеров кодов имеют уведомления об этом. Но я не хочу показывать никаких уведомлений. Это возможно?
не могли бы вы привести несколько примеров? Есть ли альтернативы?
мой сервис приложений делает mediaplayer. как сделать так, чтобы система не убивала мой сервис, за исключением того, что приложение убивает его само (например, приостановка и остановка музыки с помощью кнопки).
13 ответов:
в качестве функции безопасности платформы Android, вы не может, под любой обстоятельство, имеют переднюю службу без предварительного уведомления. Это связано с тем, что служба переднего плана потребляет большее количество ресурсов и подвержена различным ограничениям планирования (т. е. она не убивается так быстро), чем фоновые службы, и пользователь должен знать, что, возможно, ест их батарею. Итак,не do этот.
, Это и возможно иметь "поддельное" уведомление, т. е. вы можете сделать прозрачный значок уведомления (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()(тот же идентификатор уведомления)- остановите первый (поддельный) сервис (вы можете позвонить
stopSelf()и в onDestroy вызовstopForeground(true)).вуаля! Никакие уведомления вообще и ваша вторая служба продолжает работать.
вот моя реализация техники в ответ by Лиор Илуз.
обратите внимание, что это больше не работает в Android 7.1. Также обратите внимание, что этот метод потенциально может быть истолковано как нарушение политика разработчика Google Play (
Apps that introduce or exploit security vulnerabilities.).код
ForegroundService.java
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; } }ForegroundEnablingService.java
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; } }AndroidManifest.xml
<service android:name=".ForegroundEnablingService" /> <service android:name=".ForegroundService" />совместимость
протестировано и работает над:
- официальный Эмулятор
- 4.0.2
- 4.1.2
- 4.2.2
- 4.3.1
- 4.4.2
- 5.0.2
- 5.1.1
- 6.0
- 7.0
- Sony Xperia M
- 4.1.2
- 4.3
- Samsung Galaxy ?
- 4.4.2
- 5.Икс
- Genymotion
- 5.0
- 6.0
- CyanogenMod
- 5.1.1
больше не работает с Android 7.1.
вы можете использовать это :
Notification note = new Notification( 0, null, System.currentTimeMillis() ); note.flags |= Notification.FLAG_NO_CLEAR; startForeground( 42, note );как предложил @Kristopher Micinski
-----обновление
обратите внимание, что это больше не допускается с Android KitKat+ релизы. И имейте в виду, что это более или менее нарушает принцип дизайна в Android, который делает фоновые операции видимыми для пользователей, как упоминалось @Kristopher Micinski
просто установите идентификатор вашего уведомления в ноль:
// 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.
Я установил параметр icon конструктору для уведомления в ноль, а затем передал полученное уведомление в startForeground(). Никаких ошибок в журнале и никаких уведомлений не появляется. Я не знаю, однако, была ли служба успешно выдвинута на передний план-есть ли способ проверить?
отредактировано: проверено с помощью dumpsys, и действительно служба находится на переднем плане в моей системе 2.3. Еще не проверял с другими версиями ОС.
есть один обходной путь. Попробуйте создать уведомление без значка настройки, и уведомление не будет отображаться. Не знаю, как это работает, но это так:)
Notification notification = new NotificationCompat.Builder(this) .setContentTitle("Title") .setTicker("Title") .setContentText("App running") //.setSmallIcon(R.drawable.picture) .build(); startForeground(101, notification);
Я нашел на 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.класс:
@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 работают в фоновом режиме' уведомление.
версия 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);
блокировать уведомление службы переднего плана
начиная с Android 7.1, кажется, нет никаких трюков/ошибок, которые вы можете использовать для этого. Поэтому вместо этого вам нужно указать пользователю отключить уведомление о службе переднего плана в настройках Android.
как
Android 4.1 - 7.1 (включительно)
Я считаю, что единственный способ-отключить все уведомлений приложения.
использовать намерение отправить пользователя на экран сведений вашего приложения:
Uri uri = Uri.fromParts("package", getPackageName(), null); Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri); startActivity(intent);затем пользователь блокирует уведомления приложения оттуда.
обратите внимание, что это также блокирует тосты вашего приложения.
Android 8:
к сожалению, если пользователь блокирует уведомление службы, то Android заменит его на "{имя приложения} работает в фоновом режиме" уведомления. Так что нет особого смысла прятаться оно.
вот способ сделать ваше приложение oom_adj до 1 (протестировано в эмуляторе Android 6.0 SDK). Добавьте временную службу, в ваш основной вызов службы
startForgroundService(NOTIFICATION_ID, notificion). А затем запустите вызов временной службыstartForgroundService(NOTIFICATION_ID, notificion)с тем же идентификатором уведомления снова, через некоторое время во временной службе вызовите stopForgroundService(true), чтобы отклонить onging ontification.
Я разработал простой медиа плеер пару месяцев назад. Так что я считаю, если вы делаете что-то вроде:
Intent i = new Intent(this, someServiceclass.class);startService (i);
тогда система не должна быть в состоянии убить ваш сервис.
ссылка:прочитайте абзац, который обсуждает, когда система останавливает службу
вы также можете объявить свое приложение постоянным.
<application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/Theme" *android:persistent="true"* > </application>это по существу устанавливает ваше приложение с более высоким приоритетом памяти, уменьшая вероятность его уничтожения.
Comments