it-swarm.com.de

Android - StartForeground für einen Dienst implementieren?

Ich bin mir nicht sicher, wo/wie diese Methode implementiert werden soll, damit mein Dienst im Vordergrund ausgeführt wird. Derzeit beginne ich meinen Dienst mit einer anderen Aktivität: 

Intent i = new Intent(context, myService.class); 
context.startService(i);

Und dann in myServices 'onCreate () versuche ich startForeground () ...? 

Notification notification = new Notification();
startForeground(1, notification);

Ja, ich bin ein bisschen verloren und weiß nicht, wie ich das umsetzen soll.

98
JDS

Ich fange damit an, die Notification vollständig auszufüllen. Hier ist ein Beispielprojekt , das die Verwendung von startForeground() demonstriert.

119
CommonsWare

Starten Sie den Dienst aus Ihrer Hauptaktivität mit dem folgenden Code:

Intent i = new Intent(context, MyService.class); 
context.startService(i);

Dann würden Sie in Ihrem Dienst für onCreate() Ihre Benachrichtigung erstellen und als Vordergrund festlegen:

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);
59
mikebertiean

Dies ist mein Code, um den Dienst in den Vordergrund zu setzen:

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);

}

Ich muss eine Benachrichtigung mit PendingIntent erstellen, damit ich meine Hauptaktivität von der Benachrichtigung aus starten kann.

Um die Benachrichtigung zu entfernen, rufen Sie einfach stopForeground (true) auf.

Es wird in onStartCommand () aufgerufen. Bitte beachten Sie meinen Code unter: https://github.com/bearstand/greyparrot/blob/master/src/com/xiong/richard/greyparrot/Mp3Recorder.Java

26
Richard

Lösung für Oreo 8.1

Ich habe einige Probleme wie RemoteServiceException wegen ungültiger Kanal-ID bei den neuesten Versionen von Android festgestellt. So habe ich es gelöst: 

Aktivität :

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)
    }
}

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
}

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;
    }
}
14
Rawa

Zusätzlich zuRAWAantworten Sie diesen Code: 

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(intent)
} else {
    startService(intent)
}

Sie können wechseln zu:

ContextCompat.startForegroundService(context, yourIntent);

Wenn Sie in diese Methode hineinschauen, können Sie feststellen, dass diese Methode alle Überprüfungen für Sie erledigt.

8
Edgar Khimich

Wenn Sie IntentService zu einem Vordergrunddienst machen möchten

dann sollten Sie onHandleIntent() wie folgt überschreiben

Override
protected void onHandleIntent(@Nullable Intent intent) {


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

   // Do something

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

}

Wie melde ich mich?

einfach. Hier ist die getNotification()-Methode

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();
}

Tieferes Verständnis

Was passiert, wenn aus einem Dienst ein Vordergrunddienst wird

Das passiert

 enter image description here

Was ist ein Vordergrundservice?

Ein Vordergrundservice, 

  • stellt sicher, dass der Benutzer aktiv darüber informiert ist, dass im Hintergrund etwas geschieht.

  • (am wichtigsten) wird von System nicht abgebrochen, wenn der Speicher knapp wird

Ein Anwendungsfall des Vordergrunddienstes

Implementieren von Song-Download-Funktionen in einer Musik-App

6
Rohit Singh

Gib angegebenen Code Service-Klasse für "OS> = Build.VERSION_CODES.O" in onCreate ()

@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;
}

Füge diese Berechtigung in der Manifestdatei hinzu:

 <uses-permission Android:name="Android.permission.FOREGROUND_SERVICE" />
1
Kush

In meinem Fall war es völlig anders, da ich keine Aktivität hatte, um den Dienst in Oreo zu starten.

Nachfolgend sind die Schritte aufgeführt, mit denen ich dieses Problem mit dem Vordergrunddienst gelöst habe.

public class SocketService extends Service {
    private String TAG = this.getClass().getSimpleName();

    @Override
    public void onCreate() {
        Log.d(TAG, "Inside onCreate() API");
        if (Build.VERSION.SDK_INT >= 26) {
            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
            mBuilder.setSmallIcon(R.drawable.ic_launcher);
            mBuilder.setContentTitle("Notification Alert, Click Me!");
            mBuilder.setContentText("Hi, This is Android Notification Detail!");
            NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            // notificationID allows you to update the notification later on.
            mNotificationManager.notify(100, mBuilder.build());
            startForeground(100, mBuilder.mNotification);
        }
        Toast.makeText(getApplicationContext(), "inside onCreate()", Toast.LENGTH_LONG).show();
    }


    @Override
    public int onStartCommand(Intent resultIntent, int resultCode, int startId) {
        Log.d(TAG, "inside onStartCommand() API");

        return startId;
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "inside onDestroy() API");

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
}

Und danach initiierte ich diesen Dienst unter cmd -


adb -s "+ serial_id +" Shell am startforegroundservice -n com.test.socket.sample/.SocketService


Das hilft mir also, den Dienst ohne Aktivität auf Oreo-Geräten zu starten :)

0
Arpana

Hinweis: Wenn Ihre App auf API-Level 26 oder höher ausgerichtet ist, gelten Einschränkungen für die Verwendung oder Erstellung von Hintergrunddiensten, es sei denn, die App selbst befindet sich im Vordergrund. 

Wenn eine App einen Vordergrunddienst erstellen muss, sollte die App startForegroundService() aufrufen. Diese Methode erstellt einen Hintergrunddienst, aber die Methode signalisiert dem System, dass der Dienst sich selbst in den Vordergrund rückt. 

Nachdem der Dienst erstellt wurde, muss der Dienst seine startForeground() method within five seconds.aufrufen.

Behandeln Sie mit startCommand of service mit. 

 stopForeground(true)

Durch diesen Aufruf wird der Dienst aus dem Vordergrundstatus entfernt , wodurch er beendet werden kann, wenn mehr Speicher benötigt wird. Dies stoppt den Dienst nicht am Laufen. Dazu müssen Sie stopSelf () oder verwandte Methoden aufrufen.

Übergeben Sie den Wert true oder false , wenn Sie die Benachrichtigung entfernen möchten oder nicht.

val ACTION_STOP_SERVICE = "stop_service"
val NOTIFICATION_ID_SERVICE = 1
...  
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
    super.onStartCommand(intent, flags, startId)
    if (ACTION_STOP_SERVICE == intent.action) {
        stopForeground(true)
        stopSelf()
    } else {
        //Start your task

        //Send forground notification that a service will run in background.
        sendServiceNotification(this)
    }
    return Service.START_NOT_STICKY
}

Behandeln Sie Ihre Aufgabe, wenn on destroy von stopSelf () aufgerufen wird. 

override fun onDestroy() {
    super.onDestroy()
    //Stop whatever you started
}

Erstellen Sie eine Benachrichtigung, damit der Dienst im Vordergrund ausgeführt wird. 

//This is from Util class so as not to cloud your service
fun sendServiceNotification(myService: Service) {
    val notificationTitle = "Service running"
    val notificationContent = "<My app> is using <service name> "
    val actionButtonText = "Stop"
    //Check Android version and create channel for Android O and above
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        //You can do this on your own
        //createNotificationChannel(CHANNEL_ID_SERVICE)
    }
    //Build notification
    val notificationBuilder = NotificationCompat.Builder(applicationContext, CHANNEL_ID_SERVICE)
    notificationBuilder.setAutoCancel(true)
            .setDefaults(NotificationCompat.DEFAULT_ALL)
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.drawable.ic_location)
            .setContentTitle(notificationTitle)
            .setContentText(notificationContent)
            .setVibrate(null)
    //Add stop button on notification
    val pStopSelf = createStopButtonIntent(myService)
    notificationBuilder.addAction(R.drawable.ic_location, actionButtonText, pStopSelf)
    //Build notification
    val notificationManagerCompact = NotificationManagerCompat.from(applicationContext)
    notificationManagerCompact.notify(NOTIFICATION_ID_SERVICE, notificationBuilder.build())
    val notification = notificationBuilder.build()
    //Start notification in foreground to let user know which service is running.
    myService.startForeground(NOTIFICATION_ID_SERVICE, notification)
    //Send notification
    notificationManagerCompact.notify(NOTIFICATION_ID_SERVICE, notification)
}

Geben Sie der Benachrichtigung eine Stopp-Schaltfläche, um den Dienst zu stoppen, wenn der Benutzer dies benötigt.

/**
 * Function to create stop button intent to stop the service.
 */
private fun createStopButtonIntent(myService: Service): PendingIntent? {
    val stopSelf = Intent(applicationContext, MyService::class.Java)
    stopSelf.action = ACTION_STOP_SERVICE
    return PendingIntent.getService(myService, 0,
            stopSelf, PendingIntent.FLAG_CANCEL_CURRENT)
}
0