简体   繁体   English

后台服务不会停止 Android

[英]Background Service not Stopping Android

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.我有后台服务,可以从用户设备捕获位置,但是当我使用来自花药活动的 stopService 方法停止它时,它不会停止,因此应用程序崩溃,因为应用程序无法将经纬度发送到服务器。

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.注意 - 我有一个改造后的请求,当位置不为空时,当我点击主活动中的停止服务按钮时,通知从设备中消失,但实际上服务并没有停止,位置是登录 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.这是 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);
    }

}

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:服务 onDestory() 方法如下:

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

your service stops working but still getting location callbacks, means you still have registered callback in client.requestLocationUpdates() .您的服务停止工作但仍然收到位置回调,这意味着您仍然在client.requestLocationUpdates()注册了回调。

while stopping the service also remove the same callback from LocationProvderClient.在停止服务的同时,也从 LocationProvderClient 中删除相同的回调。 For that make global object of LocationCallback() remove that same object when need to stop.为此,在需要停止时,让 LocationCallback() 的全局对象删除相同的对象。 as:作为:

LocationServices.getFusedLocationProviderClient(this).removeLocationUpdates(locationCallback);

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM