Android - 为服务实现startForeground?

JDS*_*JDS 117 service android android-service

所以我不确定在何处/如何实现此方法以使我的服务在前台运行.目前我在另一项活动中通过以下方式开始我的服务:

Intent i = new Intent(context, myService.class); 
context.startService(i);
Run Code Online (Sandbox Code Playgroud)

然后在myServices的onCreate()中我尝试startForeground()......?

Notification notification = new Notification();
startForeground(1, notification);
Run Code Online (Sandbox Code Playgroud)

所以是的,我有点失落,不确定如何实现这一点.

Com*_*are 131

我首先要完全填写Notification.这是一个演示如何使用的示例项目startForeground().

  • @DoctorOreo:它必须在应用程序中是唯一的,但不一定在设备上是唯一的.我选择了1337,因为它是[1337](http://en.wikipedia.org/wiki/Leet).:-) (30认同)
  • 是否可以在没有通知的情况下使用startForeground()?或者我们以后可以更新相同的通知吗 (7认同)
  • @Snicolas:幸运的是,没有. (5认同)
  • 是否有一个特殊的原因你使用`1337`? (2认同)
  • @Snicolas:感谢您指出Android中的一个漏洞.我会努力解决这个问题. (2认同)

mik*_*ean 74

在您的主要活动中,使用以下代码启动服务:

Intent i = new Intent(context, MyService.class); 
context.startService(i);
Run Code Online (Sandbox Code Playgroud)

然后在您的服务中为onCreate()您构建通知并将其设置为前景,如下所示:

Intent notificationIntent = new Intent(this, MainActivity.class);

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                notificationIntent, 0);

Notification notification = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.app_icon)
                .setContentTitle("My Awesome App")
                .setContentText("Doing some work...")
                .setContentIntent(pendingIntent).build();

startForeground(1337, notification);
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记: <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> (3认同)

Ric*_*ard 29

这是我将服务设置为前台的代码:

private void runAsForeground(){
    Intent notificationIntent = new Intent(this, RecorderMainActivity.class);
    PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
            notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);

    Notification notification=new NotificationCompat.Builder(this)
                                .setSmallIcon(R.drawable.ic_launcher)
                                .setContentText(getString(R.string.isRecording))
                                .setContentIntent(pendingIntent).build();

    startForeground(NOTIFICATION_ID, notification);

}
Run Code Online (Sandbox Code Playgroud)

我需要使用PendingIntent构建通知,以便我可以从通知中启动我的主要活动.

要删除通知,只需调用stopForeground(true);

它在onStartCommand()中调用.请参阅我的代码:https://github.com/bearstand/greyparrot/blob/master/src/com/xiong/richard/greyparrot/Mp3Recorder.java

  • 你在哪里称这种方法? (6认同)
  • `Intent.FLAG_ACTIVITY_NEW_TASK`在`PendingIntent`的上下文中无效. (6认同)

Raw*_*awa 20

奥利奥8.1的解决方案

我遇到了一些问题,例如RemoteServiceException,因为最新版本的Android的通道ID无效.这就是我解决它的方式:

活动:

override fun onCreate(savedInstanceState: Bundle?) {
    val intent = Intent(this, BackgroundService::class.java)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(intent)
    } else {
        startService(intent)
    }
}
Run Code Online (Sandbox Code Playgroud)

BackgroundService:

override fun onCreate() {
    super.onCreate()
    startForeground()
}

private fun startForeground() {

    val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    val channelId =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                createNotificationChannel()
            } else {
                // If earlier version channel ID is not used
                // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
                ""
            }

    val notificationBuilder = NotificationCompat.Builder(this, channelId )
    val notification = notificationBuilder.setOngoing(true)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setPriority(PRIORITY_MIN)
            .setCategory(Notification.CATEGORY_SERVICE)
            .build()
    startForeground(101, notification)
}


@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(): String{
    val channelId = "my_service"
    val channelName = "My Background Service"
    val chan = NotificationChannel(channelId,
            channelName, NotificationManager.IMPORTANCE_HIGH)
    chan.lightColor = Color.BLUE
    chan.importance = NotificationManager.IMPORTANCE_NONE
    chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
    val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    service.createNotificationChannel(chan)
    return channelId
}
Run Code Online (Sandbox Code Playgroud)

JAVA EQUIVALENT

public class YourService extends Service {

    // Constants
    private static final int ID_SERVICE = 101;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        // do stuff like register for BroadcastReceiver, etc.

        // Create the Foreground Service
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? createNotificationChannel(notificationManager) : "";
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId);
        Notification notification = notificationBuilder.setOngoing(true)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(PRIORITY_MIN)
                .setCategory(NotificationCompat.CATEGORY_SERVICE)
                .build();

        startForeground(ID_SERVICE, notification);
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private String createNotificationChannel(NotificationManager notificationManager){
        String channelId = "my_service_channelid";
        String channelName = "My Foreground Service";
        NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
        // omitted the LED color
        channel.setImportance(NotificationManager.IMPORTANCE_NONE);
        channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
        notificationManager.createNotificationChannel(channel);
        return channelId;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您可以在Activity中使用`ContextCompat.startForegroundService(Context,Intent)`来执行正确的操作.(https://developer.android.com/reference/android/support/v4/content/ContextCompat.html) (4认同)
  • 请注意,针对`Build.VERSION_CODES.P`(API级别28)或更高版本的应用必须请求权限`Manifest.permission.FOREGROUND_SERVICE`才能使用`startForeground()` - 请参阅https://developer.android.com /reference/android/app/Service.html#startForeground(int,%20android.app.Notification) (4认同)
  • 如果您的最小API小于21,则可能要使用.setCategory(NotificationCompat.CATEGORY_SERVICE)而不是Notification.CATEGORY_SERVICE。 (2认同)

Edg*_*ich 18

除了RAWA的答案,这个代码的和平:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(intent)
} else {
    startService(intent)
}
Run Code Online (Sandbox Code Playgroud)

你可以改为:

ContextCompat.startForegroundService(context, yourIntent);
Run Code Online (Sandbox Code Playgroud)

如果您将查看此方法,那么您可以看到此方法为您执行所有检查工作.


Kus*_*ush 9

在 onCreate() 中为“OS >= Build.VERSION_CODES.O”添加给定的代码服务类

@Override
public void onCreate(){
    super.onCreate();

     .................................
     .................................

    //For creating the Foreground Service
    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? getNotificationChannel(notificationManager) : "";
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId);
    Notification notification = notificationBuilder.setOngoing(true)
            .setSmallIcon(R.mipmap.ic_launcher)
           // .setPriority(PRIORITY_MIN)
            .setCategory(NotificationCompat.CATEGORY_SERVICE)
            .build();

    startForeground(110, notification);
}



@RequiresApi(Build.VERSION_CODES.O)
private String getNotificationChannel(NotificationManager notificationManager){
    String channelId = "channelid";
    String channelName = getResources().getString(R.string.app_name);
    NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
    channel.setImportance(NotificationManager.IMPORTANCE_NONE);
    channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
    notificationManager.createNotificationChannel(channel);
    return channelId;
}
Run Code Online (Sandbox Code Playgroud)

在清单文件中添加此权限:

 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Run Code Online (Sandbox Code Playgroud)


Roh*_*ngh 7

如果您想使IntentService成为前台服务

那么你应该onHandleIntent()像这样覆盖

Override
protected void onHandleIntent(@Nullable Intent intent) {


    startForeground(FOREGROUND_ID,getNotification());     //<-- Makes Foreground

   // Do something

    stopForeground(true);                                // <-- Makes it again a normal Service                         

}
Run Code Online (Sandbox Code Playgroud)

如何发出通知?

简单.这是getNotification()方法

public Notification getNotification()
{

    Intent intent = new Intent(this, SecondActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,0);


    NotificationCompat.Builder foregroundNotification = new NotificationCompat.Builder(this);
    foregroundNotification.setOngoing(true);

    foregroundNotification.setContentTitle("MY Foreground Notification")
            .setContentText("This is the first foreground notification Peace")
            .setSmallIcon(android.R.drawable.ic_btn_speak_now)
            .setContentIntent(pendingIntent);


    return foregroundNotification.build();
}
Run Code Online (Sandbox Code Playgroud)

深入了解

当服务成为前台服务时会发生什么

有时候是这样的

在此输入图像描述

什么是前台服务?

前台服务,

  • 确保用户通过提供通知主动了解后台正在发生的事情.

  • (最重要的是)当内存不足时,系统不会将其杀死

前台服务的用例

在音乐应用程序中实现歌曲下载功能