1

This is not duplicate since my problem is a bit difference.

I'm trying to send location every 20 minutes when app is closed but when I use time interval it won't really work very well, so I've tried to use Handler to get Data every 20 Minutes. also the code reference was base on an answer from another question which I don't remember, I just changed some parts.

This build was base on some answers, which I was trying for my homework, when I tried to use minTimeInterver app was ignoring location changes somehow, and this is why i used handler. so the whole idea is to send locations every 20 min for once.

Here's the Activity Setup :

    mYourService = new MyService();
    mServiceIntent = new Intent(this, mYourService.getClass());
    if (!isMyServiceRunning(mYourService.getClass())) {
        startService(mServiceIntent);
    }

Service :

public class MyService extends Service {

    private static final String TAG = "MyServiceTTT";
    public int counter = 0;
    private LocationManager mLocationManager = null;
    private static int LOCATION_INTERVAL = 900000;
    private static ApiClient mApi;
    private AppDatabase appDatabase;
    private static final float LOCATION_DISTANCE = 10f;
    private ArrayList<Map> maps;

    private class LocationListener implements android.location.LocationListener {
        Location mLastLocation;

        public LocationListener(String provider) {
            Log.e(TAG, "LocationListener " + provider);
            mLastLocation = new Location(provider);
        }

        @Override
        public void onLocationChanged(Location location) {
            Log.e(TAG, "onLocationChanged: " + location.getLongitude() + " - " + location.getLatitude());

            String status = AppPref.getInstance().getUserStatus();

            if (AppPref.getInstance().getShiftService()) {
                switch (status) {
                    case "true":
                        Log.e(TAG, "1");
                        TimeZone timeZone = TimeZone.getTimeZone("Asia/Tehran");
                        Calendar cal = Calendar.getInstance(timeZone);
                        cal.add(Calendar.DATE, 0);

                        SimpleDateFormat format1 = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH);

                        String formatted = format1.format(cal.getTime());

                        String star = AppPref.getInstance().getUserStartAt();
                        String en = AppPref.getInstance().getUserEndAt();
                        try {

                            Log.e(TAG, "2");
                            if (TimeConditioner.isTimeBetweenTwoTime(star, en, formatted)) {
                                Log.e(TAG, "3");
                                OnlineCordinateRequest onlineCordinateRequest = new OnlineCordinateRequest();
                                onlineCordinateRequest.user_id = Integer.parseInt(AppPref.getInstance().getUserID());
                                onlineCordinateRequest.lat = location.getLatitude();
                                onlineCordinateRequest.lng = location.getLongitude();
                                onlineCordinateRequest.methodz = "online";
                                onlineCordinateRequest.status = "none";
                                getApi().cordinate(onlineCordinateRequest).enqueue(new Callback<GeneralCallBack>() {
                                    @Override
                                    public void onResponse(Call<GeneralCallBack> call, Response<GeneralCallBack> response) {
                                        Log.i(TAG, "Done");
                                    }

                                    @Override
                                    public void onFailure(Call<GeneralCallBack> call, Throwable t) {
                                        Log.i(TAG, "Failed");
                                        createMap(Integer.parseInt(AppPref.getInstance().getUserID()), location.getLatitude(), location.getLongitude());

                                    }
                                });
                            } else {
                                Log.i(TAG, "Failed");
                                Log.e(TAG, "4");
                            }
                        } catch (ParseException e) {
                            Log.i(TAG, "Failed");
                            Log.e(TAG, "5");
                        }

                        break;
                    case "false":
                        Log.i(TAG, "Que False");
                        Log.e(TAG, "6");
                        break;
                    default:
                        Log.i(TAG, "Que Default");
                        Log.e(TAG, "7");
                }
            } else {
                Log.e(TAG, "8");
                OnlineCordinateRequest onlineCordinateRequest = new OnlineCordinateRequest();
                onlineCordinateRequest.user_id = Integer.parseInt(AppPref.getInstance().getUserID());
                onlineCordinateRequest.lat = location.getLatitude();
                onlineCordinateRequest.lng = location.getLongitude();
                onlineCordinateRequest.methodz = "online";
                onlineCordinateRequest.status = "none";
                getApi().cordinate(onlineCordinateRequest).enqueue(new Callback<GeneralCallBack>() {
                    @Override
                    public void onResponse(Call<GeneralCallBack> call, Response<GeneralCallBack> response) {
                        Log.i(TAG, "Done");
                        Log.e(TAG, "9");
                    }

                    @Override
                    public void onFailure(Call<GeneralCallBack> call, Throwable t) {
                        Log.i(TAG, "Failed");
                        Log.e(TAG, "10");
                        createMap(Integer.parseInt(AppPref.getInstance().getUserID()), location.getLatitude(), location.getLongitude());

                    }
                });
            }
            Log.e(TAG, "11");
            mLastLocation.set(location);
        }

        @Override
        public void onProviderDisabled(String provider) {
            Log.e(TAG, "onProviderDisabled: " + provider);
        }

        @Override
        public void onProviderEnabled(String provider) {
            Log.e(TAG, "onProviderEnabled: " + provider);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.e(TAG, "onStatusChanged: " + provider);
        }
    }

    private void createMap(int user_id, double lat, double lng) {

        TimeZone timeZone = TimeZone.getTimeZone("Asia/Tehran");
        Calendar cal = Calendar.getInstance(timeZone);
        cal.add(Calendar.DATE, 0);

        SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd k:m:s", Locale.ENGLISH);
        String formatted = format1.format(cal.getTime());

        new MyService.CreateMapLogAsyncTask().execute(new Map(0, user_id, lat, lng, "offline", "opened", formatted));
    }

    private class CreateMapLogAsyncTask extends AsyncTask<Map, Void, Void> {

        @Override
        protected Void doInBackground(Map... maps) {

            long id = appDatabase.getMapDAO().addMap(maps[0]);

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            Log.i(TAG, "Added to DB");
        }
    }

    public ApiClient getApi() {
        if (mApi == null) {
            mApi = ApiService.getClient().create(ApiClient.class);
        }
        return mApi;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
            Log.e("MyServiceTTT", "Testing Data111 : ");
        }
//            startMyOwnForeground();
        else {
            Log.e("MyServiceTTT", "Testing Data222 : ");
        }
//            startForeground(1, new Notification());
//        startTimer();
    }

    private void initializeLocationManager() {
        Log.e(TAG, "initializeLocationManager - LOCATION_INTERVAL: " + LOCATION_INTERVAL + " LOCATION_DISTANCE: " + LOCATION_DISTANCE);
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        }
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private void startMyOwnForeground() {

    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "LOCATION_INTERVAL");
        super.onStartCommand(intent, flags, startId);
        appDatabase = AppDatabase.getInstance(getApplicationContext());
        startTimer();
        return START_STICKY;
    }

    MyService.LocationListener[] mLocationListeners = new MyService.LocationListener[]{
            new MyService.LocationListener(LocationManager.PASSIVE_PROVIDER)
    };

    @Override
    public void onDestroy() {
        super.onDestroy();

        Intent broadcastIntent = new Intent();
        broadcastIntent.setAction("restartservice");
        broadcastIntent.setClass(this, Restarter.class);
        this.sendBroadcast(broadcastIntent);
        if (mLocationManager != null) {
            for (int i = 0; i < mLocationListeners.length; i++) {
                try {
                    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        return;
                    }
                    mLocationManager.removeUpdates(mLocationListeners[i]);
                } catch (Exception ex) {
                    Log.i(TAG, "fail to remove location listener, ignore", ex);
                }
            }
        }
    }

    final Handler updateHandler = new Handler(Looper.getMainLooper());

    public void startTimer() {
        int timerTime = Integer.parseInt(AppPref.getInstance().getIntervalMiliSeconds()) * 60000;
        LOCATION_INTERVAL = timerTime;
        Log.i(TAG, String.valueOf(timerTime));
        Runnable runnable = new Runnable() {
            public void run() {

                initializeLocationManager();

                try {
                    mLocationManager.requestLocationUpdates(
                            LocationManager.PASSIVE_PROVIDER,
                            LOCATION_INTERVAL,
                            LOCATION_DISTANCE,
                            mLocationListeners[0]
                    );

                } catch (java.lang.SecurityException ex) {
                    Log.i(TAG, "fail to request location update, ignore", ex);
                } catch (IllegalArgumentException ex) {
                    Log.d(TAG, "network provider does not exist, " + ex.getMessage());
                }
                updateHandler.postDelayed(this, timerTime); // determines the execution interval
            }
        };
        updateHandler.post(runnable);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
Twisha Kotecha
  • 1,082
  • 1
  • 4
  • 18
Atlas-Pio
  • 1,063
  • 11
  • 26
  • You should use `AlarmManager` rather than thread timer https://developer.android.com/training/scheduling/alarms#java – The_ehT Dec 11 '19 at 06:28
  • @The_ehT can u please explain why? i got lowest memory reserve when i used thread timer. – Atlas-Pio Dec 11 '19 at 06:32
  • @The_ehT also Thread timer is doing the job after all, my problem is with sending every second. – Atlas-Pio Dec 11 '19 at 06:34
  • You said 20 min interval. Sending every second is very bad idea. Yes Thread timer has low overhead. But it actually depends on use case. Look here for more info https://stackoverflow.com/a/26740872/1517029 – The_ehT Dec 11 '19 at 06:43
  • @The_ehT no i said app is sending every seconds but i set it to 20 min. about timer i get it now. can i register broadcast receiver in my service? i'm using active service on close app, so when someone close app this service will start again. – Atlas-Pio Dec 11 '19 at 07:00
  • Yes you can register broadcast receiver. – The_ehT Dec 11 '19 at 07:09

1 Answers1

0

Implementing JobService is the best choice for that.You can modify it according to your requirement.For more info goto the official site

AkashToSky
  • 107
  • 1
  • 11
  • JobService is using api 21 i'm developing at 15. – Atlas-Pio Dec 11 '19 at 06:55
  • Then you should use firebase dispatcher for that. – AkashToSky Dec 11 '19 at 07:08
  • You can try WorkManager .(Reference : https://www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwiV5q-Chq3mAhVVDCsKHdTSCIIYABAAGgJzZg&ohost=www.google.com&cid=CAESQeD2qH6FeUvqKWlPIdi0rWT-GENsbukD-Ib8f_2GSLnHmBbv34GHJCihKpAIzfdZwx3-vHwa39wdfUauxYjTU6Sd&sig=AOD64_36TuVZOGIMi_wuEi2VmbKn5h9PVA&q=&ved=2ahUKEwj_6amChq3mAhX1wzgGHb94AMAQ0Qx6BAgREAE&adurl= – SIVAKUMAR.J Dec 11 '19 at 07:14
  • Workmanager references :https://developer.android.com/topic/libraries/architecture/workmanager – SIVAKUMAR.J Dec 11 '19 at 07:16