Android - 前台在 Oreo 中不起作用。操作系统在一段时间后终止服务

Posted

技术标签:

【中文标题】Android - 前台在 Oreo 中不起作用。操作系统在一段时间后终止服务【英文标题】:Android - Foreground is not working in Oreo. OS killed service after some interval 【发布时间】:2019-05-12 02:04:22 【问题描述】:

我有一个应用程序每隔 5 分钟在后台使用一次定位服务。我们在前台服务中使用 Fusedlocationproviderclient。当应用程序打开时它工作正常。

当我将应用程序置于后台或从后台滑动杀死时,android 8.0 及更高版本的操作系统会自动杀死前台服务。

我们在三星 note 8、一加 5t 和 red mi 设备中遇到问题。

请告诉我如何实现兼容所有设备的服务。

这是我的定位服务课程。

    public class TrackingForgroundService extends Service 


    private final long UPDATE_INTERVAL = (long) 2000;
    private static final long FASTEST_INTERVAL = 2000;

    public BookingTrackingForgroundService() 

    

    @Nullable
    @Override
    public IBinder onBind(Intent intent) 
        return null;
    


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


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        if (intent != null) 
            String action = intent.getAction();

            switch (action) 
                case ACTION_START_FOREGROUND_SERVICE:
                    startForegroundService();

                    break;
                case ACTION_STOP_FOREGROUND_SERVICE:
                    stopForegroundService();

                    break;
            
        
        return START_STICKY;
    


    private class TimerTaskToGetLocation extends TimerTask 
        @Override
        public void run() 

            mHandler.post(new Runnable() 
                @Override
                public void run() 
                    // Call webservice evry 5 minute
                
            );

        
    


    private void startForegroundService() 

        Log.d(TAG_FOREGROUND_SERVICE, "Start foreground service.");

        context = this;
        startLocationUpdates();
        notify_interval1 = Prefs.with(this).readLong("notify_interval1", 5000);
        mTimer = new Timer();
        mTimer.scheduleAtFixedRate(new TimerTaskToGetLocation(), 15000, notify_interval1);
        mTimer.scheduleAtFixedRate(new TimerTaskToSendCsvFile(), 60000, 1200000);
        prefsPrivate = getSharedPreferences(Constants.prefsKeys.PREFS_PRIVATE, Context.MODE_PRIVATE);
        internet = new NetConnectionService(context);


        Intent notificationIntent = new Intent(this, ActTherapistDashboard.class);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle(getString(R.string.app_name))
                .setContentText("Geolocation is running")
                .setTicker("Geolocation").setSmallIcon(R.drawable.app_small_icon_white)
                .setContentIntent(pendingIntent);
        Notification notification = builder.build();
        if (Build.VERSION.SDK_INT >= 26) 
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
            channel.setDescription(CHANNEL_DESCRIPTION);
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(channel);
        
        startForeground(SERVICE_ID, notification);
    

    private void stopForegroundService() 
        stopLocationUpdates();
        Log.d(TAG_FOREGROUND_SERVICE, "Stop foreground service.");
        if (mTimer != null) 
            mTimer.cancel();
         else 
            mTimer = null;
        
        // Stop foreground service and remove the notification.
        stopForeground(true);

        // Stop the foreground service.
        stopSelf();
    




    public static boolean isServiceRunningInForeground(Context context, Class<?> serviceClass) 
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) 
            if (serviceClass.getName().equals(service.service.getClassName())) 
                if (service.foreground) 
                    return true;
                

            
        
        return false;
    


    private void startLocationUpdates() 
        // create location request object
        mLocationRequest = LocationRequest.create();

        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);


        // initialize location setting request builder object
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);
        LocationSettingsRequest locationSettingsRequest = builder.build();


        // initialize location service object
        SettingsClient settingsClient = LocationServices.getSettingsClient(this);
        Task<LocationSettingsResponse> task = settingsClient.checkLocationSettings(locationSettingsRequest);
        task.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() 
            @Override
            public void onSuccess(LocationSettingsResponse locationSettingsResponse) 
                registerLocationListner();
            
        );


    


    private void registerLocationListner() 
        locationCallback = new LocationCallback() 
            @Override
            public void onLocationResult(LocationResult locationResult) 
                super.onLocationResult(locationResult);
                onLocationChanged(locationResult.getLastLocation());
            
        ;

      //location permission
        LocationServices.getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, locationCallback, null);

    


    private void onLocationChanged(Location location) 

        if (location != null) 
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            latitudeTemp = latitude;
            longitudeTemp = longitude;
        

    



       

【问题讨论】:

为什么不能使用 JobScheduler ?为了让服务在 Android Oreo 中继续运行,我们需要显示通知 @Rahul Patil JobScheduler 在设备处于睡眠模式或打盹模式时不起作用。 前台服务不能保证永久驻留该服务。它只是将它放在杀死优先级链上的较低位置。 @RahulPatil 感谢您的快速回复。以前我们使用过jobschduler,但它不能在锁定屏幕和打盹模式下工作。这就是我们从作业调度程序切换到带有通知的前台服务的原因。 @GabeSechan - 感谢分享知识。除前台服务外,哪个是解决我的问题的最佳解决方案? 【参考方案1】:

请参阅here 对类似问题的回答以及链接网站dontkillmyapp,它为开发人员提供了非常有用的摘要,以帮助了解不同手机制造商和 Android 操作系统版本的此问题。

【讨论】:

以上是关于Android - 前台在 Oreo 中不起作用。操作系统在一段时间后终止服务的主要内容,如果未能解决你的问题,请参考以下文章

Oreo+ 中位置更新的前台服务不起作用

FCM 通知在 OREO 中不起作用

广播接收器在 Android 8 的前台服务中不起作用

Android Oreo onTaskRemoved 事件不起作用(Android 版本 Oreo)

在android oreo中设备重启后PeriodicWorkRequest不起作用

Firebase 云消息传递前台通知在 Vue 中不起作用