如何启动Foreground()而不显示通知?

我想创build一个服务,并在前台运行。

大多数示例代码都有通知。 但我不想显示任何通知。 那可能吗?

你能举几个例子吗? 有没有其他的select?

我的应用服务正在做mediaplayer。 如何让系统不杀我的服务,除了应用程序自己杀死它 (如通过button暂停或停止音乐)。

作为Android平台的一项安全function,在任何情况下,您都不可能在没有通知的情况下获得预先安排的服务。 这是因为一个非常规的服务会消耗更多的资源,并受到与后台服务不同的调度约束(即不会被快速杀死),用户需要知道可能正在吃电池的东西。 所以, 要这样做。

但是,可能会发出“假”通知,即可以制作透明的通知图标(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); 

我已经和平了,通知本身仍然需要在那里,但是对于那些还想隐藏的人来说,我可能find了一个解决方法:

  1. 使用startForeground()与通知和一切开始一个虚假的服务。
  2. startForeground() (相同的通知ID)启动你想运行的真实服务,
  3. 停止第一个(假的)服务(可以调用stopSelf()并在onDestroy中调用stopForeground(true) )。

瞧! 根本没有通知,你的第二个服务继续运行。

这是我在Lior Iluz 的回答中实现的技术。

请注意,这不再适用于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" /> 

兼容性

经过testing和工作:

  • 官方模拟器
    • 4.0.2
    • 4.1.2
    • 4.2.2
    • 4.3.1
    • 4.4.2
    • 5.0.2
    • 5.1.1
    • 6
    • 7
  • 索尼Xperia M
    • 4.1.2
    • 4.3
  • 三星Galaxy ?
    • 4.4.2
    • 5.X
  • Genymotion
    • 5
    • 6
  • 的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所build议的那样

—– UPDATE

请注意,Android KitKat +版本不允许这样做。 请记住,这或多或less违反了Android的devise原则,使用户可以看到后台操作,如@ 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系统破坏,除非在高内存压力。

编辑

要使用Pre-Honeycomb和Android 4.4以及更高版本,请确保使用由Support Library v7提供的Notification.Builder ,而不是Notification.Builder

我将图标参数设置为Notification的构造函数为零,然后将生成的通知传递给startForeground()。 日志中没有错误,没有通知显示。 不过,我不知道这项服务是否成功了,有什么方法可以检查吗?

编辑:检查与dumpsys,并且事实上服务是根据我的2.3系统。 尚未与其他操作系统版本进行检查。

有一个解决方法。 尝试创build没有设置图标的通知,并且通知不会显示。 不知道它是如何工作的,但它:)

  Notification notification = new NotificationCompat.Builder(this) .setContentTitle("Title") .setTicker("Title") .setContentText("App running") //.setSmallIcon(R.drawable.picture) .build(); startForeground(101, notification); 

版本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(含)

我相信唯一的办法是禁用所有的应用程序的通知。

  1. 使用意图将用户发送到您的应用程序的详细信息屏幕:

     Uri uri = Uri.fromParts("package", getPackageName(), null); Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri); startActivity(intent); 
  2. 然后让用户从那里阻止应用程序的通知。

请注意,这也会阻止你的应用程序吐司。

Android 8:

不幸的是,如果用户阻止了服务通知,那么Android会用“ 后台运行的{App名称} ”通知来replace它。 所以隐藏它没有太大的意义。

这是一个让你的应用程序的oom_adj为1的方法(在ANDROID 6.0 SDK模拟器中testing)。 添加一个临时服务,在你的主服务中调用startForgroundService(NOTIFICATION_ID, notificion) 。 然后再次使用相同的通知ID启动临时服务调用startForgroundService(NOTIFICATION_ID, notificion) ,在临时服务调用stopForgroundService(true)之后,closuresonging ontification。

几个月前我开发了一个简单的媒体播放器。 所以我相信如果你正在做类似的事情:

 Intent i = new Intent(this, someServiceclass.class); 

startService(ⅰ);

那么系统不应该能够杀死你的服务。

参考 : 阅读系统停止服务时讨论的段落

你也可以声明你的应用程序是持久的。

 <application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/Theme" *android:persistent="true"* > </application> 

这基本上将您的应用设置为更高的内存优先级,从而降低被杀死的可能性。