In a Splash Activity's onResume(), I start the service this way
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, LocationService.class);
PendingIntent pi = PendingIntent.getService(this, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pi);
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
ystemClock.elapsedRealtime() + 20000, 60000, pi);
and in onStop(), I stop the service this way
stopService(new Intent(this, LocationService.class));
and the Service Class is:
public class LocationService extends Service implements LocationListener {
private LocationManager mgr;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
//get Location details
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10 * 60 * 1000, 50, this);
return START_NOT_STICKY;
}
private void dumpLocation(Location l) {
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onDestroy() {
super.onDestroy();
mgr.removeUpdates(this);
}
}
Once I stop the service in Splash Activity's onStop(), onDestroy() of the LocationService is triggered(which means the service is stopped?), but still after a minute as specified in the AlarmManager the service runs.
Store the pending intent for the alarm in a variable. Call cancel on it when the service ends.
Related
I have a location service which sends location to my server after every 3 minutes.This location service is started from Activity by click of a button.I want this service stops automatically after 6 hours from started time.Here is my service file.Service is starting normally and i am able to stop it by click of a button in activity.But i want to stop it automatically after 6 hours even app is minimized.Any help would be highly appreciated.
public class LocationService extends Service {
private LocationListener listener;
private LocationManager locationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.i("location:","location is "+location.getLongitude()+" "+location.getLatitude());
LocationApi.sendGpsLocation(getApplicationContext(),location.getLongitude(),location.getLatitude());
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String provider) {
Log.e("disabled provider is :","location is "+provider);
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
// locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
if (ContextCompat.checkSelfPermission(DashboardActivity.activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ) {
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,0,listener);
}
}
/* #Override
public final void stopSelf(){
}*/
#Override
public boolean onUnbind(Intent intent) {
LocationApi.stopLocation(getApplicationContext());
//super.onDestroy();
if (locationManager != null) {
//noinspection MissingPermission
locationManager.removeUpdates(listener);
}
return super.onUnbind(intent);
}
#Override
public void onDestroy() {
LocationApi.stopLocation(getApplicationContext());
super.onDestroy();
if(locationManager != null){
//noinspection MissingPermission
locationManager.removeUpdates(listener);
}
}
}
and i start this service in Activity by below code.
Intent i = new Intent(getApplicationContext(), LocationService.class);
if (Build.VERSION.SDK_INT >= 26) {
startForegroundService(i);
}else{
startService(i);
}
You can add a counter to your 3 min timer and count up til you reach 120 and than stop Locationupdates and shutdown the service.
You could schedule an alarm via AlarmManager when the service gets started - this will be an Intent you receive. When receiving you can stop your running service.
Try this code:
public class LocationService extends Service {
public static final String ACTION_STOP = "com.mycompany.myapp.SERVICE_STOP";
/*private static final long UPDATE_INTERVAL = 3 * 60 * 1000;
private static final long STOP_INTERVAL = 6 * 3600 * 1000;*/
private static final long UPDATE_INTERVAL = 3 * 1000;
private static final long STOP_INTERVAL = 20 * 1000;
private LocationListener listener;
private LocationManager locationManager;
private BroadcastReceiver receiver;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent i, int flags, int startId){
if (Build.VERSION.SDK_INT >= 26){
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel("Location",
"Location", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
Notification notif = new NotificationCompat.Builder(this, "Location")
.setContentTitle("Location service")
.build();
startForeground(3001, notif);
}
return START_STICKY;
}
#Override
public void onCreate() {
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.i("location:","location is "+location.getLongitude()+" "+location.getLatitude());
LocationApi.sendGpsLocation(getApplicationContext(),location.getLongitude(),location.getLatitude());
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String provider) {
Log.e("disabled provider is :","location is "+provider);
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ) {
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,UPDATE_INTERVAL,0,listener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,UPDATE_INTERVAL,0f,listener);
}
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(ACTION_STOP);
PendingIntent pi = PendingIntent.getBroadcast(this, 100, i, PendingIntent.FLAG_UPDATE_CURRENT);
am.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + STOP_INTERVAL, pi);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
stopSelf();
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_STOP);
registerReceiver(receiver, filter);
}
#Override
public void onDestroy() {
Log.i("location:","stopping updates");
unregisterReceiver(receiver);
LocationApi.stopLocation(getApplicationContext());
super.onDestroy();
if(locationManager != null){
locationManager.removeUpdates(listener);
}
}
}
Explanation: use AlarmManager.set() to schedule a broadcast after certain time (STOP_INTERVAL). To receive the broadcast, register a receiver in onCreate(), and unregister it in onDestroy().
I want to call LocationListener Service from BroadcastReceiver, So I can get current location of device and call my API on server after every 5 minutes in backend, even if application is not running.
So, I have created class with BroadcastReceiver, Which will call my LocationListener Service. In this service, I want to get location and save it in db.
The problem is, I am not able to call LocationListener Service from BroadcastReceiver. BroadcastReceiver running well.
Code,
Run BroadcastReceiver in AlarmManager.
public void LocationClicked(View view){
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int interval = 10000;
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
Toast.makeText(this, "Alarm Set", Toast.LENGTH_SHORT).show();
}
BroadcastReceiver class file,
public class LocationReceiver extends BroadcastReceiver {
private static int count = 0;
#Override
public void onReceive(Context context, Intent intent) {
count++;
Toast.makeText(context, "I'm running " + count, Toast.LENGTH_SHORT).show();
Intent myIntent = new Intent(context, LocationUpdateService.class);
context.startService(myIntent);
}
}
"I'm running " is coming.
LocationListerner Service file,
public class LocationUpdateService extends Service implements LocationListener {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onLocationChanged(Location location) {
double ss = location.getLatitude();
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
}
Here what do I need to change to make it work ?
And tell me If I am doing it in wrong way.
I'm new to services and BroadcastReceiver so maybe this question is newbie, but I didn't found the solution for my question after a long search on the web.
I need to run a CountDownTimer inside service, so the time keep moving even the application was finished.
In my code I based on THIS EXAMPLE.
My code works fine, but after the application is finished the CountDownTimer stopped(The service doesn't destroyed, just the timer).
I tried to implement it in different ways, but nothing works for me.
This is the part of my code that relevant:
AlarmReciver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent background = new Intent(context, BackgroundService.class);
Bundle bundle = intent.getExtras();
background.putExtra("time", bundle.getInt("time"));
context.startService(background);
}
}
BackgroundService :
public class BackgroundService extends Service {
private final static String TAG = "BroadcastService";
private CountDownTimer cdt = null;
private Bundle bundle;
private boolean isRunning;
private Context context;
private int timeInMili;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
this.context = this;
this.isRunning = false;
}
#Override
public void onDestroy() {
//cdt.cancel();
Log.i(TAG, "Timer cancelled");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
bundle = intent.getExtras();
timeInMili = bundle.getInt("time");
if(!this.isRunning) {
this.isRunning = true;
}
cdt = new CountDownTimer(timeInMili, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
Log.i(TAG, "Timer finished");
stopSelf();
}
};
cdt.start();
return START_STICKY;
}
}
MainActivity (extends FragmentActivity):
public void StartBackgroundAlarm(int timeInMili)
{
Intent alarm = new Intent(this, AlarmReceiver.class);
alarm.putExtra("time", timeInMili);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarm, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), pendingIntent);
}
MANIFEST :
<service android:enabled="true" android:name= "com.MES.yo.servicemanager.BackgroundService" />
<receiver android:name="com.MES.yo.servicemanager.AlarmReceiver"></receiver>
I have a Bound service which collects locations for 3 minutes every 15 minutes. I start a CountDownTimer once the Service is connected in onServiceConnected of ServiceConnection.
I receive all the Timer callbacks (onFinish) (onTick) perfectly as far the Activity which bindService is visible.
When Device is locked I do not receive any updates from the timer.
MyLocationService
public class MyLocationService extends Service implements MyTimerListener{
private IBinder mBinder = new MyLocationBinder();
public void onCreate() {
locationManager = new MyLocationManager(this);
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
public class MyLocationBinder extends Binder
{
public MyLocationService getService()
{
return MyLocationService.this;
}
}
public void startFetchingLocations()
{
if(locationManager != null){
locationManager.startFetchingLocations();
if(publishPeriodCountDownTimer != null) {
publishPeriodCountDownTimer.cancel();
publishPeriodCountDownTimer = null;
}
publishPeriodCountDownTimer = new MyCountTimer(gpsPublishPeriod * 60 * 1000, 1000, MyLocationService.this);
publishPeriodCountDownTimer.start();
}
}
#Override
public void onTimeFinished() {
//Start fetching locations
locationManager.startFetchingLocations(); //Start 3 min CountdownTimer
}
#Override
public void onTick() {
}
public void onAllLocationsRecieved(ArrayList<Location> locations)
{
//Do stuff on Locations
locationManager.stopFetchingGPS(); //Stops 3 min countdownTimer
}
}
MyActivty
public class MyActivity
{
#Override
protected void onStart() {
super.onStart();
btnStop.setVisibility(View.VISIBLE);
MyNoificationManager.cancelAllNotifications();
if (!isLocationServiceBound) {
Intent locServiceIntent = new Intent(this, MyLocationService.class);
bindService(locServiceIntent, locationServiceConnection, Context.BIND_AUTO_CREATE);
}
}
private ServiceConnection locationServiceConnection = new ServiceConnection(){
#Override
public void onServiceDisconnected(ComponentName name) {
isLocationServiceBound = false;
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyLocationBinder locationBinder = (MyLocationBinder) service;
locationService = locationBinder.getService();
isLocationServiceBound = true;
locationService.startFetchingLocations();
}
};
}
It works as expected when the Activity is visible. The timer doesn't provide any onTick() or onTimeFinished() callbacks when the device is locked.
What could be the problem here ?
The CountDownTimer will not work when the phone goes to sleep mode. This is by design and it's to save battery life.
Alternately you can use android.app.AlarmManager instead to achieve your goal. Following is the sample code how to do that. Set the alaram like below
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, MyLocationService.class);
intent.putExtra("need_to_fetch_loc", true);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, gpsPublishPeriod * 60 * 1000, alarmIntent);
Add the following method to your MyLocationService class
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(locationManager!= null && intent.getBooleanExtra("need_to_fetch_loc", false))
{
locationManager.startFetchingLocations();
}
return super.onStartCommand(intent, flags, startId);
}
My app scenario is that I want to track employees location. I have a broadcastreceiver which listens device boot broadcast and register an alarm manager. When alarm manager ticks, it registers two location listeners, one to listen to gps and other for network. I want that when I got first location update in onLocationChange() method, save location and unregister that location listener so that when alarm manager ticks again, it does not get duplicate. To unregister, I have location listeners as static objects to access them in onLocationChange(). But I have found that it is NOT removing location listener. Here is my code example:
public class BootTimeServiceActivator extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Calendar calendar = Calendar.getInstance();
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent mIntent = new Intent(context, MyBroadCastReceiver.class);
PendingIntent mPendingIntent = PendingIntent.getBroadcast(context, 0, mIntent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 20 * 60 * 1000, mPendingIntent);
}
}
//..........
public class MyBroadCastReceiver extends BroadcastReceiver{
public static LocationManager locationManager;
public static MyLocationListener networkLocationListener;
public static MyLocationListener gpsLocationListener;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(context, "Alarm has been called...", Toast.LENGTH_SHORT).show();
initLocationListeners(context);
registerLocationListeners();
}
public void initLocationListeners(Context context) {
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
networkLocationListener = new MyLocationListener(context);
gpsLocationListener = new MyLocationListener(context);
}
public void registerLocationListeners() {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0, gpsLocationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100, 0, gpsLocationListener);
}
}
\\.....
public class MyLocationListener implements LocationListener {
Context context;
public MyLocationListener(Context context) {
this.context = context;
}
#Override
public void onLocationChanged(Location location) {
if(location != null) {
SDCardService sdService = new SDCardService(context);
try {
sdService.logToDB(location);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("provider",location.getProvider());
if(location.getProvider().equals(LocationManager.GPS_PROVIDER)) {
MyBroadCastReceiver.locationManager.removeUpdates(MyBroadCastReceiver.gpsLocationListener);
}
else if(location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
MyBroadCastReceiver.locationManager.removeUpdates(MyBroadCastReceiver.networkLocationListener);
}
}
}
Can anyone guide me where I am wrong?
Try this..
lmNetwork.removeUpdates(networkLocationListener);
lmGps.removeUpdates(gpsLocationListener);
Ahh... I have a typo mistake. Actually in MyBroadCastREciever class I was registering gpsListener twice as:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
100, 0,
gpsLocationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
100, 0,
networkLocationListener); //previously was gpsLocationListener again. Wrong.
that's y network listener was not being removed.
you can do it this way with an insider class and remove the listener onPause() :
#Override
protected void onPause() {
super.onPause();
GPSlocationManager.removeUpdates(GPSLocationListener);
CellLOcationManager.removeUpdates(NetworkLocationListener);
}
private void SetLocationManager() {
GPSlocationManager =(LocationManager)getSystemService(Context.LOCATION_SERVICE);
CellLOcationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
NetworkLocationListener = new MyNetworkLocationListener();
GPSLocationListener = new MyGPSLocationListener();
GPSlocationManager.requestLocationUpdates("gps", 5000, 1, GPSLocationListener);
CellLOcationManager.requestLocationUpdates("network", 10000, 1, NetworkLocationListener);
}
private class MyNetworkLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
}