I have to track location in background with specific interval of time. When the app minimize and it is not moving it properly hit the location on 10 min but when it moves it hits frequently. How to stop that frequent hitting when it is moving and set the interval at 10 mins of duration. Below is the class which i extend with service. Here I used Timer to hit at 10 min of interval
public class ForgroundService extends Service {
private LocationMonitoringService monitoringService;
private Handler locationHandler;
private Runnable locationThread;
private static final String PACKAGE_NAME =
"com.appynitty.swachbharatabhiyanlibrary.services";
private static final String EXTRA_STARTED_FROM_NOTIFICATION = PACKAGE_NAME +
".started_from_notification";
private static String channelId;
private Handler mHandler = new Handler();
private Timer mTimer = null;
long notify_interval = 1000 * 60 * 10;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// Toast.makeText(this, " MyService Created ", Toast.LENGTH_LONG).show();
Log.d("okh", "onCreate: " +System.currentTimeMillis());
monitoringService = new LocationMonitoringService(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Toast.makeText(this, " MyService Started", Toast.LENGTH_LONG).show();
Log.d("okh", "onCreate: " +System.currentTimeMillis());
Log.d("okh", "onStartCommand: ");
final int currentId = startId;
mTimer = new Timer();
mTimer.schedule(new TimerTaskToGetLocation(), 1,notify_interval);
locationThread = new Runnable() {
public void run() {
// monitoringService.onStartTacking();
}
};
locationHandler = new Handler(Looper.getMainLooper());
locationHandler.post(locationThread);
startLocationForeground();
return Service.START_STICKY;
// return Service.START_NOT_STICKY;
}
@Override
public void onDestroy() {
//Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
locationHandler.removeCallbacks(locationThread);
monitoringService.onStopTracking();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
stopForeground(STOP_FOREGROUND_REMOVE);
}
if(Prefs.getBoolean(AUtils.PREFS.IS_ON_DUTY,false))
{
Intent broadcastIntent = new Intent(this, RestarterBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
}
}
private void startLocationForeground() {
if (Build.VERSION.SDK_INT >= 26) {
String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
? this.createNotificationChannel("my_service", "My Background Service")
: "";
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder((Context) this,
channelId);
Notification notification = notificationBuilder
.setOngoing(true)
.setContentText("Please don't kill the app from background. Thank you!!")
.setSmallIcon(getNotificationIcon(notificationBuilder))
.setPriority(-2)
.setCategory("service")
.build();
startForeground(101, notification);
}
}
@RequiresApi(26)
private String createNotificationChannel(String channelId, String channelName) {
NotificationChannel chan = new NotificationChannel(channelId, (CharSequence)channelName,
NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
service.createNotificationChannel(chan);
return channelId;
}
private int getNotificationIcon(NotificationCompat.Builder notificationBuilder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int color = 0x008000;
notificationBuilder.setColor(color);
return R.drawable.ic_noti_icon;
}
return R.drawable.ic_noti_icon;
}
private class TimerTaskToGetLocation extends TimerTask {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
monitoringService.onStartTacking();
}
});
}
}
}
Below is LocationMonitoring service in which i implements LocationListener & Gps Listener
public class LocationMonitoringService extends BroadcastReceiver implements LocationListener, GpsStatus.Listener {
private static final String TAG = LocationMonitoringService.class.getSimpleName();
private final Context mContext;
private final LocationRepository mLocationRepository;
private final ShareLocationAdapterClass mAdapter;
private final SyncOfflineRepository syncOfflineRepository;
private long updatedTime = 0;
private final List<UserLocationPojo> mUserLocationPojoList;
private final SyncOfflineAttendanceRepository syncOfflineAttendanceRepository;
private Handler mHandler = new Handler();
private Timer mTimer = null;
long notify_interval = 1000 * 60 * 10;
public LocationMonitoringService(final Context context) {
mContext = context;
public void onStartTacking() {
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
//Exception thrown when GPS or Network provider were not available on the user's device.
try {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
criteria.setAltitudeRequired(false);
criteria.setSpeedRequired(true);
criteria.setCostAllowed(false);
criteria.setBearingRequired(false);
//API level 9 and up
criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH);
criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH);
int gpsFreqInDistance =100;
assert locationManager != null;
locationManager.addGpsStatusListener(this);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, AUtils.LOCATION_INTERVAL,
gpsFreqInDistance, this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, AUtils.LOCATION_INTERVAL,
gpsFreqInDistance, this);
} catch (IllegalArgumentException | SecurityException e) {
Log.e(TAG, Objects.requireNonNull(e.getLocalizedMessage()));
Log.d(TAG, "onStartTacking: " + e.getMessage());
Log.d(TAG, "onStartTacking: " + e.getLocalizedMessage());
e.printStackTrace();
} catch (RuntimeException e) {
Log.e(TAG, Objects.requireNonNull(e.getLocalizedMessage()));
Log.d(TAG, "onStartTacking: " + e.getMessage());
e.printStackTrace();
}
}
public void onStopTracking() {
mAdapter.shareLocation();
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(this);
}
/*
* LOCATION CALLBACKS
*/
//to get the location change
@Override
public void onLocationChanged(Location location) {
Log.d("okh ", "onLocationChanged: "+System.currentTimeMillis());
if (location != null) {
Log.d(TAG, String.valueOf(location.getAccuracy()));
if (!AUtils.isNullString(String.valueOf(location.getLatitude())) && !AUtils.isNullString(String.valueOf(location.getLongitude()))) {
Prefs.putString(AUtils.LAT, String.valueOf(location.getLatitude()));
Prefs.putString(AUtils.LONG, String.valueOf(location.getLongitude()));
if (Prefs.getBoolean(AUtils.PREFS.IS_ON_DUTY, false)) {
if (updatedTime == 0) {
updatedTime = System.currentTimeMillis();
Log.d(TAG, "updated Time ==== " + updatedTime);
}
if ((updatedTime + AUtils.LOCATION_INTERVAL_MINUTES) <= System.currentTimeMillis()) {
updatedTime = System.currentTimeMillis();
Log.d(TAG, "updated Time ==== " + updatedTime);
}
mTimer = new Timer();
mTimer.schedule(new TimerTaskToGetLocation(), 5,notify_interval);
// sendLocation();
}
}
} else {
Log.d(TAG, "onLocationChanged: no location found !!");
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged" + provider + "Status" + status);
}
@Override
public void onProviderEnabled(String provider) {
Log.d(TAG, " onProviderEnabled" + provider);
}
@Override
public void onProviderDisabled(String provider) {
Log.d(TAG, " onProviderDisabled" + provider);
}
@Override
public void onGpsStatusChanged(int event) {
}
private void sendLocation() {
Handler handler = new Handler();
Runnable periodicUpdate = new Runnable() {
@Override
public void run() {
// whatever you want to do
// sendLocation();
}
};
handler.post(periodicUpdate);
wl.release();
}
private void scheduleExactAlarm(Context context, AlarmManager systemService) {
Intent i=new Intent(context, LocationMonitoringService.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
systemService.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000 * 60 * 10, pi);
}
public static void cancelAlarm(Context context, AlarmManager alarms) {
Intent i=new Intent(context, GpsTracker.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
alarms.cancel(pi);
}
private class TimerTaskToGetLocation extends TimerTask {
@Override
public void run() {
sendLocation();
}
}
}
Below is the manifiest file in which i comment the background service because on 10 version both foreground and background cant used simultaneously. If used i used to turn on the services manually from settings of mobile.
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<service
android:name=".services.ForgroundService"
android:enabled="true"
android:foregroundServiceType="location" />