我想创建一个服务并使它在前台运行。
大多数示例代码都带有通知,但我不想显示任何通知。这可能吗?
你能给我一些例子吗?还有其他替代方案吗?
我的应用服务正在执行播放器功能。如何让系统不杀死我的服务,除非应用程序自己终止它(例如通过按钮暂停或停止音乐)?
我想创建一个服务并使它在前台运行。
大多数示例代码都带有通知,但我不想显示任何通知。这可能吗?
你能给我一些例子吗?还有其他替代方案吗?
我的应用服务正在执行播放器功能。如何让系统不杀死我的服务,除非应用程序自己终止它(例如通过按钮暂停或停止音乐)?
startForeground()
启动服务而不显示通知基本上是不可能的。NotificationCompat
来支持旧版本)NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setPriority(Notification.PRIORITY_MIN);
我已经接受了通知本身仍然需要存在的事实,但是对于任何仍然想要隐藏它的人,我可能已经找到了一个解决办法:
更新:这个问题在Android 7.1上已经“修复”了。 https://code.google.com/p/android/issues/detail?id=213309
startForeground()
启动一个带有通知和其他内容的虚假服务。startForeground()
启动你想要运行的真实服务(使用相同的通知ID)。stopSelf()
,并在onDestroy中调用stopForeground(true)
)。大功告成!没有任何通知,你的第二个服务仍然在运行。
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开始不再支持。
ForegroundService
前台服务 - Sam警告: 尽管这个答案看起来有效,但实际上它会在不知不觉中阻止您的服务成为前台服务。
原始答案:
只需将通知的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);
...
startForeground(1, notification)
“notificationManager.createNotificationChannel(“channel_id”)”
。
或者 使用 notificationManager.removeNotificationChannel(channel)
。Notification.Builder
、Support Library v4 NotificationCompat.Builder
和 Support Library v7 NotificationCompat.Builder
。通知没有出现在通知抽屉或状态栏中,但当我使用 getRunningServices()
和 dumpsys
进行检查时,服务并未以前台模式运行。 - SamNotification note = new Notification( 0, null, System.currentTimeMillis() );
note.flags |= Notification.FLAG_NO_CLEAR;
startForeground( 42, note );
更新:
请注意,这在Android KitKat+版本中不再允许。并且请记住,这更或多或少违反了Android的设计原则,即将后台操作对用户可见,如@Kristopher Micinski所述。
您可以使用布局高度为"0dp"的自定义布局,在Android 9+上隐藏通知。
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或更早版本上无效。
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Title")
.setTicker("Title")
.setContentText("App running")
//.setSmallIcon(R.drawable.picture)
.build();
startForeground(101, notification);
这里的大部分答案要么无效,会破坏前台服务,或者违反了Google Play政策。
唯一可靠且安全地隐藏通知的方法是让用户屏蔽它。
唯一的方法是屏蔽您应用程序的所有通知:
Send user to app's details screen:
Uri uri = Uri.fromParts("package", getPackageName(), null);
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri);
startActivity(intent);
Have user block app's notifications
Send user to notification channel's settings
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName())
.putExtra(Settings.EXTRA_CHANNEL_ID, myNotificationChannel.getId());
startActivity(intent);
Have user block channel's notifications
Notification()
构造函数。 - johsin18版本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);