Oreo - Starting a service in the foreground

14,210

Solution 1

Try to change your startInForeground() method with this code:

private void startInForeground() {
        Intent notificationIntent = new Intent(this, WorkoutActivity.class);
        PendingIntent pendingIntent=PendingIntent.getActivity(this,0,notificationIntent,0);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID)
                .setSmallIcon(R.drawable.shsl_notification)
                .setContentTitle("TEST")
                .setContentText("HELLO")
                .setTicker("TICKER") 
                .setContentIntent(pendingIntent);
        Notification notification=builder.build();
        if(Build.VERSION.SDK_INT>=26) {
            NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
            channel.setDescription(NOTIFICATION_CHANNEL_DESC);
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(channel);
        }
        startForeground(NOTIFICATION_ID, notification);
}

So, when your Android version is Oreo (or higher) notification channel will be created, otherwise not.

Solution 2

Before show notification you have to create notification channel:

private void createNotificationChannel() {
    if (Build.VERSION_CODES.O <= Build.VERSION.SDK_INT) {
        NotificationChannel notificationChannel =
                new NotificationChannel(PRIMARY_CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
        notificationManager.createNotificationChannel(notificationChannel);
    }
}

and then change create notification builder

new Notification.Builder(context, PRIMARY_CHANNEL_ID)
Share:
14,210
KOB
Author by

KOB

Updated on July 23, 2022

Comments

  • KOB
    KOB almost 2 years

    I have created a service that tracks the device's location as it moves. The service is started in by an Activity that binds to it, and in this activity there is a "Start Tracking" button. When this button is pressed, I need the service to start in the foreground, so that it stores the Locations that the device has moved to, even if the Activity that binds to it is closed, or the app is minimised.

    I understand that for the Service to be in the foreground, a notification must be displayed. I have attempted to do so, but I cannot get the notification to show or the Service to work in the foreground when the activity is destroyed.

    It appears that notifications have changed in Oreo due to the notification channels, but I cannot figure out what needs to be done differently. The device I am testing this on is on 8.0.0.

    Here is mys service:

    public class LocationTrackerService extends Service {
    
        private LocationListener locationListener;
        private LocationManager locationManager;
        private IBinder binder = new LocalBinder();
        private boolean isTracking;
        private ArrayList<Location> trackedWaypoints;
        private String bestProvider;
        private Timer timer;
        private Distance distance;
    
        @SuppressLint("MissingPermission")
        @Override
        public void onCreate() {
            super.onCreate();
    
            locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
            Criteria criteria = new Criteria();
            bestProvider = locationManager.getBestProvider(criteria, true);
    
            isTracking = false;
    
            locationListener = new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    Intent intent = new Intent("location_update");
                    intent.putExtra("latitude", location.getLatitude());
                    intent.putExtra("longitude", location.getLongitude());
                    sendBroadcast(intent);
                    if (isTracking) {
                        if (trackedWaypoints.size() > 1) {
                            distance.add(trackedWaypoints.get(trackedWaypoints.size() - 1).distanceTo(location));
                        }
                        trackedWaypoints.add(location);
                    }
                }
    
                @Override
                public void onStatusChanged(String s, int i, Bundle bundle) { }
    
                @Override
                public void onProviderEnabled(String s) { }
    
                @Override
                public void onProviderDisabled(String s) {
                    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                }
            };
    
            locationManager.requestLocationUpdates(bestProvider, 0, 0, locationListener);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            if (locationManager != null) {
                locationManager.removeUpdates(locationListener);
            }
        }
    
        public void startTracking() {
            trackedWaypoints = new ArrayList<Location>();
            timer = new Timer();
            distance = new Distance();
            timer.start();
            isTracking = true;
            startInForeground();
        }
    
        private void startInForeground() {
            Intent notificationIntent = new Intent(this, WorkoutActivity.class);
            PendingIntent pendingIntent =
                    PendingIntent.getActivity(this, 0, notificationIntent, 0);
    
            Notification notification =
                    new Notification.Builder(this)
                            .setContentTitle("TEST")
                            .setContentText("HELLO")
                            .setSmallIcon(R.drawable.ic_directions_run_black_24dp)
                            .setContentIntent(pendingIntent)
                            .setTicker("TICKER")
                            .build();
    
            startForeground(101, notification);
        }
    
        public void stopTracking() {
            isTracking = false;
            stopForeground(true);
        }
    
        public boolean isTracking() {
            return isTracking;
        }
    
        public ArrayList<Location> getTrackedWaypoints() {
            return trackedWaypoints;
        }
    
        public Timer getTime() {
            timer.update();
            return timer;
        }
    
        public Distance getDistance() {
            return distance;
        }
    
        public int getSteps() {
            return 0;
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        public class LocalBinder extends Binder {
            public LocationTrackerService getLocationTrackerInstance() {
                return LocationTrackerService.this;
            }
        }
    }
    
  • A.Alqadomi
    A.Alqadomi over 6 years
    thanks it worked , minor update to the code , instead of using 26 you can use Build.VERSION_CODES.O which will increase the readability of your code .
  • j3App
    j3App almost 6 years
    From which library are you using "NotificationCompat.Builder" ? The variants I found only accept one parameter (Context).
  • j3App
    j3App almost 6 years
    Just found the answer. You need to set ALL google support libs to minimum 26.1.0