做特色菜的网站徐州市住房和城乡建设局网站
web/
2025/10/3 14:03:57/
文章来源:
做特色菜的网站,徐州市住房和城乡建设局网站,网站开发 百度网盘,免费做效果图的网站概述
前台服务是用户主动意识到的一种服务#xff0c;因此在内存不足时#xff0c;系统也不会考虑将其终止。前台服务必须为状态栏提供通知#xff0c;将其放在运行中的标题下方。这意味着除非将服务停止或从前台移除#xff0c;否则不能清除该通知。
在 Android 8.0因此在内存不足时系统也不会考虑将其终止。前台服务必须为状态栏提供通知将其放在运行中的标题下方。这意味着除非将服务停止或从前台移除否则不能清除该通知。
在 Android 8.0API 级别 26及更高版本中系统对后台服务进行了限制如果想要一直保持服务的运行就需要将服务设置为前台服务。前台服务与普通服务的区别在于它会有个通知在状态栏显示。当然有时可能也不仅仅是为了防止服务被回收才使用前台服务有些项目的需要要求必须使用前台服务。如音乐播放、小说听书、天气等软件这些都需要设置为前台服务跟随进程的销毁而销毁。有些不仅仅是依赖应用进程也可设置为系统白名单保持一直运行的状态。
需要注意的是应尽量限制应用使用前台服务。只有当应用执行的任务需供用户查看即使该任务未直接与应用交互时您才应使用前台服务。因此前台服务必须显示优先级为 PRIORITY_LOW 或更高的状态栏通知这有助于确保用户知道应用正在执行的任务。如果某操作不是特别重要您希望使用最低优先级通知则可能不适合使用服务此时您可以考虑使用WorkManager、JobScheduler。
每个运行服务的应用都会给系统带来额外负担从而消耗系统资源。如果应用尝试使用低优先级通知隐藏其服务则可能会降低用户正在主动交互的应用的性能。因此如果某个应用尝试运行拥有最低优先级通知的服务则系统会在抽屉式通知栏的底部调用出该应用的行为。
例如应将服务播放音乐的音乐播放器设置为在前台运行因为用户会明确意识到其操作。状态栏中的通知可能表示正在播放的歌曲并且其允许用户通过启动 Activity 与音乐播放器进行交互。同样如果应用允许用户追踪其运行则需通过前台服务来追踪用户的位置。 注意如果应用面向 Android 9API 级别 28或更高版本并使用前台服务则其必须请求 FOREGROUND_SERVICE 权限。这是一种普通权限因此系统会自动为请求权限的应用授予此权限。如果面向 API 级别 28 或更高版本的应用试图创建前台服务但未请求 FOREGROUND_SERVICE则系统会抛出 SecurityException。 有关前台服务的通知如果您的应用正在运行“前台服务”一种长时间在后台运行且用户可以察觉到的 Service如媒体播放器则需要发出通知。不能像关闭其他通知那样关闭这种通知。要移除此类通知必须停止运行服务或者将其从“前台”状态中移除。如要从前台移除服务请调用 stopForeground()。此方法接受布尔值参数指示是否需同时移除状态栏通知。
应用场景
前台服务执行用户可以注意到的操作。前台服务显示一个状态栏通知让用户知道你的应用程序正在前台执行任务正在消耗系统资源。
应用程序使用前台服务的例子包括:
一个在前台服务中播放音乐的音乐播放器应用程序。通知可能会显示当前正在播放的歌曲。一种健身应用程序在获得用户的许可后在前台服务中记录用户的跑步情况。该通知可能会显示用户在当前健身会话中走过的距离。
只有当你的应用需要执行用户可以注意到的任务时才使用前台服务即使他们没有直接与应用程序交互。如果操作的重要性足够低你想使用最低优先级通知那么创建一个后台任务。
本文介绍了使用前台服务所需的权限以及如何启动前台服务并将其从后台移除。它还描述了如何将某些用例与前台服务类型相关联以及当您从正在后台运行的应用程序启动前台服务时生效的访问限制。
前台服务的特点
默认情况下用户可取消前台服务
从Android 13 (API级别33)开始默认情况下用户可以取消与前台服务相关的通知。此时只需要用户在通知上执行滑动手势即可。通常情况下除非前台服务停止或从前台删除否则通知不会被取消。
如果您希望通知不被用户划掉则在使用notification.builder创建通知时将true传递给setOngoing() 方法。
立即显示通知的服务
如果前台服务有以下特征之一系统在服务启动后立即显示相关的通知即使在运行Android 12或更高版本的设备上
该服务与包含操作按钮的通知相关联。该服务的前台服务类型为mediaPlayback、mediaProjection或phoneCall。该服务提供了与电话呼叫、导航或媒体播放相关的用例这些用例在通知的category属性中定义。在设置通知时服务通过将FOREGROUND_SERVICE_IMMEDIATE传递给setForegroundServiceBehavior()来选择退出行为。
manifest ...uses-permission android:nameandroid.permission.FOREGROUND_SERVICE /uses-permission android:nameandroid.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK /application ...serviceandroid:name.MyMediaPlaybackServiceandroid:foregroundServiceTypemediaPlaybackandroid:exportedfalse/service/application
/manifest在Android 13 (API级别33)或更高版本上如果用户拒绝通知权限他们仍然会在任务管理器中看到与前台服务相关的通知但在通知抽屉中看不到它们。
申请前台服务权限
针对Android 9 (API级别28)或更高版本并使用前台服务的应用程序需要请求FOREGROUND_SERVICE权限如下面的代码片段所示。这是一个正常的权限所以系统会自动将其授予请求应用程序。
manifest xmlns:androidhttp://schemas.android.com/apk/res/android ...uses-permission android:nameandroid.permission.FOREGROUND_SERVICE/application ....../application
/manifest 注意:如果目标API级别为28或更高的应用程序试图创建前台服务而没有请求FOREGROUND_SERVICE权限系统将抛出一个SecurityException。 启动一个前台服务
紧接上文的案例这里首先添加前台服务的权限
uses-permission android:nameandroid.permission.FOREGROUND_SERVICE/在请求系统将某个服务作为前台服务运行之前请先启动该服务本身: 在MainActivity中修改启动服务的方式如下
//启动一个普通后台服务
//startService(startIntent);//启动一个前台服务 在api大于26才可使用startForegroundService此方法if (Build.VERSION.SDK_INT Build.VERSION_CODES.O) {startForegroundService(startIntent);}else{startService(startIntent);}
在服务内部通常是在onStartCommand() 中你可以请求你的服务在前台运行。为此调用startForeground()。此方法接受两个参数:一个在状态栏中唯一标识通知的正整数和notification对象本身。接着修改服务内部的代码
首先创建一个通知在MyService的oncreate方法和onStartCommand()方法中做如下修改
public class MyService extends Service {public MyService() {}private Looper serviceLooper;private ServiceHandler serviceHandler;private NotificationManager manager;// 从当前线程接收消息的处理程序private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}Overridepublic void handleMessage(Message msg) {try {Thread.sleep(5000);Log.i(Myservice,当前进程编号 Thread.currentThread().getName() ·····正在处理任务);} catch (InterruptedException e) {Thread.currentThread().interrupt();}//服务处理完成后使用startId停止服务这样我们就不会在停止处理另一个作业的服务
// stopSelf(msg.arg1);}}Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException(Not yet implemented);}Overridepublic void onCreate() {manager (NotificationManager) getSystemService(NOTIFICATION_SERVICE);Log.i(Myservice,onCreate);//启动运行该服务的线程。因为默认情况下服务通常运行在进程的主线程中我们不希望阻塞主线程。所以创建了一个单独的线程// 我们还将其设置为后台优先级这样cpu密集型工作就不会破坏我们的UI。HandlerThread thread new HandlerThread(ServiceStartArguments,Process.THREAD_PRIORITY_BACKGROUND);thread.start();// Get the HandlerThreads Looper and use it for our HandlerserviceLooper thread.getLooper();serviceHandler new ServiceHandler(serviceLooper);}Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.i(Myservice,onStartCommand);// If the notification supports a direct reply action, use
// PendingIntent.FLAG_MUTABLE instead.Intent notificationIntent new Intent(this, MainActivity.class);PendingIntent pendingIntent PendingIntent.getActivity(this, 0, notificationIntent,PendingIntent.FLAG_IMMUTABLE);Notification notification null;if (android.os.Build.VERSION.SDK_INT android.os.Build.VERSION_CODES.O) {//只在Android O之上需要渠道NotificationChannel notificationChannel new NotificationChannel(channelid1,channelname,NotificationManager.IMPORTANCE_HIGH);//如果这里用IMPORTANCE_NOENE就需要在系统的设置里面开启渠道通知才能正常弹出manager.createNotificationChannel(notificationChannel);notification new Notification.Builder(this, channelid1).setContentTitle(getText(R.string.notification_title)).setContentText(getText(R.string.notification_message)).setSmallIcon(R.drawable.ic_launcher_background).setContentIntent(pendingIntent).setTicker(getText(R.string.ticker_text)).build();}// Notification ID cannot be 0.startForeground(1, notification);Toast.makeText(this, service starting, Toast.LENGTH_SHORT).show();//对于每个开始请求发送一个消息来开始一个作业并传递启动ID这样我们就知道当我们完成作业时我们正在停止哪个请求Message msg serviceHandler.obtainMessage();msg.arg1 startId;//在当前线程下执行服务的任务。serviceHandler.sendMessage(msg);// If we get killed, after returning from here, restartreturn START_STICKY;}Overridepublic void onDestroy() {super.onDestroy();Log.i(Myservice,onDestroy);}
}
经过上述三步我们来测试一下效果 这会在前台开启一个通知日志可见并没有进行销毁。服务列表中也可查看当前前台服务运行的时间 这样一个前台任务就创建好了。 注意:状态栏通知必须使用优先级为PRIORITY_LOW或更高。如果你的应用程序试图使用一个优先级较低的通知系统会在通知抽屉中添加一条消息提醒用户应用程序使用了前台服务。 后台启动限制
针对Android 12 (API级别31)或更高版本的应用程序不能在后台运行时启动前台服务除非有一些特殊情况。如果应用程序在后台运行时试图启动前台服务而前台服务不满足前文中的情况系统将抛出ForegroundServiceStartNotAllowedException异常。 注意:如果一个应用程序调用Context.startForegroundService()来启动另一个应用程序拥有的前台服务这里限制只适用于两个应用程序都针对Android 12或更高版本。 检查应用程序是否执行后台启动
为了更好地验证当你的应用程序试图在后台运行时启动前台服务可以在连接到测试设备或模拟器的开发机器上执行以下ADB命令每当这种行为发生时就会出现通知
adb shell device_config put activity_manager \ default_fgs_starts_restriction_notification_enabled true
免除后台启动限制
在以下情况下即使你的应用程序在后台运行应用程序也可以启动前台服务:
你的应用从一个用户可见的状态转换比如一个活动。当应用程序在一个现有任务的后台堆栈中有一个活动时服务可以从后台启动一个活动。您的应用程序使用云消息接收高优先级消息。 注意:如果应用程序没有使用高优先级消息向用户显示时间敏感的内容系统可以将高优先级消息降级为正常优先级。如果消息的优先级被降级你的应用程序不能启动前台服务并且试图启动前台服务会导致ForegroundServiceStartNotAllowedException异常。 因此在尝试启动前台服务之前建议检查RemoteMessage.getPriority() 的结果并确认它是PRIORITY_HIGH。 用户在与应用程序相关的UI元素上执行操作。例如他们可能与气泡、通知、小部件或活动交互。应用程序调用精确的Alarm来完成用户请求的操作。应用程序是设备当前的输入法。应用程序接收到一个与地理围栏或活动识别转换相关的事件。在设备重启并在广播接收器中接收到ACTION_BOOT_COMPLETED、ACTION_LOCKED_BOOT_COMPLETED或action_my_package_replace意图动作后。应用程序在广播接收器中接收ACTION_TIMEZONE_CHANGED、ACTION_TIME_CHANGED或ACTION_LOCALE_CHANGED意图动作。具有特定系统角色或权限的应用程序例如设备所有者和配置文件所有者。........
从前台删除一个服务
要从前台删除服务请调用stopForeground()。此方法接受一个布尔值该值指示是否也删除状态栏通知。如果在前台运行时停止服务则会删除其通知。 Overridepublic void onDestroy() {super.onDestroy();if (Build.VERSION.SDK_INT Build.VERSION_CODES.N) {stopForeground(Service.STOP_FOREGROUND_REMOVE);}Log.i(Myservice,onDestroy);} 此时通知也会被移除。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/86250.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!