-1

My app requires users to be tracked at regular intervals. this is my location service class intended to provide location updates in the set interval. this code works fine until Nougat but doesn't work from Oreo. this code was working fine a few days back not sure what went wrong. Suggestions and reviews are welcome.

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        startMyOwnForeground();
    else{
        startForeground(1, createNotification());}
    getLocationUpdates();
    thread = new LocationMonitoringThread();
    thread.start();
    mLocationCallback = new LocationCallback(){
        @Override
        public void onLocationResult(LocationResult locationResult) {
            sendNewLocationBroadcast(locationResult);
        }
    };

    return START_STICKY;
}

private void startMyOwnForeground() {

    String CHANNEL_ID = "my_channel_01";
    CharSequence name = "Project U";
    String Description = "You are being Monitored";

    int NOTIFICATION_ID = 234;

    NotificationManager notificationManager = (NotificationManager) 
getSystemService(Context.NOTIFICATION_SERVICE);


    if (android.os.Build.VERSION.SDK_INT >= 
android.os.Build.VERSION_CODES.O) {

        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, 
name, importance);
        mChannel.setDescription(Description);
        mChannel.setVibrationPattern(new long[]{ 0 });
        mChannel.enableVibration(true);
        if (notificationManager != null) {

            notificationManager.createNotificationChannel(mChannel);
        }

    }

    NotificationCompat.Builder builder = new 
NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentText("You Are being Monitored")
            .setSmallIcon(R.drawable.ic_baseline_satellite_24px)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setAutoCancel(true);
    builder.setOngoing(true);

    if (notificationManager != null) {

        notificationManager.notify(NOTIFICATION_ID, builder.build());
    }

}


private void getLocationUpdates() {

    mLocationProviderClient = 
LocationServices.getFusedLocationProviderClient(this);

    mLocationRequest = new LocationRequest();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(900000);
    mLocationRequest.setFastestInterval(20000);

}

private void sendNewLocationBroadcast(LocationResult result){

    Log.i(TAG, "sendNewLocationBroadcast: ");

    Intent intent = new Intent("com.example.projectu.LocationService");

    double latitude = result.getLastLocation().getLatitude();
    double longtitude = result.getLastLocation().getLongitude();
    int complete = 1;
    Log.d(TAG, "date: " + latitude);
    Log.d(TAG, "date: " + longtitude);
    intent.putExtra("latitude", latitude);
    intent.putExtra("longtitude", longtitude);
    intent.putExtra("complete", complete);
    sendBroadcast(intent);
    FirebaseApp.initializeApp(this);

    if (FirebaseAuth.getInstance().getCurrentUser() != null) {
        uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
    }
    adb = FirebaseFirestore.getInstance();
    Map<String, Object> att = new HashMap<>();
    att.put("Location", (new GeoPoint(latitude, longtitude)));
    att.put("latestUpdateTimestamp", FieldValue.serverTimestamp());
    adb.collection("Users").document(uid + "")
            .update(att);
}


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

private Notification createNotification(){
    String CHANNEL_ID = "my_channel_01";
    NotificationCompat.Builder builder = new 
NotificationCompat.Builder(this,
            CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_baseline_satellite_24px)
            .setContentTitle("Project U")
            .setContentText("You are being Monitored")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT);
    builder.setOngoing(true);
    return builder.build();

}

class LocationMonitoringThread extends Thread{

    Looper looper;

    @Override
    public void run() {
        if (ActivityCompat.checkSelfPermission(LocationService.this, 
Manifest.permission.ACCESS_FINE_LOCATION) != 
PackageManager.PERMISSION_GRANTED) {
             return;
        }
        getLocationUpdates();
        looper = Looper.myLooper();
        looper.prepare();
        mLocationProviderClient.requestLocationUpdates(
                mLocationRequest,
                mLocationCallback,
                looper
        );

        looper.loop();
    }

  }

}
Zoe
  • 27,060
  • 21
  • 118
  • 148
Mahesh CS
  • 9
  • 6
  • _"this code was working fine few days back not sure what went wrong."_ As it worked before, then the question is what code changes you made to break it? Android Studio can show the recent changes to the currently shown source file via the `VCS -> Local history -> Show history` menu. – Markus Kauppinen Jun 12 '19 at 11:49
  • unfortunately this project was migrated to a different computer history not present :( – Mahesh CS Jun 12 '19 at 11:51
  • What's the problem? Do you get any errors? Is the service called at all? – MarkWalczak Jun 12 '19 at 11:55
  • there is no errors also there is no location updates in the logs. yes the service is called from the main activity. also the notification for nougat and below appears. this issue is only with oreo and above. – Mahesh CS Jun 12 '19 at 11:58
  • @Jasurbek please read https://meta.stackoverflow.com/questions/254990/when-should-code-formatting-be-used-for-non-code-text/254995#254995 – Zoe Jun 12 '19 at 13:01

1 Answers1

-1

Here are two of the common pitfalls with foreground services in Android >= O:

1. Did you request the Foreground Service permission? See here:

Note: Apps that target Android 9 (API level 28) or higher and use foreground services must request the FOREGROUND_SERVICE permission. This is a normal permission, so the system automatically grants it to the requesting app.

If an app that targets API level 28 or higher attempts to create a foreground service without requesting FOREGROUND_SERVICE, the system throws a SecurityException.

2. Did you start the service using Context.startForegroundService()?

If an app needs to create a foreground service, the app should call startForegroundService(). That method creates a background service, but the method signals to the system that the service will promote itself to the foreground. Once the service has been created, the service must call its startForeground() method within five seconds.

Example code from one of my projects to make sure to call the right method to start the service:

Intent i = new Intent(context, MyService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    context.startForegroundService(i);
} else {
    context.startService(i);
}
fjc
  • 5,590
  • 17
  • 36