我想创建一个服务,并使它在前台运行。
大多数例子代码有它的通知。 但我不希望出现任何通知。 那可能吗?
你能给我一些例子吗? 是否有其它方法吗?
我的应用程序服务是做媒体播放器。 如何使系统不杀我的服务,除了应用程序杀死它本身 (如暂停或按钮停止音乐)。
我想创建一个服务,并使它在前台运行。
大多数例子代码有它的通知。 但我不希望出现任何通知。 那可能吗?
你能给我一些例子吗? 是否有其它方法吗?
我的应用程序服务是做媒体播放器。 如何使系统不杀我的服务,除了应用程序杀死它本身 (如暂停或按钮停止音乐)。
由于Android平台的安全功能,你不能 ,在任何情况下,有前景化服务而不让一个通知。 这是因为前景化的服务消耗资源的重量,并受不同的调度限制(即,它不会因为迅速杀死),比后台服务,用户需要知道什么是可能吃他们的电池。 所以, 不这样做。
但是,它可能有一个“假”的通知,也就是说,你可以做一个透明的通知图标(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)
)。 瞧! 根本没有通知和您的第二个服务继续运行。
这不再是安卓7.1+工作。 这种技术可能会违反谷歌Play的开发者政策 ( Apps that introduce or exploit security vulnerabilities.
)。
相反,我建议让用户阻止该服务的通知 。
下面是我的实现在技术,答案由利奥尔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奇巧+发布了允许的。 并牢记,这或多或少是违反在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系统的破坏,除非对高内存压力。
编辑
为了使其与前蜂窝和Android 4.4及更高版本工作,请确保您使用NotificationCompat.Builder
代替它通过支持库V7提供, Notification.Builder
。
的图标I参数给构造为通知设定为零,然后传递所产生的通知到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);
版本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 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应用程序在后台运行”。
安卓7.1+不能被利用来隐藏通知。 取而代之的是,让用户来阻止它。
唯一的办法就是阻止你的应用程序的所有通知:
发送用户的应用程序的详细信息屏幕:
Uri uri = Uri.fromParts("package", getPackageName(), null); Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri); startActivity(intent);
有用户模块应用的通知
请注意,这也会阻止你的应用程序的祝酒词。
这不值得堵在Android澳通知,因为该操作系统将只是一个“ 在后台运行 ”或“ 使用电池 ”通知更换。
使用通知信道阻塞只是服务通知。
发送用户通知通道的设置
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) .putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName()) .putExtra(Settings.EXTRA_CHANNEL_ID, myNotificationChannel.getId()); startActivity(intent);
有用户块信道的通知
您可以通过使用自定义布局与layout_height =“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>
上像素的1测试,机器人9.本解决方案并不在Android 8或更小的工作
这里有一个方法,使您的应用程序的oom_adj 1(经测试,在ANDROID 6.0 SDK模拟器)。 添加一个临时服务,在你的主要服务调用startForgroundService(NOTIFICATION_ID, notificion)
然后启动临时服务呼叫startForgroundService(NOTIFICATION_ID, notificion)
再次用相同的通知ID,在临时服务调用stopForgroundService(真)驳回onging 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>
这实质上是将您的应用程序在一个更高的内存优先级,降低它被杀死的概率。