Reputation: 109
I want to run a Foreground Service
whether the app is closed or open for, lets say, 10 seconds. After those 10 seconds have passed, the Foreground Service
should be destroyed and be called again after 5 minutes. The Foreground Service
I have finds the user's location and then saves it to an SQLite
database. So basically I want to store new coordinates once, every 5 minutes, so that I can improve battery consumption.
My Service Class:
public class LocationService extends Service{
private final static int UPDATE_TIME = 10000;
private final static int UPDATE_DISTANCE = 0;
private LocationListener locationListener;
private LocationManager locationManager;
private PowerManager.WakeLock mWakeLock;
private String latitude, longitude;
private DatabaseHelper myDb;
@Override
public void onCreate() {
super.onCreate();
myDb = new DatabaseHelper(this);
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
createWakeLock(); //Creates a wakelock
createNotification(); //Creates a notification if SDK version is > 26
}
@SuppressLint("MissingPermission")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mWakeLock.acquire(10*60*500L /*5 minutes*/);
locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.d("Location", "Updated");
getCoordinates(location); //Gets coordinates
insertCoordinates(latitude, longitude); //Sends coordinates to SQLite database
sendDataToMainActivity(latitude, longitude); //Sends coordinates to MainActivity
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, UPDATE_TIME, UPDATE_DISTANCE, locationListener);
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("Service", "Destroyed");
if(locationManager != null)
locationManager.removeUpdates(locationListener);
mWakeLock.release();
}
private void createWakeLock() {
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
if(pm != null)
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "myApp:myWakeLock");
}
private void createNotification() {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Service")
.setContentText("Coordinates Location Running")
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
}
private void getCoordinates(Location location) {
this.latitude = String.valueOf(location.getLatitude());
this.longitude = String.valueOf(location.getLongitude());
}
private void insertCoordinates(String latitude, String longitude) {
boolean inserted = myDb.insertData(latitude, longitude); //Insert coordinates
//Check if insertion is completed
if(inserted)
Toast.makeText(LocationService.this, "Coordinates Inserted", Toast.LENGTH_SHORT).show();
else
Toast.makeText(LocationService.this, "Coordinates Not Inserted", Toast.LENGTH_SHORT).show();
}
private void sendDataToMainActivity(String latitude, String longitude) {
Intent i = new Intent("location_update");
i.putExtra("latitude", latitude);
i.putExtra("longitude",longitude);
sendBroadcast(i);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
Upvotes: 2
Views: 3636
Reputation: 1
"Fused Location Api" may not work in background due to power management restrictions. You should use Alarm Manager, but there are some limitations in latest android versions. More about DOZE here
AlarmManager alarm =
(AlarmManager)getSystemService(Context.ALARM_SERVICE);
if (alarm == null) return; // for instant apps
Intent intent = new Intent(this, MyBroadcastReceiver.class)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerInMillis,
PendingIntent.getBroadcast(this, intent, PendingIntent.FLAG_UPDATE_CURRENT));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AlarmManager.AlarmClockInfo ac=
new AlarmManager.AlarmClockInfo(triggerInMillis, null);
alarm.setAlarmClock(ac, PendingIntent.getBroadcast(this, intent, PendingIntent.FLAG_UPDATE_CURRENT));
} else {
alarm.setExact(AlarmManager.RTC_WAKEUP, triggerInMillis,
PendingIntent.getBroadcast(this, intent, PendingIntent.FLAG_UPDATE_CURRENT));
}
Upvotes: 0
Reputation: 2511
You can use Alarm Manager to set an exact alarm, start service in Alarm's on receive function run the foreground service for 5 minutes than set next alarm
Upvotes: 0
Reputation: 3665
Use Fused Location Api to request location updates,which will trigger a pending intent(Let's say starts an intent service) in the specified repeat interval(Give 5 minutes).So Fused Location Api reads the location every 5 minutes and send it to a intent service,from where you can do your processing.
Please refere this for more details.
Upvotes: 2