Background Service not Stopping Android

Deepank Mehta :

I have background services which captures location from the users device but when I stop it using the stopService method from anther activity it does not stop and due to this the app crashes as the app is not able to send the lat long to server.

Note - I have a retrofit post request which is made to the server when the location is not null and also when I click on the stop service button in main activity the notification disappears from the device but actually the service does not stop and the location is logged in the logcat. But it is not posted to the server due to this timeout error is received and app crashes.

Here is the service class:

public class LiveLocationService extends Service {
    private static final String TAG = LiveLocationService.class.getSimpleName();
    Retrofit retrofitClient;
    CompositeDisposable compositeDisposable = new CompositeDisposable();
    MyService myService;
    String empCode, year, month, date;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        retrofitClient = RetrofitClient.getInstance();
        myService = retrofitClient.create(MyService.class);

        empCode = intent.getStringExtra("empCode");
        year = intent.getStringExtra("year");
        month = intent.getStringExtra("month");
        date = intent.getStringExtra("date");
        return super.onStartCommand(intent, flags, startId);
    }

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

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void onCreate() {
        super.onCreate();
        buildNotification();
        requestLocationUpdates();
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void buildNotification() {
        String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
        String channelName = "My Background Service";
        NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_HIGH);
        chan.setLightColor(Color.BLUE);
        chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        assert manager != null;
        manager.createNotificationChannel(chan);

        PendingIntent intent = PendingIntent.getActivity(this, 0,  new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
        Notification notification = notificationBuilder.setOngoing(true)
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle("Service is tracking your location.")
                .setPriority(NotificationManager.IMPORTANCE_HIGH)
                .setCategory(Notification.CATEGORY_SERVICE)
                .setContentIntent(intent)
                .build();
        startForeground(2, notification);

    }

    private void requestLocationUpdates() {
        LocationRequest request = new LocationRequest();
        request.setInterval(10000);
        request.setFastestInterval(5000);
        request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(this);
        int permission = ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION);
        if (permission == PackageManager.PERMISSION_GRANTED) {
                client.requestLocationUpdates(request, new LocationCallback() {
                    @Override
                    public void onLocationResult(LocationResult locationResult) {
                        Location location = locationResult.getLastLocation();
                        if (location != null) {
                            Log.d(TAG, "location update " + location);
                            double lat = location.getLatitude();
                            double lon = location.getLongitude();
                            final String time = new SimpleDateFormat("HH:mm", Locale.getDefault()).format(new Date());
                            compositeDisposable.add(myService.userLocation(empCode, year, month, date, time, lat, lon)
                                    .subscribeOn(Schedulers.io())
                                    .observeOn(AndroidSchedulers.mainThread())
                                    .subscribe(new Consumer< String >() {
                                        @Override
                                        public void accept(String s) throws Exception {
                                            Log.e("data", s);
                                            if (s.equals("\"done\"")) {
                                                Log.e("status", "location punched");
                                            }
                                        }
                                    }));
                        } else {
                            Log.d("MSER", "location update, no location found. ");
                        }
                    }
                }, null);
        } else {
            Log.e("MSER", "Please enable location.");
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopForeground(true);
        stopSelf();
    }
}

Here is the HomeActivity.

public class HomeActivity extends AppCompatActivity {

    String empCode, name;
    private TextView code, displayName;
    private Button punchInBtn, punchOutBtn;
    CompositeDisposable compositeDisposable = new CompositeDisposable();
    MyService myService;
    private Toolbar toolbar;
    SharedPreferences sharedPreferences;
    SharedPreferences.Editor editor;
    private static final String SHARED_PREFS = "sharedPrefs";
    private static final int PERMISSIONS_REQUEST = 1;
    LiveLocationService liveLocationService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setTitle("Management Services");
        toolbar.setTitleTextColor(getResources().getColor(R.color.white));
        toolbar.setOverflowIcon(getResources().getDrawable(R.drawable.menu));

        Retrofit retrofitClient = RetrofitClient.getInstance();
        myService = retrofitClient.create(MyService.class);

        code = findViewById(R.id.code);
        displayName = findViewById(R.id.name);
        punchInBtn = findViewById(R.id.punchIn);
        punchOutBtn = findViewById(R.id.punchOut);

        empCode = getIntent().getStringExtra("empCode");
        name = getIntent().getStringExtra("name");

        code.setText(empCode);
        displayName.setText(name);

        final String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
        final String year = date.substring(0, 4);
        final String month = date.substring(5, 7);
        final String dateToday = date.substring(8, 10);

        punchInBtn.setVisibility(View.INVISIBLE);
        punchOutBtn.setVisibility(View.INVISIBLE);


        compositeDisposable.add(myService.userStatus(empCode)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer< String >() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.e("data", s);
                        if (s.equals("logout")) {
                            Toast.makeText(HomeActivity.this, s, Toast.LENGTH_SHORT).show();
                        } else {
                            JSONObject basicObject = new JSONObject(s);
                            JSONArray attendanceArray = basicObject.getJSONArray("attendance");

                            ArrayList< String > toAdd = new ArrayList<>();

                            if (attendanceArray.length() > 0) {
                                for (int i = 0; i < attendanceArray.length(); i++) {
                                    JSONObject attendanceObject = attendanceArray.getJSONObject(i);
                                    String yearName = attendanceObject.getString("year");
                                    String monthName = attendanceObject.getString("month");
                                    String dateName = attendanceObject.getString("date");
                                    boolean loginStatus = attendanceObject.getBoolean("loginStatus");
                                    if (yearName.equals(year) && monthName.equals(month) && dateName.equals(dateToday) && loginStatus) {
                                        punchInBtn.setVisibility(View.INVISIBLE);
                                        punchOutBtn.setVisibility(View.VISIBLE);
                                        return;
                                    } else {
                                        toAdd.add("punch in");
                                    }
                                }
                                if (toAdd.contains("punch in")) {
                                    punchInBtn.setVisibility(View.VISIBLE);
                                    punchOutBtn.setVisibility(View.INVISIBLE);
                                }
                            } else {
                                punchInBtn.setVisibility(View.VISIBLE);
                            }
                        }
                    }
                }));

        punchInBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Check GPS is enabled
                LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
                if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                    Toast.makeText(HomeActivity.this, "Please enable location services", Toast.LENGTH_SHORT).show();
                    finish();
                }

                // Check location permission is granted - if it is, start
                // the service, otherwise request the permission
                int permission = ContextCompat.checkSelfPermission(HomeActivity.this,
                        Manifest.permission.ACCESS_FINE_LOCATION);
                if (permission == PackageManager.PERMISSION_GRANTED) {

                    final String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
                    final String time = new SimpleDateFormat("HH:mm", Locale.getDefault()).format(new Date());
                    final String year = date.substring(0, 4);
                    final String month = date.substring(5, 7);
                    final String dateToday = date.substring(8, 10);

                    compositeDisposable.add(myService.userStatus(empCode)
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new Consumer< String >() {
                                @Override
                                public void accept(String s) throws Exception {
                                    Log.e("data", s);
                                    if (s.equals("logout")) {
                                        Toast.makeText(HomeActivity.this, s, Toast.LENGTH_SHORT).show();
                                    } else {
                                        JSONObject basicObject = new JSONObject(s);

                                        String inTime = basicObject.getString("inTime");
                                        SimpleDateFormat df = new SimpleDateFormat("HH:mm");
                                        Date finalInTime = df.parse(inTime);
                                        Calendar cal = Calendar.getInstance();
                                        cal.setTime(finalInTime);
                                        cal.add(Calendar.MINUTE, 15);
                                        String newTime = df.format(cal.getTime());

                                        String[] timeDivide = time.split(":");
                                        String[] newTimeDivide = newTime.split(":");

                                        int timeHour = Integer.parseInt(timeDivide[0]);
                                        int timeMin = Integer.parseInt(timeDivide[1]);

                                        int newTimeHour = Integer.parseInt(newTimeDivide[0]);
                                        int newTimeMin = Integer.parseInt(newTimeDivide[1]);

                                        String status = "";

                                        if (timeHour > newTimeHour) {
                                            Log.e("status", "Your are late");
                                            status = "Late";
                                        } else if (timeHour == newTimeHour) {
                                            if (timeMin > newTimeMin) {
                                                Log.e("status", "Your are late");
                                                status = "Late";
                                            } else {
                                                Log.e("status", "You are on time");
                                                status = "On Time";
                                            }
                                        } else {
                                            Log.e("status", "You are on time");
                                            status = "On Time";
                                        }

                                        ArrayList< String > toAdd = new ArrayList<>();

                                        JSONArray attendanceArray = basicObject.getJSONArray("attendance");
                                        if (attendanceArray.length() > 0) {
                                            for (int i = 0; i < attendanceArray.length(); i++) {
                                                JSONObject attendanceObject = attendanceArray.getJSONObject(i);
                                                String yearName = attendanceObject.getString("year");
                                                String monthName = attendanceObject.getString("month");
                                                String dateName = attendanceObject.getString("date");
                                                boolean loginStatus = attendanceObject.getBoolean("loginStatus");
                                                if (yearName.equals(year) && monthName.equals(month) && dateName.equals(dateToday) && !loginStatus) {
                                                    Log.e("status", "add new inTime.");
                                                    compositeDisposable.add(myService.userPunchInExisting(empCode, year, month, dateToday, time, status)
                                                            .subscribeOn(Schedulers.io())
                                                            .observeOn(AndroidSchedulers.mainThread())
                                                            .subscribe(new Consumer< String >() {
                                                                @Override
                                                                public void accept(String s) throws Exception {
                                                                    Log.e("data", s);
                                                                    if (s.equals("\"done\"")) {
                                                                        startTrackerService();
                                                                        punchInBtn.setVisibility(View.INVISIBLE);
                                                                        punchOutBtn.setVisibility(View.VISIBLE);
                                                                    }
                                                                }
                                                            }));
                                                    return;
                                                } else {
                                                    toAdd.add("add new attendance");
                                                }
                                            }
                                            if (toAdd.contains("add new attendance")) {
                                                Log.e("status", "add new attendance");
                                                compositeDisposable.add(myService.userPunchInNew(empCode, year, month, dateToday, time, status)
                                                        .subscribeOn(Schedulers.io())
                                                        .observeOn(AndroidSchedulers.mainThread())
                                                        .subscribe(new Consumer< String >() {
                                                            @Override
                                                            public void accept(String s) throws Exception {
                                                                Log.e("data", s);
                                                                if (s.equals("\"done\"")) {
                                                                    startTrackerService();
                                                                    punchInBtn.setVisibility(View.INVISIBLE);
                                                                    punchOutBtn.setVisibility(View.VISIBLE);
                                                                }
                                                            }
                                                        }));
                                            }

                                        } else {
                                            Log.e("status", "add new attendance.");
                                            compositeDisposable.add(myService.userPunchInNew(empCode, year, month, dateToday, time, status)
                                                    .subscribeOn(Schedulers.io())
                                                    .observeOn(AndroidSchedulers.mainThread())
                                                    .subscribe(new Consumer< String >() {
                                                        @Override
                                                        public void accept(String s) throws Exception {
                                                            Log.e("data", s);
                                                            if (s.equals("\"done\"")) {
                                                                startTrackerService();
                                                                punchInBtn.setVisibility(View.INVISIBLE);
                                                                punchOutBtn.setVisibility(View.VISIBLE);
                                                            }
                                                        }
                                                    }));
                                        }
                                    }
                                }
                            }));

                } else {
                    ActivityCompat.requestPermissions(HomeActivity.this,
                            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                            PERMISSIONS_REQUEST);
                }


            }
        });


        punchOutBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                    final String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
                    final String time = new SimpleDateFormat("HH:mm", Locale.getDefault()).format(new Date());
                    final String year = date.substring(0, 4);
                    final String month = date.substring(5, 7);
                    final String dateToday = date.substring(8, 10);

                    compositeDisposable.add(myService.userStatus(empCode)
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new Consumer< String >() {
                                @Override
                                public void accept(String s) throws Exception {
                                    Log.e("data", s);
                                    if (s.equals("logout")) {
                                        Toast.makeText(HomeActivity.this, s, Toast.LENGTH_SHORT).show();
                                    } else {
                                        JSONObject basicObject = new JSONObject(s);

                                        JSONArray attendanceArray = basicObject.getJSONArray("attendance");
                                        if (attendanceArray.length() > 0) {
                                            for (int i = 0; i < attendanceArray.length(); i++) {
                                                JSONObject attendanceObject = attendanceArray.getJSONObject(i);
                                                String yearName = attendanceObject.getString("year");
                                                String monthName = attendanceObject.getString("month");
                                                String dateName = attendanceObject.getString("date");
                                                boolean loginStatus = attendanceObject.getBoolean("loginStatus");
                                                if (yearName.equals(year) && monthName.equals(month) && dateName.equals(dateToday) && loginStatus) {
                                                    Log.e("status", "add new outTime.");
                                                    compositeDisposable.add(myService.userPunchOut(empCode, year, month, dateToday, time)
                                                            .subscribeOn(Schedulers.io())
                                                            .observeOn(AndroidSchedulers.mainThread())
                                                            .subscribe(new Consumer< String >() {
                                                                @Override
                                                                public void accept(String s) throws Exception {
                                                                    Log.e("data", s);
                                                                    if (s.equals("\"done\"")) {
                                                                        stopTrackerService();
                                                                        punchOutBtn.setVisibility(View.INVISIBLE);
                                                                        punchInBtn.setVisibility(View.VISIBLE);
                                                                    }
                                                                }
                                                            }));
                                                    return;
                                                }
                                            }
                                        }
                                    }
                                }
                            }));

            }
        });

    }

    private void startTrackerService() {
        final String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
        final String year = date.substring(0, 4);
        final String month = date.substring(5, 7);
        final String dateToday = date.substring(8, 10);

        Intent intent = new Intent(this, LiveLocationService.class);
        intent.putExtra("empCode", empCode);
        intent.putExtra("year", year);
        intent.putExtra("month", month);
        intent.putExtra("date", dateToday);
        startService(intent);
    }

    private void stopTrackerService() {
        stopService(new Intent(this, LiveLocationService.class));

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[]
            grantResults) {
        if (requestCode == PERMISSIONS_REQUEST && grantResults.length == 1
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Start the service when the permission is granted
            startTrackerService();
        } else {
            finish();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.logout) {
            sharedPreferences = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
            editor = sharedPreferences.edit();
            editor.remove("myKey");
            editor.remove("myKey1");
            editor.remove("myKey2");
            editor.apply();
            Intent intent = new Intent(HomeActivity.this, MainActivity.class);
            startActivity(intent);
            finish();
        }
        return super.onOptionsItemSelected(item);
    }

}
Nensi Kasundra :

Start service like below:

  Intent intent = new Intent(this, LiveLocationService.class);
  intent.putExtra("empCode", empCode);
  intent.putExtra("year", year);
  intent.putExtra("month", month);
  intent.putExtra("date", dateToday);
  startService(intent);

  ContextCompat.startForegroundService(this, intent)

Stop service like below:

stopService(new Intent(this, LiveLocationService.class));

Service onDestory() method like below:

 @Override
    public void onDestroy() {
        super.onDestroy();
        // Stop location udates
       //hide your notification here
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=216871&siteId=1