如何启动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了一个解决方法:
- 使用
startForeground()
与通知和一切开始一个虚假的服务。 - 用
startForeground()
(相同的通知ID)启动你想运行的真实服务, - 停止第一个(假的)服务(可以调用
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(含)
我相信唯一的办法是禁用所有的应用程序的通知。
-
使用意图将用户发送到您的应用程序的详细信息屏幕:
Uri uri = Uri.fromParts("package", getPackageName(), null); Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri); startActivity(intent);
-
然后让用户从那里阻止应用程序的通知。
请注意,这也会阻止你的应用程序吐司。
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>
这基本上将您的应用设置为更高的内存优先级,从而降低被杀死的可能性。