简体   繁体   English

为什么前台服务从后台删除应用程序后无法正常工作?

[英]Why foreground Service not working after removing app from the background?

I have been trying to implement foreground service to get location after every 3 sec even when the app is in the background by showing a notification. 即使应用程序在后台显示通知,我也一直在尝试实施前台服务,以便每隔3秒获取一次位置。 But when I remove my app from the background notification also removes. 但是当我从后台删除我的应用时,通知也会删除。 However, this is only occurring when I am doing it in MI REDMI NOTE 5(API version 28) and MI REDMI NOTE 4(API version 24) but when I ran the same app in Samsung J5(API version 23), the notification is showing even when the app is removed from background until it is manually stopped from the activity. 但是,这只发生在MI REDMI NOTE 5(API版本28)和MI REDMI NOTE 4(API版本24)中,但是当我在Samsung J5(API版本23)中运行相同的应用程序时,通知是甚至在应用程序从后台删除,直到从活动中手动停止为止。 Is the varied result behavior is due to change in API or is it because of different phone model? 变化的结果行为是由于API的变化还是因为不同的手机型号?

Here's my Service Class 这是我的服务类

package com.example.locationrunandall;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;

public class ForeService extends Service {


    private static final String PACKAGE_NAME =
            "com.example.customizedforeground";

    static final String ACTION_BROADCAST = PACKAGE_NAME + ".broadcast";
    static final String EXTRA_LOCATION = PACKAGE_NAME + ".location";
    private static final String EXTRA_STARTED_FROM_NOTIFICATION = PACKAGE_NAME +
            ".started_from_notification";
    private Handler mServiceHandler;
    private NotificationManager mNotificationManager;
   // private Notification notification;
    private LocationRequest mLocationRequest;
    private FusedLocationProviderClient mFusedLocationClient;
    private LocationCallback mLocationCallback;
    private Location mLocation;
    private static final String CHANNEL_ID = "CHANNEL_ONE";
    private static final int NOTIFICATION_ID = 4567123;
    private static final String TAG = "123";
    String loc;

    public ForeService(){}

    @Override
    public void onCreate() {
      mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
      mLocationCallback = new LocationCallback(){
    @Override
    public void onLocationResult(LocationResult locationResult) {
        super.onLocationResult(locationResult);
      //Do Location Work You Want To Do
        onNewLocation(locationResult.getLastLocation());
    }
};
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(3*1000);
        mLocationRequest.setFastestInterval(1000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        getLastLocation();
        HandlerThread handlerThread = new HandlerThread("HANDLER");
        handlerThread.start();
        mServiceHandler = new Handler(handlerThread.getLooper());
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        CharSequence name = "Name Charseq";
        if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.O){
            NotificationChannel notificationChannel = new
                    NotificationChannel(CHANNEL_ID,name, NotificationManager.IMPORTANCE_DEFAULT);

            mNotificationManager.createNotificationChannel(notificationChannel);
        }
        startForeground(NOTIFICATION_ID,getNotification());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
       // startForeground(NOTIFICATION_ID,getNotification());
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceHandler.removeCallbacksAndMessages(null);

        //stopForeground(true);
    }

    @androidx.annotation.Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    private void getLastLocation() {
        try {
            mFusedLocationClient.getLastLocation()
                    .addOnCompleteListener(new OnCompleteListener<Location>() {
                        @Override
                        public void onComplete(@NonNull Task<Location> task) {
                            if (task.isSuccessful() && task.getResult() != null) {
                                mLocation = task.getResult();
                            } else {
                                Log.d(TAG, "Failed to get location.");
                            }
                        }
                    });
        } catch (SecurityException unlikely) {
            Log.d(TAG, "Lost location permission." + unlikely);
        }
    }

    private void onNewLocation(Location location) {
        mLocation = location;
        if(mLocation==null)
        Log.d("DSK_OPER","Lat: = "+"Not known");
        else
            Log.d("DSK_OPER"," : "+location.getLatitude());
        //send intent to broadcast reciever
        Intent intent = new Intent(ACTION_BROADCAST);
        intent.putExtra(EXTRA_LOCATION, location);
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
        // todo - Write More code here
        mNotificationManager.notify(NOTIFICATION_ID,getNotification());
    }



    private Notification getNotification() {

        //Intent intent = new Intent(this,MainActivity.class);

        if(mLocation==null)
            loc = "unknown loc";
        else
            loc = String.valueOf(mLocation.getLatitude());

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setContentTitle("Latitude and longitude")
                .setContentText(" = "+loc)
                .setOngoing(true)
                .setPriority(Notification.PRIORITY_HIGH)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setWhen(System.currentTimeMillis());

        // Set the Channel ID for Android O.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder.setChannelId(CHANNEL_ID);
        }
        return builder.build();
    }

}

I am using the foreground service for location update after some interval. 我在一段时间后使用前台服务进行位置更新。 Foreground service is useful when you wants to update the location if your app is in background but not killed. 如果您想要在应用程序处于后台但未被杀死的情况下更新位置,则前台服务非常有用。 But this is your responsibility to stop the foreground service when your app is killed. 但是,当您的应用程序被杀时,您有责任停止前台服务。 So you just implement the LifeCycleDelegate so that you can start the service when app is in background and stop the service when app is in foreground. 因此,您只需实现LifeCycleDelegate,以便在应用程序处于后台时启动服务,并在应用程序处于前台时停止服务。 and also kill the service when your main activity or HomeActivity is killed. 并在主要活动或HomeActivity被杀死时终止服务。 this is the code for AppLifecycleHandler. 这是AppLifecycleHandler的代码。

internal class AppLifecycleHandler(private val lifeCycleDelegate: LifeCycleDelegate) : Application.ActivityLifecycleCallbacks,
    ComponentCallbacks2 {

private var appInForeground = false

override fun onActivityPaused(p0: Activity?) {}

/**
 * app resumed
 */
override fun onActivityResumed(p0: Activity?) {
    if (!appInForeground) {
        appInForeground = true
        lifeCycleDelegate.onAppForegrounded()
    }
}

override fun onActivityStarted(p0: Activity?) {
}

override fun onActivityDestroyed(p0: Activity?) {
}

override fun onActivitySaveInstanceState(p0: Activity?, p1: Bundle?) {
}

override fun onActivityStopped(p0: Activity?) {
}

override fun onActivityCreated(p0: Activity?, p1: Bundle?) {
}

override fun onLowMemory() {}

override fun onConfigurationChanged(p0: Configuration?) {}

/**
 * app sent to background
 */
override fun onTrimMemory(level: Int) {
    if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
        appInForeground = false
        lifeCycleDelegate.onAppBackgrounded()
    }
}

Add this method to your application class private fun registerLifecycleHandler(lifeCycleHandler: AppLifecycleHandler) { registerActivityLifecycleCallbacks(lifeCycleHandler) registerComponentCallbacks(lifeCycleHandler) } 将此方法添加到您的应用程序类private fun registerLifecycleHandler(lifeCycleHandler:AppLifecycleHandler){registerActivityLifecycleCallbacks(lifeCycleHandler)registerComponentCallbacks(lifeCycleHandler)}

override fun getLifecycle(): Lifecycle {
    return mLifecycleRegistry
}

implements LifeCycleDelegate in your application class and override the methods 在您的应用程序类中实现LifeCycleDelegate并覆盖这些方法

internal interface LifeCycleDelegate {
fun onAppBackgrounded()
fun onAppForegrounded()

} }

create app object in application class 在应用程序类中创建app对象

val lifeCycleHandler = AppLifecycleHandler(this)
    registerLifecycleHandler(lifeCycleHandler)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当应用程序从后台进入前台时,onBackPress() 不起作用 - onBackPress() is not working when app comes to foreground from background 当应用程序移至后台时,在前台服务中获取位置更新不起作用 - getting location updates in foreground service isn't working when app is moved to background 应用程序终止后如何停止前台服务? - How to stop a foreground service after app kill? 后台执行服务 - Background and foreground Service For Execution 当Oreo中的应用程序在后台运行时,音乐服务几秒钟后无法正常工作 - Music service not working after some second when app in background in Oreo 杀死并重新启动应用程序后前台服务未停止 - Android Studio - Foreground service not stopping after killing and relaunching app - Android Studio 如何连续检查我的应用程序的前台服务在前台打开了哪个应用程序? - How to check continuously which app is opened in foreground from my app's foreground service? 从前景到背景后位置始终为空? - Location is always null after coming from foreground to background? 背景-&gt;前景开关上的服务插座断开连接 - Service Socket Disconnect on Background->Foreground switch 安卓后台wifi扫描前台服务 - Android Background Wifi Scanning Foreground Service
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM