My app is a tracker app, that uses GPS. At every 15 minutes, it finds current location of user. For this, I had used AlarmManager. I am getting The current location through a background service, which is scheduled to run at every 15 minutes. This service will be started by the broadcast receiver upon alarm. But, the problem is alarm fires up before time, i.e. once service started and finished its work, service was supposed to be called after 15 minutes. But, it is getting called at interval of 2-3 minutes.
Activity code
AlarmManager AlmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Sender = PendingIntent.getBroadcast(GpsTrackActivity.this, 0,
AlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlmMgr.setRepeating(AlarmManager.RTC_WAKEUP, 0, 15 * 60 * 1000,
Sender);
BroadcastReceiver
public class StartServiceReceiver extends BroadcastReceiver
{
private static final String TAG = "StartServiceReceiver";
#Override
public void onReceive(Context context, Intent intent)
{
Intent serviceIntent = new Intent(context, MyLocationService.class);
context.startService(serviceIntent);
Log.v(TAG, "onReceive called");
}
}
Service Class
public class MyLocationService extends Service implements
OnLocationReceivedListener {
private LocationManager manager;
private Location location = null;
PowerManager powerManager;
private WakeLock wakeLock;
private String city, time, udid;
private String country;
GPSLocationListener mGPSLocationListener;
NetworkLocationListener mNetworkLocationListener;
private static final int MAX_ATTEMPTS = 250;
private static String TAG = "MyLocationService";
LocTimerTask mTimerTask;
int mSattelites;
Timer myLocTimer;
int i = 0;
boolean isGPS;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand called");
getCurrentLocation();
time = getCurrentTime();
udid = getDeviceId();
return 1;
}
#Override
public void onCreate() {
Log.v(TAG, "onCreate called");
powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"mywakelock");
mGPSLocationListener = new GPSLocationListener();
mNetworkLocationListener = new NetworkLocationListener();
wakeLock.acquire();
super.onCreate();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
public String getCurrentTime() {
String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
Locale.getDefault()).format(new Date());
return currentTime;
}
public String getDeviceId() {
TelephonyManager tm = (TelephonyManager) MyLocationService.this
.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getDeviceId();
}
public void getCurrentLocation() {
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
manager.addGpsStatusListener(mGPSStatusListener);
mTimerTask = new LocTimerTask(LocationManager.GPS_PROVIDER);
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.v(TAG, "GPS ENABLED");
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000L,
50.0f, mGPSLocationListener);
} else {
turnGPSOn();
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000L,
50.0f, mGPSLocationListener);
}
myLocTimer = new Timer("LocationRunner", true);
myLocTimer.schedule(mTimerTask, 0, 1000);
}
public String getLong(Location loc) {
String longi = null;
if (loc != null) {
longi = Double.toString(loc.getLongitude());
}
return longi;
}
public String getLat(Location loc) {
String lat = null;
if (loc != null) {
lat = Double.toString(loc.getLatitude());
}
return lat;
}
public class GPSLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location argLocation) {
location = argLocation;
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
class LocTimerTask extends TimerTask {
String provider;
public LocTimerTask(String provider) {
this.provider = provider;
}
final Handler mHandler = new Handler(Looper.getMainLooper());
Runnable r = new Runnable() {
#Override
public void run() {
i++;
Log.v(TAG, "Timer Task run " + i);
location = manager.getLastKnownLocation(provider);
if (location != null) {
Log.v(TAG, "in timer task run in if location not null");
isGPS = true;
onLocationReceived(location);
myLocTimer.cancel();
myLocTimer.purge();
mTimerTask.cancel();
return;
} else {
Log.v(TAG, "in timer task run in else location null");
isGPS = false;
if (location == null && i == MAX_ATTEMPTS) {
Log.v(TAG, "if 1 max attempts done");
turnGPSOff();
location = manager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
Log.v(TAG,
"if 1 max attempts done Location from network not null");
Log.v(TAG,
"if 1 max attempts done Location from network not null coordinates not null");
onLocationReceived(location);
myLocTimer.cancel();
myLocTimer.purge();
mTimerTask.cancel();
i = 0;
return;
} else {
i = 0;
return;
}
} else {
return;
}
}
}
};
public void run() {
mHandler.post(r);
}
}
private GpsStatus.Listener mGPSStatusListener = new GpsStatus.Listener() {
#Override
public synchronized void onGpsStatusChanged(int event) {
switch (event) {
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
Log.v(TAG, "GPS SAtellitestatus");
GpsStatus status = manager.getGpsStatus(null);
mSattelites = 0;
Iterable<GpsSatellite> list = status.getSatellites();
for (GpsSatellite satellite : list) {
if (satellite.usedInFix()) {
mSattelites++;
}
}
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
Toast.makeText(getApplicationContext(), "Got First Fix",
Toast.LENGTH_LONG).show();
break;
case GpsStatus.GPS_EVENT_STARTED:
Toast.makeText(getApplicationContext(), "GPS Event Started",
Toast.LENGTH_LONG).show();
break;
case GpsStatus.GPS_EVENT_STOPPED:
Toast.makeText(getApplicationContext(), "GPS Event Stopped",
Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
};
public void onDestroy() {
super.onDestroy();
if (myLocTimer != null) {
myLocTimer.cancel();
myLocTimer.purge();
}
if (mTimerTask != null) {
if (mTimerTask.r != null) {
mTimerTask.mHandler.removeCallbacks(mTimerTask.r);
}
}
if (manager != null) {
if (mGPSLocationListener != null) {
manager.removeUpdates(mGPSLocationListener);
}
if (mNetworkLocationListener != null) {
manager.removeUpdates(mNetworkLocationListener);
}
if (mGPSStatusListener != null) {
manager.removeGpsStatusListener(mGPSStatusListener);
}
}
Toast.makeText(getApplicationContext(), "Service onDestroy called",
Toast.LENGTH_LONG).show();
}
#Override
public void onLocationReceived(Location mLoc) {
String lat = getLat(mLoc);
String lon = getLong(mLoc);
if (NetworkConnection.isOnline(getApplicationContext())) {
new SendDataAsynctask(lat, lon, "", time, udid, city, country,
wakeLock).execute();
Log.v(TAG, "net available");
} else {
Toast.makeText(getApplicationContext(), "Network unavailable",
Toast.LENGTH_LONG).show();
Log.v(TAG, "net unavailable");
}
}
}
I have a doubt, does AlarmManager gets affected by Timer or TimerTask. I am asking this because within my service I had used Timer, since it takes time for GPS to find first fix.
Related
I have created background service to get user location periodically and send it to server like this :`
public class SyncDataToServerService extends Service {
private static final String TAG = "SyncDataToServerService";
private ServerCall serverCall;
private SharedPreferences tempPref2;
private Timer timer;
LocationManager locationManager;
UtilityClass utilityClass;
PowerManager.WakeLock wakeLock;
PowerManager powerManager;
#Override
public void onCreate() {
Log.e(TAG, "onCreate");
serverCall = new ServerCall(this);
timer = new Timer();
utilityClass = new UtilityClass(this);
tempPref2 = getSharedPreferences(getString(R.string.temp_pref_name_2), Context.MODE_PRIVATE);
}
#SuppressLint("MissingPermission")
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.e(TAG, "onStartCommand");
powerManager = (PowerManager) getSystemService(POWER_SERVICE);
if (powerManager != null)
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyApp::MyWakelockTag");
wakeLock.acquire();
//initialize and start Location service
startLocation();
//initialize and start the TimerTask's job
startTimer();
return START_STICKY;
}
#SuppressLint("MissingPermission")
private void startLocation() {
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (locationManager != null)
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
10, new MyLocationListener());
if (locationManager != null)
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0,
10, new MyLocationListener());
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
if (locationManager != null)
locationManager.removeUpdates(new MyLocationListener());
super.onDestroy();
}
private void syncPath(Location mLocation) {
Log.w(TAG, "Location: " + mLocation + " Latitude: " + mLocation.getLatitude() + " & Longitude: "
+ mLocation.getLongitude());
if (tempPref2.getString(getString(R.string.attendance_key), "").equalsIgnoreCase("present")) {
serverCall.sendEmpPath(mLocation);
}
}
private void startTimer() {
TimerTask timerTask = new TimerTask() {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void run() {
if (utilityClass.isInternetConnected()) {
if (serverCall != null) {
if (serverCall.requestQ.size() > 0)
Log.e(TAG, "Request queue size ==" + serverCall.requestQ.size());
serverCall.syncData();
}
}
}
};
//schedule the timer, to wake up every 1 second
timer.schedule(timerTask, 1000, 1000);
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
Intent intent1 = new Intent("com.example.mc_project");
intent1.putExtra("location", location);
sendBroadcast(intent1);
if (location.getAccuracy() < 25)
syncPath(location);
wakeLock.release();
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
}
}`
everything working fine but when i lock my phone it stop to send location updates. i have read that it is because of system sleep and have to use wake lock but it also not working.And when i unlock phone it suppose to start to send location updates but this also not happening.My service do not stop,it always in running state.Please help where i am doing wrong or missing something.
you should use foreground service and put location update code inside it .
os stops background service any time power is off
My service is using the ActivityRecognition API and a LocationListener to save the current location when a user stops driving.
It works fine while the app is open, but I'm having no luck keeping detection going after the app has closed.
This is the service to detect activity & save location:
public class ActivityRecognitionService extends IntentService implements LocationListener {
public Location currentBestLocation;
private LocationManager locationManager ;
private String provider;
private String TAG = this.getClass().getSimpleName();
public ActivityRecognitionService() {
super("ActivityRecognitionService");
}
#Override
public void onCreate() {
super.onCreate();
try {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
if (provider != null && !provider.equals("")) {
Location location = locationManager.getLastKnownLocation(provider);
locationManager.requestLocationUpdates(provider, 1000, 1, this);
if (location != null)
onLocationChanged(location);
else
Toast.makeText(this, "Location can't be retrieved", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "No Provider Found", Toast.LENGTH_SHORT).show();
}
} catch(SecurityException e) {
Toast.makeText(this, "Enable location permissions from settings", Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onHandleIntent(Intent intent) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
Log.i(TAG, "Detected activity being called... ");
// Get the list of the probable activities associated with the current state of the
// device. Each activity is associated with a confidence level, which is an int between
// 0 and 100.
ArrayList<DetectedActivity> detectedActivities = (ArrayList) result.getProbableActivities();
for (final DetectedActivity activity : detectedActivities) {
Log.i(TAG, "Detected activity: " + getActivityString(activity.getType()) + ", " + activity.getConfidence());
if(activity.getConfidence() < 60)
continue;
logActivity(getActivityString(activity.getType()), activity.getConfidence());
List<UserActivity> userActivities = UserActivity.listAll(UserActivity.class);
if(!userActivities.isEmpty()) {
UserActivity last = userActivities.get(userActivities.size() - 1);
if(last.activity.equals("in vehicle") && activity.getType() != DetectedActivity.IN_VEHICLE) {
logParking();
}
}
}
}
private void logActivity(String type, int confidence) {
UserActivity ua = new UserActivity(type, confidence, (System.currentTimeMillis() / 1000L));
ua.save();
}
private void logParking() {
Location l = currentBestLocation;
CarLocation cl = new CarLocation(l.getLongitude(), l.getLatitude(), (System.currentTimeMillis() / 1000L));
cl.save();
}
static String getActivityString( int detectedActivityType) {
switch(detectedActivityType) {
case DetectedActivity.IN_VEHICLE:
return "in vehicle";
case DetectedActivity.ON_BICYCLE:
return "on bicycle";
case DetectedActivity.ON_FOOT:
return "on foot";
case DetectedActivity.RUNNING:
return "running";
case DetectedActivity.STILL:
return "still";
case DetectedActivity.TILTING:
return "tilting";
case DetectedActivity.UNKNOWN:
return "unknown";
case DetectedActivity.WALKING:
return "walking";
default:
return "unknown";
}
}
/**
* Only replaces current location if this reading is
* more likely to be accurate
* #param location
* #return
*/
private static final int TWO_MINUTES = 1000 * 60 * 2;
protected boolean isBetterLocation(Location location) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
#Override
public void onLocationChanged(Location location) {
if(isBetterLocation(location)) {
currentBestLocation = location;
}
}
#Override
public void onProviderDisabled(String provider) {
permissionsCheck();
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void permissionsCheck() {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
// Check Permissions Now
ActivityCompat.requestPermissions(
LocationScene.mActivity,
new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
0);
}
}
}
This service is being used to start the above service and keep it running:
public class BackgroundDetectedActivitiesService extends Service {
private static final String TAG = BackgroundDetectedActivitiesService.class.getSimpleName();
IBinder mBinder = new BackgroundDetectedActivitiesService.LocalBinder();
private Intent mIntentService;
private PendingIntent mPendingIntent;
private ActivityRecognitionClient mActivityRecognitionClient;
public BackgroundDetectedActivitiesService() {
}
#Override
public void onCreate() {
super.onCreate();
mActivityRecognitionClient = new ActivityRecognitionClient(this);
mIntentService = new Intent(this, uk.co.appoly.wheres_my_car.services.ActivityRecognitionService.class);
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, PendingIntent.FLAG_UPDATE_CURRENT);
requestActivityUpdatesButtonHandler();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
public void requestActivityUpdatesButtonHandler() {
Task<Void> task = mActivityRecognitionClient.requestActivityUpdates(
20000,
mPendingIntent);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void result) {
Toast.makeText(getApplicationContext(),
"Successfully requested activity updates",
Toast.LENGTH_SHORT)
.show();
}
});
task.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getApplicationContext(),
"Requesting activity updates failed to start",
Toast.LENGTH_SHORT)
.show();
}
});
}
public void removeActivityUpdatesButtonHandler() {
Task<Void> task = mActivityRecognitionClient.removeActivityUpdates(
mPendingIntent);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void result) {
Toast.makeText(getApplicationContext(),
"Removed activity updates successfully!",
Toast.LENGTH_SHORT)
.show();
}
});
task.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getApplicationContext(), "Failed to remove activity updates!",
Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onDestroy() {
super.onDestroy();
//removeActivityUpdatesButtonHandler();
/**/
}
public class LocalBinder extends Binder {
public BackgroundDetectedActivitiesService getServerInstance() {
return BackgroundDetectedActivitiesService.this;
}
}
}
I have this in my android manifest:
<service
android:name="uk.co.appoly.wheres_my_car.services.ActivityRecognitionService"
android:exported="false" />
<service android:name="uk.co.appoly.wheres_my_car.services.BackgroundDetectedActivitiesService"></service>
(plus correct permissions)
I am starting the service from my MainActivity like so:
activityRecognitionClient = ActivityRecognition.getClient(mContext);
transitionIntent = new Intent(MainActivity.this, BackgroundDetectedActivitiesService.class);
startService(transitionIntent);
I've been trying to fix this for about a day but to no avail. What am I doing wrong?
I'm making an app where I need to get constant location updates from a Service on a fragment, the problem is that the fragment is not getting the updates and I'm not sure what is the problem, here is the service:
public class GPService extends Service
{
private LocationManager locMan;
private Boolean locationChanged;
private Handler handler = new Handler();
static final int REQUEST_LOCATION = 1;
public static Location curLocation;
public static boolean isService = true;
public LocalBroadcastManager broadcast;
LocationListener gpsListener = new LocationListener() {
public void onLocationChanged(Location location) {
if (curLocation == null) {
curLocation = location;
locationChanged = true;
Intent intent= new Intent("GPSLocationUpdates");
intent.putExtra("latitud",curLocation.getLatitude());
intent.putExtra("latitud",curLocation.getLongitude());
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
}else if (curLocation.getLatitude() == location.getLatitude() && curLocation.getLongitude() == location.getLongitude()){
locationChanged = false;
return;
}else
locationChanged = true;
curLocation = location;
if (locationChanged)
locMan.removeUpdates(gpsListener);
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status,Bundle extras) {
}
};
#Override
public void onCreate() {
super.onCreate();
curLocation = getBestLocation();
if (curLocation == null)
Toast.makeText(getBaseContext(),"Unable to get your location", Toast.LENGTH_SHORT).show();
else{
//Toast.makeText(getBaseContext(), curLocation.toString(), Toast.LENGTH_LONG).show();
}
isService = true;
broadcast= LocalBroadcastManager.getInstance(this);
}
final String TAG="LocationService";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onLowMemory() {
super.onLowMemory();
}
#Override
public void onStart(Intent i, int startId){
handler.postDelayed(GpsFinder,1);
}
#Override
public void onDestroy() {
handler.removeCallbacks(GpsFinder);
handler = null;
Toast.makeText(this, "Stop services", Toast.LENGTH_SHORT).show();
isService = false;
}
public IBinder onBind(Intent arg0) {
return null;
}
public Runnable GpsFinder = new Runnable(){
public void run(){
Location tempLoc = getBestLocation();
if(tempLoc!=null)
curLocation = tempLoc;
tempLoc = null;
handler.postDelayed(GpsFinder,1000);
}
};
private Location getBestLocation() {
Location gpslocation = null;
Location networkLocation = null;
if(locMan==null){
locMan = (LocationManager) getApplicationContext() .getSystemService(Context.LOCATION_SERVICE);
}
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) {
//ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION);
}
else {
if(locMan.isProviderEnabled(LocationManager.GPS_PROVIDER)){
locMan.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000, 1, gpsListener);
gpslocation = locMan.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Intent intent= new Intent("GPSLocationUpdates");
intent.putExtra("latitud",gpslocation.getLatitude());
intent.putExtra("longitud",gpslocation.getLongitude());
Log.wtf("COORDENATES TO SEND",gpslocation.getLatitude()+" "+gpslocation.getLongitude());
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
}
if(locMan.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
locMan.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,1000, 1, gpsListener);
networkLocation = locMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Intent intent= new Intent("GPSLocationUpdates");
Log.wtf("LAS COORDENADAS a enviar SON",networkLocation.getLatitude()+" "+networkLocation.getLongitude());
intent.putExtra("latitud",networkLocation.getLatitude());
intent.putExtra("longitud",networkLocation.getLongitude());
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
}
}
The service is initiated in the activity like this
startService(new Intent(this, GPService.class));
In the fragment this is how I create it and register it
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
receiver= new GPSReceiver();
//this.getActivity().registerReceiver(receiver, new IntentFilter());
db=Database.getInstance(this.getContext());
}
#Override
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter("GPSLocationUpdates");
getActivity().registerReceiver(receiver,filter);
}
#Override
public void onPause() {
getActivity().unregisterReceiver(receiver);
super.onPause();
}
Finally this is the reciever in the Fragment, I can't get it to get the info from the service, any ideas? I don't know what I'm doing wrong.
private class GPSReceiver extends BroadcastReceiver {
private LatLng changed;
public GPSReceiver()
{
changed= new LatLng(0,0);
}
#Override
public void onReceive(Context context, Intent intent) {
Log.wtf("RECIEVE", "IT IS IN BROADCAST");
if (intent.getAction().equals("GPSLocationUpdates"))
{
Log.wtf("RECIEVE1", "INTENT ARRIVES");
double lat= intent.getDoubleExtra("latitud",1);
double longi= intent.getDoubleExtra("longitud",1);
changed= new LatLng(lat,longi);
}
// String text = intent.getStringExtra("position");
}
public LatLng getChanged()
{
return changed;
}
}
The service seems to be working fine, I can see the coordinates in the console being send.
You're not registering you BroadcastReceiver to the LocalBroadcastManager. You're registering it to the global broadcast manager, but sending on the local.
Change:
#Override
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter("GPSLocationUpdates");
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(receiver,filter);
}
#Override
public void onPause() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
super.onPause();
}
I have written a background service to insert latitude , longitude and some other details into my sqlite database based on the time limit set in my AlarmManager.
I am using GoogleApiClient to calculate latitude and longitude , but i am facing some problems.
Problem
When i am travelling outside without net , the latitude and longitude is not getting updated at regular intervals. The data is getting inserted in my sqlite at regular intervals but latitude and longitude remains same even after half an hour though i am travelling some about 10 kms.
I want the latitude and longitude to change while i am travelling like auto update.
I wanted to know if the FusedLocationApi calculates latitude longitude properly even if i am not connected to the internet , if yes then i need some suggestions to improve the code that i have tried.
Code i have tried.
AlarmManagerService.java
public class AlarmManagerService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = "AlarmManagerService";
AlarmReceiver alarmReceiver;
DriverDbHelper driverDbHelper;
Handler handler;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 120000; // 2 mins
private static int FATEST_INTERVAL = 60000; // 1 min
private static int DISPLACEMENT = 10; // 10 meters
public Activity activity;
protected String mLastUpdateTime;
String areaName0, areaName1, areaName2, areaName3, fullAreaName,
sessionMobileNo, sessionDriverName, sessionDID, sessiondriverUserId,
date, time, dateTime, doc, trac_transId;
double latitude, longitude;
PowerManager.WakeLock mWakeLock;
SessionManager session;
ConnectionDetector cd;
Boolean isInternet = false;
String sync_no = "No";
String sync_yes = "Yes";
public AlarmManagerService() {
alarmReceiver = new AlarmReceiver();
driverDbHelper = new DriverDbHelper(this);
cd = new ConnectionDetector(this);
}
public void setActivity(Activity activity) {
this.activity = activity;
}
#Override
public void onCreate() {
super.onCreate();
try {
driverDbHelper.open(AlarmManagerService.this);
} catch (Exception e) {
e.printStackTrace();
}
Log.d("Service created", "Alarm Service Created");
// First we need to check availability of play services
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
createLocationRequest();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
PowerManager mgr = (PowerManager)
getSystemService(Context.POWER_SERVICE);
if (this.mWakeLock == null) {
this.mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakeLock");
}
if (!this.mWakeLock.isHeld()) {
this.mWakeLock.acquire();
}
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
Log.d("Service started", "Alarm Service Started");
handler = new Handler(Looper.myLooper());
handler.post(new Runnable() {
#Override
public void run() {
postDatabaseDetails();
}
});
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("Service started", "Alarm Service Destroyed");
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
mGoogleApiClient.disconnect();
}
if (this.mWakeLock != null) {
this.mWakeLock.release();
this.mWakeLock = null;
}
}
private void displayLocation() {
if (mLastLocation != null) {
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
List<Address> addressList = null;
try {
Geocoder gcd = new Geocoder(getBaseContext(),
Locale.getDefault());
addressList = gcd.getFromLocation(mLastLocation.getLatitude(),
mLastLocation.getLongitude(), 1);
if (addressList != null && addressList.size() > 0) {
Address address = addressList.get(0);
areaName0 = address.getLocality(); // city name
areaName1 = address.getSubLocality();
areaName2 = address.getAdminArea();// statename
//areaName3 = address.getFeatureName(); plot no
//areaName3 = address.getCountryCode();// IN
areaName3 = address.getThoroughfare();
fullAreaName = areaName3 + "\n" + areaName1 + "\n" +
areaName0 + "," + areaName2;
} else {
Log.i("Location ", "Location null");
}
} catch (IOException e1) {
Log.e("HomePage", "IO Exception in getFromLocation()");
e1.printStackTrace();
} catch (IllegalArgumentException e2) {
// Error message to post in the log
String errorString = "Illegal arguments " +
Double.toString(mLastLocation.getLatitude()) + " , " +
Double.toString(mLastLocation.getLongitude()) +
" passed to address service";
Log.e("HomePage", errorString);
e2.printStackTrace();
}
}
}
/**
* Creating google api client object
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Creating location request object
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
//mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
/**
* Method to verify google play services on the device
*/
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, activity,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Log.i("Google play services", "Device not supported");
activity.finish();
}
return false;
}
return true;
}
/**
* Starting the location updates
*/
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
#Override
public void onConnected(Bundle bundle) {
// Once connected with google api, get the location
//displayLocation();
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
if (mLastLocation == null) {
mLastLocation =
LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
displayLocation();
}
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.d("Location changed ", "Location changed " + mLastLocation);
Log.d("Last updated time", "Last updated location " + mLastUpdateTime);
// Displaying the new location on UI
displayLocation();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ connectionResult.getErrorCode());
}
public void postDatabaseDetails() {
session = new SessionManager(getApplicationContext());
HashMap<String, String> user = session.getUserDetails();
sessionMobileNo = user.get(SessionManager.KEY_MOBILENO);
sessionDriverName = user.get(SessionManager.KEY_NAME);
sessionDID = user.get(SessionManager.KEY_DEVICEID);
sessiondriverUserId = user.get(SessionManager.KEY_DRIVERUSERID);
Calendar in = Calendar.getInstance();
Date dt = new Date();
in.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat stf = new SimpleDateFormat("HH:mm:ss");
date = sdf.format(dt);
time = stf.format(dt);
String timeval = time.toString();
String dateval = date.toString();
dateTime = date.toString() + " " + time.toString();
doc = sessionDID + "" + dateTime;
isInternet = cd.isConnectingToInternet();
if (isInternet) {
long id = driverDbHelper.insertDriverDetails(doc, sessionDID,
sessiondriverUserId, latitude, longitude,
fullAreaName, dateTime, "DEMO", sync_no, dateval, timeval);
postDriverDetails();
Log.d("GPS", "Service started after 2 mins with internet");
} else {
Log.d("Internet status", "No internet available for service");
long id = driverDbHelper.insertDriverDetails(doc, sessionDID,
sessiondriverUserId, latitude, longitude,
"NA", dateTime, "DEMO", sync_no, dateval, timeval);
Log.d("GPS", "Service started after 2 mins without internet");
}
}
I am calling this service from the activity HomePage.java , but from where do i have to call the below code , from onStart() or after setContentView(R.layout.home)?
try {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MINUTE, 2);
AlarmManager am = (AlarmManager)
getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(Home_Page.this, AlarmManagerService.class);
PendingIntent pi = PendingIntent.getService(Home_Page.this, 0, i,0);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), EXEC_INTERVAL, pi);
} catch (Exception e) {
e.printStackTrace();
}
I hope i can get some suggestions to improve the above service code as i want it to run smoothly in background updating the latitude and longitude at regular intervals.
Hai am trying to get the gps location using BroadCast Receiver.its working fine,But i want to get the location every half hour once.i used **MINIMUM_TIME_BETWEEN_UPDATES ** 30mts .i got when latitude and longitude value changed
update
public class MainActivity extends Activity implements LocationListener {
final DBAdapter1 db=new DBAdapter1(this);
private ConnectivityReceiver receiver = null;
private TextView txtNetworkInfo ;
private static TextView latituteField;
private static TextView longitudeField;
private LocationManager locationManager;
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
private static final String HostUrl =" http://xxx/Service.svc";
// private static final String HostUrl =" http://yyyService.svc";
private static final String NAMESPACE = "http://tempuri.org/";
private HttpTransportSE httpTransport = new HttpTransportSE(HostUrl);
private String provider;
private SoapObject request=null;
private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 1; // in Meters
private static final long MINIMUM_TIME_BETWEEN_UPDATES = 1800000; // in Milliseconds
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
latituteField = (TextView) findViewById(R.id.TextView02);
longitudeField = (TextView) findViewById(R.id.TextView04);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Define the criteria how to select the locatioin provider -> use
// default
Criteria criteria = new Criteria();
Log.i("ConnTest",locationManager.toString());
provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
// Initialize the location fields
if (location != null) {
System.out.println("Provider " + provider + " has been selected.");
float lat = (float) (location.getLatitude());
float lng = (float) (location.getLongitude());
latituteField.setText(String.valueOf(lat));
longitudeField.setText(String.valueOf(lng));
} else {
latituteField.setText("provider not available");
longitudeField.setText("provider not available");
}
txtNetworkInfo = (TextView)findViewById(R.id.txtNetworkInfo);
receiver = new ConnectivityReceiver();
registerReceiver(receiver,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
#Override
protected void onResume() {
super.onResume();
//locationManager.requestLocationUpdates(provider,1000, 1, this);
locationManager.requestLocationUpdates(
provider,
MINIMUM_TIME_BETWEEN_UPDATES,
MINIMUM_DISTANCE_CHANGE_FOR_UPDATES,
this
);
}
/* Remove the locationlistener updates when Activity is paused */
#Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
float lat = (float) (location.getLatitude());
float lng = (float) (location.getLongitude());
longitudeField.setText(String.valueOf(lng));
latituteField.setText(String.valueOf(lat));
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
Toast.makeText(this, "Enabled new provider " + provider,
Toast.LENGTH_SHORT).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
Toast.makeText(this, "Disenabled provider " + provider,
Toast.LENGTH_SHORT).show();
}
protected void Display(Cursor c) {
Toast.makeText(this, "rowid: " + c.getString(0) + "\n" +
"Latitude: " + c.getString(1) + "\n" + "Longitude: " + c.getString(2) + "\n" +
Toast.LENGTH_LONG, 0).show();
}
#Override
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
private String getNetworkStateString(NetworkInfo.State state){
String stateString = "Unknown";
switch(state)
{
case CONNECTED: stateString = "Connected"; break;
case CONNECTING: stateString = "Connecting"; break;
case DISCONNECTED: stateString = "Disconnected"; break;
case DISCONNECTING: stateString = "Disconnecting"; break;
case SUSPENDED: stateString = "Suspended"; break;
default: stateString = "Unknown"; break;
}
return stateString;
}
private class ConnectivityReceiver extends BroadcastReceiver{
private Timer mTimer;
private TimerTask mTimerTask;
#Override
public void onReceive(Context context, Intent intent) {
NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if(null != info)
{
String state = getNetworkStateString(info.getState());
if(state.equals("Connected")){
try{
mTimer = new Timer();
mTimer.scheduleAtFixedRate(mTimerTask,1000,1800000);
mTimerTask = new TimerTask() {
#Override
public void run() {
SoapPrimitive response=null;
final String methodname="InsertAllGPSInformation";
request = new SoapObject(NAMESPACE,methodname);
envelope.dotNet = true;
request.addProperty("Longitude",longitudeField.getText().toString());
request.addProperty("Latitude",latituteField.getText().toString());
request.addProperty("Date",newtime);
envelope.setOutputSoapObject(request);
String result = null;
try
{
httpTransport.call(NAMESPACE+"IService/"+methodname, envelope);
response = ( SoapPrimitive )envelope.getResponse();
result=response.toString();
}
catch(Exception e)
{
Toast.makeText(getBaseContext(), "Your Net Connected or Not Login to Net"+"", Toast.LENGTH_LONG).show();
Log.e("Upload Picture Error:",e.getMessage());
}
}
};
}
catch(Exception e)
{
Toast.makeText(getBaseContext(),e.getMessage()+"", Toast.LENGTH_LONG).show();
Log.e("Upload Picture Error:",e.getMessage());
}
I guess the question is "why do I get more updates than once every 30 minutes?":
Then the answer would be: "the minimum time interval for notifications, in milliseconds. This field is only used as a hint to conserve power, and actual time between location updates may be greater or lesser than this value.".
See http://developer.android.com/reference/android/location/LocationManager.html
Alternatively you could use a Handler or trigger an alarm every 30' and request a single location update when the alarm fires. Starting with API 9 there is a requestSingleUpdate().
Use Alarm Manager. Because your timer can die. But Alarm will wake your app. Try this working code: It wakes CPU every 10 minutes and shows notification.
Add to Manifest.xml:
...
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
...
<receiver android:process=":remote" android:name="Alarm"></receiver>
...
Code:
public class Alarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG");
wl.acquire();
// Put here YOUR code.
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show(); // For example
wl.release();
}
public void SetAlarm(Context context)
{
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 10, pi); // Millisec * Second * Minute
}
public void CancelAlarm(Context context)
{
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}