Background location update using Google Play Services...
Successfully have location updates every 5 minutes in the background.
But, perhaps not surprisingly, if the device is rebooted then the updates stop.
Is it possible to have background location updates survive a phone reboot... and if so, how?
Here is present code in case that helps:
import android.os.Bundle;
import java.util.ArrayList;
public class GPSTracker extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {
protected static final String TAG = "Location...";
private Context mContext = this;
/**
* Tracks the status of the location updates request.
*/
public static Boolean mRequestingLocationUpdates;
/**
* Time when the location was updated represented as a String.
*/
protected String mLastUpdateTime;
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation;
public static boolean isEnded = false;
#Override
public void onCreate() {
super.onCreate();
buildGoogleApiClient();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("LOC", "Service init...");
isEnded = false;
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
// buildGoogleApiClient();
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
return START_STICKY;
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended==");
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
double latitude = location.getLatitude();
double longitude = location.getLongitude();
StringBuilder stringBuilder = new StringBuilder();
StringBuilder latlong = stringBuilder.append(latitude + "," + longitude);
Calendar cal = Calendar.getInstance();
String zone = TimeZone.getDefault().getDisplayName(false, android.icu.util.TimeZone.SHORT);
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM 'at' h:mm a");
Date date = new Date();
String localtime = (formatter.format(date)).toString();
Date myDate = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
calendar.setTime(myDate);
date = calendar.getTime();
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss zz");
dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
String utc = dateFormatter.format(date);
// DateFormat df = DateFormat.getTimeInstance();
// df.setTimeZone(TimeZone.getTimeZone("gmt"));
// String gmtTime = df.format(new Date());
String model = Build.MODEL;
String reqString = Build.VERSION.RELEASE
+ " " + Build.VERSION_CODES.class.getFields()[android.os.Build.VERSION.SDK_INT].getName();
// Date currentTime = Calendar.getInstance().getTime();
// String localtime = currentTime.toString();
PreferencesClass preferencesClass = new PreferencesClass(mContext);
String id = preferencesClass.getFingerPrint();
Data data = null;
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("userId", id);
jsonObject.put("latLon", latlong);
jsonObject.put("timeZone", zone);
jsonObject.put("localTime", localtime);
jsonObject.put("osVersion", reqString);
jsonObject.put("phoneModel", model);
jsonObject.put("utcTime", utc);
data = new Data();
data.setData(jsonObject.toString());
if (data != null) {
if (Utility.isConnectingToInternet(mContext)) {
// boolean isChecked = preferencesClass.getIsChecked();
// if (isChecked){
LocationWebServiceMgr locationWebServiceMgr = new LocationWebServiceMgr();
locationWebServiceMgr.Location(data, new CallBackInterface() {
#Override
public void onResponse(ArrayList<Object> objects, ResponseMetaData responseMetaData) {
Log.d(TAG, "onResponse: Succesfully added the location to server");
// Toast.makeText(getApplicationContext(), "added to server", Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(ResponseMetaData t) {
}
});
// } else {
// Log.d("serverCall", "Location Permission not available ");
// }
} else {
Log.e("serverCall", "Network not available");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient===");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
/**
* Sets up the location request. Android has two location request settings:
* {#code ACCESS_COARSE_LOCATION} and {#code ACCESS_FINE_LOCATION}. These settings control
* the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in
* the AndroidManifest.xml.
* <p/>
* When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update
* interval (5 seconds), the Fused Location Provider API returns location updates that are
* accurate to within a few feet.
* <p/>
* These settings are appropriate for mapping applications that show real-time location
* updates.
*/
protected void createLocationRequest() {
mGoogleApiClient.connect();
mLocationRequest = new LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(Constants.UPDATE_INTERVAL_IN_MILLISECONDS);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(Constants.FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
// mLocationRequest.setSmallestDisplacement(Constants.DISPLACEMENT);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
// The final argument to {#code requestLocationUpdates()} is a LocationListener
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.i(TAG, " startLocationUpdates===");
isEnded = true;
}
}
}
I handled like below it's will helpful for you
RestartReceiver:
public class RestartReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
//started service for update the location of userx
LocationsUpdateRequest.createLocationRequest(context);
//updated in my preference because I need to send data to server if user signed in app only
} catch (Exception e) {
LogUtils.crashlytics(e);
}
}
}
ShutdownReceiver:
public class ShutdownReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
//stop the service when phone is shotdown
LocationsUpdateRequest.getPendingIntent(context).cancel();
//reset flag in preference
} catch (Exception e) {
}
}
}
Manifest:
<receiver android:name=".services.ShutdownReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.QUICKBOOT_POWEROFF" />
</intent-filter>
</receiver>
<receiver android:name=".services.RestartReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Related
I am Using Fused Location Provider Google api client to get the location for every 5 minutes . It is updating both in background and also when the application is killed . But it is Stopped updating after some 2 to 3 days . i have tested in most of the android devices.
I am calling this Service from an Activity and i am Killing the application, it is sending location updates for every 5 minutes for almost 3 days after that it is getting stopped .I tried So many times.
public class GPSTracker extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener {
protected static final String TAG = "Location...";
private Context mContext = this;
/**
* Tracks the status of the location updates request.
*/
public static Boolean mRequestingLocationUpdates;
/**
* Time when the location was updated represented as a String.
*/
protected String mLastUpdateTime;
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation;
public static boolean isEnded = false;
#Override
public void onCreate() {
super.onCreate();
buildGoogleApiClient();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("LOC", "Service init...");
isEnded = false;
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
// buildGoogleApiClient();
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
return START_STICKY;
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended==");
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
double latitude = location.getLatitude();
double longitude = location.getLongitude();
StringBuilder stringBuilder = new StringBuilder();
StringBuilder latlong = stringBuilder.append(latitude + "," + longitude);
Calendar cal = Calendar.getInstance();
String zone = TimeZone.getDefault().getDisplayName(false, android.icu.util.TimeZone.SHORT);
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM 'at' h:mm a");
Date date = new Date();
String localtime = (formatter.format(date)).toString();
Date myDate = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
calendar.setTime(myDate);
date = calendar.getTime();
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss zz");
dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
String utc = dateFormatter.format(date);
// DateFormat df = DateFormat.getTimeInstance();
// df.setTimeZone(TimeZone.getTimeZone("gmt"));
// String gmtTime = df.format(new Date());
String model = Build.MODEL;
String reqString = Build.VERSION.RELEASE
+ " " + Build.VERSION_CODES.class.getFields()[android.os.Build.VERSION.SDK_INT].getName();
// Date currentTime = Calendar.getInstance().getTime();
// String localtime = currentTime.toString();
PreferencesClass preferencesClass = new PreferencesClass(mContext);
String id = preferencesClass.getFingerPrint();
Data data = null;
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("userId", id);
jsonObject.put("latLon", latlong);
jsonObject.put("timeZone", zone);
jsonObject.put("localTime", localtime);
jsonObject.put("osVersion",reqString);
jsonObject.put("phoneModel",model);
jsonObject.put("utcTime",utc);
data = new Data();
data.setData(jsonObject.toString());
if (data != null) {
if (Utility.isConnectingToInternet(mContext)) {
// boolean isChecked = preferencesClass.getIsChecked();
// if (isChecked){
LocationWebServiceMgr locationWebServiceMgr = new LocationWebServiceMgr();
locationWebServiceMgr.Location(data, new CallBackInterface() {
#Override
public void onResponse(ArrayList<Object> objects, ResponseMetaData responseMetaData) {
Log.d(TAG, "onResponse: Succesfully added the location to server");
// Toast.makeText(getApplicationContext(), "added to server", Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(ResponseMetaData t) {
}
});
// } else {
// Log.d("serverCall", "Location Permission not available ");
// }
} else {
Log.e("serverCall", "Network not available");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient===");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
/**
* Sets up the location request. Android has two location request settings:
* {#code ACCESS_COARSE_LOCATION} and {#code ACCESS_FINE_LOCATION}. These settings control
* the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in
* the AndroidManifest.xml.
* <p/>
* When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update
* interval (5 seconds), the Fused Location Provider API returns location updates that are
* accurate to within a few feet.
* <p/>
* These settings are appropriate for mapping applications that show real-time location
* updates.
*/
protected void createLocationRequest() {
mGoogleApiClient.connect();
mLocationRequest = new LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(Constants.UPDATE_INTERVAL_IN_MILLISECONDS);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(Constants.FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
// mLocationRequest.setSmallestDisplacement(Constants.DISPLACEMENT);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
// The final argument to {#code requestLocationUpdates()} is a LocationListener
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.i(TAG, " startLocationUpdates===");
isEnded = true;
}
}
}
you can create service for do this
public class TimeService extends Service {
// constant
public static final long NOTIFY_INTERVAL = 10 * 1000; // 10 seconds
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
// cancel if already existed
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast
startService(new Intent(this, MyService.class));
}
});
}
private String getDateTime() {
// get date time in custom format
SimpleDateFormat sdf = new SimpleDateFormat("[yyyy/MM/dd - HH:mm:ss]");
return sdf.format(new Date());
}
}
and service for location
public class MyService extends Service
{
private static final String TAG = "BOOMBOOMTESTGPS";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 10f;
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);
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);
}
}
LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onCreate()
{
Log.e(TAG, "onCreate");
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} 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());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_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, "gps provider does not exist " + ex.getMessage());
}
}
#Override
public void onDestroy()
{
Log.e(TAG, "onDestroy");
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
}
Use workmanager to reschedule your location service. Check if location service not running then start from scheduler.
To read more regarding workmanager click here
Create a class for location get.
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);
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);
}
}
in onLocation(Location location) change method you will get current let,long
For that, you can use AlarmManager or firebase jobdispatcher or job scheduler to trigger any event after specific intervals. I suggest you to use AlarmManager which are easiest.
Refer this code to set alarm:
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
int notificationID = 2018;
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, notificationID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),5*1000, pendingIntent);
And you can cancel alarm like this way:
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, notificationID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.cancel(pendingIntent);
pendingIntent.cancel();
Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.
I'm using GoogleApiClient to implement a location listener service, but the GPS icon is always being displayed, even with the service in background. How to disable the GPS icon when the service is in the background?
Follow the sources below:
Activity
public class ShowDistanceActivity extends AppCompatActivity implements ILocationConstants {
protected static final String TAG = ShowDistanceActivity.class.getSimpleName();
#Bind(R.id.tvLocationData)
TextView tvLocationData;
#Bind(R.id.toolbar)
Toolbar toolbar;
/**
* Receiver listening to Location updates and updating UI in activity
*/
private LocationReceiver locationReceiver;
/**
* Permission util with callback mechanism to avoid boilerplate code
* <p/>
* https://github.com/kayvannj/PermissionUtil
*/
private PermissionUtil.PermissionRequestObject mBothPermissionRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_distance);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
locationReceiver = new LocationReceiver();
}
private void startLocationService() {
Intent serviceIntent = new Intent(this, LocationService.class);
startService(serviceIntent);
}
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(locationReceiver, new IntentFilter(LOACTION_ACTION));
/**
* Runtime permissions are required on Android M and above to access User's location
*/
if (AppUtils.hasM() && !(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {
askPermissions();
} else {
startLocationService();
}
}
/**
* Ask user for permissions to access GPS location on Android M
*/
public void askPermissions() {
mBothPermissionRequest =
PermissionUtil.with(this).request(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION).onResult(
new Func2() {
#Override
protected void call(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
startLocationService();
} else {
Toast.makeText(ShowDistanceActivity.this, R.string.permission_denied, Toast.LENGTH_LONG).show();
}
}
}).ask(PERMISSION_ACCESS_LOCATION_CODE);
}
#Override
protected void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(this).unregisterReceiver(locationReceiver);
}
private class LocationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (null != intent && intent.getAction().equals(LOACTION_ACTION)) {
String locationData = intent.getStringExtra(LOCATION_MESSAGE);
tvLocationData.setText(locationData);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (null != mBothPermissionRequest) {
mBothPermissionRequest.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Service
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, ILocationConstants, IPreferenceConstants {
private static final String TAG = LocationService.class.getSimpleName();
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation;
private String mLatitudeLabel;
private String mLongitudeLabel;
private String mLastUpdateTimeLabel;
private String mDistance;
/**
* Time when the location was updated represented as a String.
*/
protected String mLastUpdateTime;
private Location oldLocation;
private Location newLocation;
private AppPreferences appPreferences;
/**
* Total distance covered
*/
private float distance;
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
appPreferences = new AppPreferences(this);
oldLocation = new Location("Point A");
newLocation = new Location("Point B");
mLatitudeLabel = getString(R.string.latitude_label);
mLongitudeLabel = getString(R.string.longitude_label);
mLastUpdateTimeLabel = getString(R.string.last_update_time_label);
mDistance = getString(R.string.distance);
mLastUpdateTime = "";
distance = appPreferences.getFloat(PREF_DISTANCE, 0);
Log.d(TAG, "onCreate Distance: " + distance);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand called");
buildGoogleApiClient();
mGoogleApiClient.connect();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
}
return Service.START_STICKY;
}
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.d(TAG, "buildGoogleApiClient() called");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
protected void createLocationRequest() {
Log.d(TAG, "createLocationRequest() called");
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
try {
Log.d(TAG, "startLocationUpdates called");
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
} catch (SecurityException ex) {
ex.printStackTrace();
}
}
/**
* Updates the latitude, the longitude, and the last location time in the UI.
*/
private void updateUI() {
if (null != mCurrentLocation) {
StringBuilder sbLocationData = new StringBuilder();
sbLocationData.append(mLatitudeLabel)
.append(" ")
.append(mCurrentLocation.getLatitude())
.append("\n")
.append(mLongitudeLabel)
.append(" ")
.append(mCurrentLocation.getLongitude())
.append("\n")
.append(mLastUpdateTimeLabel)
.append(" ")
.append(mLastUpdateTime)
.append("\n")
.append(mDistance)
.append(" ")
.append(getUpdatedDistance())
.append(" meters");
/*
* update preference with latest value of distance
*/
appPreferences.putFloat(PREF_DISTANCE, distance);
Log.d(TAG, "Location Data:\n" + sbLocationData.toString());
sendLocationBroadcast(sbLocationData.toString());
} else {
Toast.makeText(this, R.string.unable_to_find_location, Toast.LENGTH_SHORT).show();
}
}
/**
* Send broadcast using LocalBroadcastManager to update UI in activity
*
* #param sbLocationData
*/
private void sendLocationBroadcast(String sbLocationData) {
Log.d(TAG, "sendLocationBroadcast() called");
Intent locationIntent = new Intent();
locationIntent.setAction(LOACTION_ACTION);
locationIntent.putExtra(LOCATION_MESSAGE, sbLocationData);
LocalBroadcastManager.getInstance(this).sendBroadcast(locationIntent);
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
Log.d(TAG, "stopLocationUpdates() called");
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy() called");
appPreferences.putFloat(PREF_DISTANCE, distance);
stopLocationUpdates();
mGoogleApiClient.disconnect();
Log.d(TAG, "onDestroy Distance " + distance);
super.onDestroy();
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) throws SecurityException {
Log.i(TAG, "Connected to GoogleApiClient");
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
startLocationUpdates();
}
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged() called");
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
#Override
public void onConnectionSuspended(int cause) {
Log.d(TAG, "onConnectionSuspended() called");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
private float getUpdatedDistance() {
/**
* There is 68% chance that user is with in 100m from this location.
* So neglect location updates with poor accuracy
*/
if (mCurrentLocation.getAccuracy() > ACCURACY_THRESHOLD) {
Log.d(TAG, "getUpdatedDistance() called");
return distance;
}
if (oldLocation.getLatitude() == 0 && oldLocation.getLongitude() == 0) {
oldLocation.setLatitude(mCurrentLocation.getLatitude());
oldLocation.setLongitude(mCurrentLocation.getLongitude());
newLocation.setLatitude(mCurrentLocation.getLatitude());
newLocation.setLongitude(mCurrentLocation.getLongitude());
return distance;
} else {
oldLocation.setLatitude(newLocation.getLatitude());
oldLocation.setLongitude(newLocation.getLongitude());
newLocation.setLatitude(mCurrentLocation.getLatitude());
newLocation.setLongitude(mCurrentLocation.getLongitude());
}
/**
* Calculate distance between last two geo locations
*/
distance += newLocation.distanceTo(oldLocation);
return distance;
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
Manifest
Android Manifest declaration
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.technosavy.showmedistance">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".ShowDistanceActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".service.LocationService"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
Please, any help is welcome.
To remove the GPS icon you need to use cached and wi-fi location settings (from memory). In your code make the following changes.
In Manifest, remove:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
In Service, change the following:
mLocationRequest.setInterval(10000L);
mLocationRequest.setFastestInterval(5000L);
// Do NOT use LocationRequest.PRIORITY_HIGH_ACCURACY here
// Instead use one of the other option.
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_NO_POWER);
// Remove setSmallestDisplacement() as it should not be used
// unless you are using a GPS / PRIORITY_HIGH_ACCURACY
//mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
Pretty sure this is will remove the GPS icon but you will also only get the FusedLocationApi.getLastLocation() values when the onConnected() method is called (very possible this will be low accuracy).
The onLocationChanged() method may never trigger until another application makes a location request at a higher priority or with more accuracy.
The new fused location providers take a slightly different approach compared to previous methods. Developers now choose how much battery power is used to calculate a location instead of which device components are used to calculate it. It uses any available combination of GPS, Wi-Fi, mobile networks, and onboard sensors to calculate the location.
The LocationRequest priority settings are now:
PRIORITY_NO_POWER (passively listens for location updates from other clients)
PRIORITY_LOW_POWER (~10km "city" accuracy)
PRIORITY_BALANCED_POWER_ACCURACY (~100m "block" accuracy)
PRIORITY_HIGH_ACCURACY (accurate as possible at the expense of battery life)
Google describes the LocationRequest class here: http://developer.android.com/reference/com/google/android/gms/location/LocationRequest.html
I am using google fused location API and I was able to successfully implement it but it appears like this I have the logs:
Location[fused 31******,30****** acc=27 et=+16h8m55s272ms]
I can't figure the problem.
i managed to get it by casting it to double
Double.toString(location.getLatitude())
This is Location Service which runs in background and Tested
public class LocationTrackingService extends Service implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
protected static final String TAG = "location-updates-sample";
private Context context;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
protected Location mCurrentLocation;
protected Boolean mRequestingLocationUpdates;
private String locationIntent;
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected to GoogleApiClient");
if (mCurrentLocation == null) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.disconnect();
}
#Override
public void onLocationChanged(Location location) {
if (locationIntent.equals(AppConstants.LOCATION_INTENT)) {
EventBus.getDefault().post(new CurrentLocation(location));
Log.e(TAG, "LOCATION CHANGED : " + " " + DateFormat.getTimeInstance().format(new Date()) + " " + location.getLatitude() + " " + location.getLongitude());
//stopLocationUpdates();
//mGoogleApiClient.disconnect();
} else if (location.equals(AppConstants.LOCATION_TRACK_INTENT)) {
startLocationUpdates();
Log.e(TAG, "TRACK LOCATION : " + " " + DateFormat.getTimeInstance().format(new Date()) + " " + location.getLatitude() + " " + location.getLongitude());
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
buildGoogleApiClient();
mGoogleApiClient.connect();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
context = this;
locationIntent = intent.getStringExtra(AppConstants.LOCATION_INTENT);
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
}
return START_STICKY;
}
#Override
public void onDestroy() {
// handler.removeCallbacks(sendUpdatesToUI);
super.onDestroy();
Log.e("STOP_SERVICE", "STOP_SERVICE");
stopLocationUpdates();
mGoogleApiClient.disconnect();
}
#Override
public void onCreate() {
super.onCreate();
buildGoogleApiClient();
mGoogleApiClient.connect();
Toast.makeText(this, "service", Toast.LENGTH_LONG).show();
}
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.e(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
/**
* Sets up the location request. Android has two location request settings:
* {#code ACCESS_COARSE_LOCATION} and {#code ACCESS_FINE_LOCATION}. These settings control
* the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in
* the AndroidManifest.xml.
* <p>
* When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update
* interval (5 seconds), the Fused Location Provider API returns location updates that are
* accurate to within a few feet.
* <p>
* These settings are appropriate for mapping applications that show real-time location
* updates.
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
mRequestingLocationUpdates = true;
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}}
Hi I have a service in which I find the user location co-ordinates. This service is started in onCreate in my MainActivity. however until it finds the values as I know GPS can take some time to find the co-ordinates the screen is black. I have created a splash screen which I would like to show but I am not sure on how to implement. My code will explain more:
My service:
public class LocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
LocationListener {
public static double curlat;
public static double curlong;
IBinder mBinder = new LocalBinder();
private LocationClient mLocationClient;
private LocationRequest mLocationRequest;
// Flag that indicates if a request is underway.
private boolean mInProgress;
public static final String BROADCAST_ACTION = "com.example.fusedlocation.displayevent";
Intent intent;
private Boolean servicesAvailable = false;
public class LocalBinder extends Binder {
public LocationService getServerInstance() {
return LocationService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
mInProgress = false;
// Create the LocationRequest object
mLocationRequest = LocationRequest.create();
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
// Set the update interval to 5 seconds
mLocationRequest.setInterval(Constants.UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
mLocationRequest.setFastestInterval(Constants.FASTEST_INTERVAL);
servicesAvailable = servicesConnected();
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
mLocationClient = new LocationClient(this, this, this);
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
return true;
} else {
return false;
}
}
public int onStartCommand (Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
if(!servicesAvailable || mLocationClient.isConnected() || mInProgress)
return START_STICKY;
setUpLocationClientIfNeeded();
if(!mLocationClient.isConnected() || !mLocationClient.isConnecting() && !mInProgress)
{
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Started", Constants.LOG_FILE);
mInProgress = true;
mLocationClient.connect();
}
return START_STICKY;
}
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
private void setUpLocationClientIfNeeded()
{
if(mLocationClient == null)
mLocationClient = new LocationClient(this, this, this);
}
// Define the callback method that receives location updates
#Override
public void onLocationChanged(android.location.Location location) {
// Report to the UI that the location was updated
String msg = Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Log.d("debug", msg);
curlat = location.getLatitude();
curlong = location.getLongitude();
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
appendLog(msg, Constants.LOCATION_FILE);
intent.putExtra("Latitude", location.getLatitude());
intent.putExtra("Longitude", location.getLongitude());
sendBroadcast(intent, null);
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public String getTime() {
SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return mDateFormat.format(new Date());
}
public void appendLog(String text, String filename)
{
File logFile = new File(filename);
if (!logFile.exists())
{
try
{
logFile.createNewFile();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
//BufferedWriter for performance, true to set append to file flag
BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
buf.append(text);
buf.newLine();
buf.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onDestroy(){
// Turn off the request flag
mInProgress = false;
if(servicesAvailable && mLocationClient != null) {
mLocationClient.removeLocationUpdates(this);
// Destroy the current location client
mLocationClient = null;
}
// Display the connection status
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Stopped", Constants.LOG_FILE);
super.onDestroy();
}
/*
* Called by Location Services when the request to connect the
* client finishes successfully. At this point, you can
* request the current location or start periodic updates
*/
#Override
public void onConnected(Bundle bundle) {
// Request location updates using static settings
mLocationClient.requestLocationUpdates(mLocationRequest, this);
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Connected", Constants.LOG_FILE);
}
/*
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
#Override
public void onDisconnected() {
// Turn off the request flag
mInProgress = false;
// Destroy the current location client
mLocationClient = null;
// Display the connection status
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
appendLog(DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected", Constants.LOG_FILE);
}
/*
* Called by Location Services if the attempt to
* Location Services fails.
*/
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mInProgress = false;
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
// If no resolution is available, display an error dialog
} else {
}
}
}
MainActivity ( Only the relevant parts):
public class MainActivity extends Activity implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener{
// Google Map & markers
private GoogleMap googleMap;
private Circle mCircle;
private Marker mMarker;
double radiusInMeters;
long start_time, countUp, timeDialogShown = 0;
double latitude, longitude, startLongitude, startLatitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setting the layout
setContentView(R.layout.activity_main);
try {
// Loading map
initilizeMap();
} catch (Exception e) {
e.printStackTrace();
}
startService(new Intent(this, LocationService.class));
} // end onCreate
//Checking the latest location updates
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
latitude = extras.getDouble("Latitude");
longitude = extras.getDouble("Longitude");
LatLng latLng = new LatLng(latitude, longitude);
if (mCircle == null || mMarker == null) {
drawMarkerWithCircle(latLng);
} else {
updateMarkerWithCircle(latLng);
}
getDistance();
//Getting the current weather conditions
//if (condDescr.getText().equals(" ")){
// getWeatherConditions();
//}
//Check if the user has breached the Geofence boundaries
checkBoundaries();
}
};
Check my answer here:
Android SplashScreen
Basically creating a theme background will deal with the black screen till you set the content.
Create a splash_screen activity. Set it as start-up activity.
In this splash_screen activity's onCreate() u can start a service to get location update.
Once u r done with location update, start ur MainAcitivity.class.
protected void onCreate(android.os.Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen_layout);
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
// start the service to get location update
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
// start the main activity
}
});
t1.start();
}
Hey everybody,
I am writing an app that uses geolocation to track a user while he is walking from point A to point B. Here is my code so far:
public class LocationTest extends Activity {
private static final String[] S = { "out of service", "temporarily unavailable", "available" };
ArrayList<Location> list = new ArrayList<Location>();
private TextView output;
private String best;
LocationListener locationListener;
LocationManager mgr;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
output = (TextView) findViewById(R.id.output);
mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
best = mgr.getBestProvider(criteria, true);
log("\nBest provider is: " + best);
locationListener = new LocationListener(){
public void onLocationChanged(Location location){
dumpLocation(location);
list.add(location);
}
public void onStatusChanged(String provider, int status, Bundle extras){
log("\nProvider status changed: " + provider + ", status=" + S[status]);
}
public void onProviderEnabled(String provider){
log("\nProvider enabled: " + provider);
}
public void onProviderDisabled(String provider){
log("\nProvider disabled: " + provider);
}
};
}
#Override
protected void onResume(){
super.onResume();
mgr.requestLocationUpdates(best, 120000, 50, locationListener);
}
#Override
protected void onPause(){
super.onPause();
mgr.removeUpdates(locationListener);
log_gen(list);
}
The app currently displays longitude and latitude whenever new fix is obtained. However, the tracking only works when the Activity is displayed on the screen and as soon as the user quits the app the tracking stops. What I want my app to do is keep tracking the user in the background even if he quits the app. Whenever he re-opens an app few minutes later, for example, all the coordinates captured in the background should be displayed on the screen.
From what I researched so far, there are two ways one can go about it: either use a background service to do the tracking or use
requestLocationUpdates (String provider, long minTime, float minDistance, PendingIntent intent)
in combination with BroadcastReceiver to continue getting location updates even if the user quits the app. If I am understanding correct, the second method would continue running in the background. Can someone please show to me in code how to implement BroadcastReceiver with the alternate version of requestLocationUpdates
Many thanks in advance.
Using the below code you can get the periodic location updates well if are concerned for the continuously running service you can customise the interval for getting the location updates also you would need to integrate the google play services in you app in order the following code to work
public class BackgroundLocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
IBinder mBinder = new LocalBinder();
private LocationClient mLocationClient;
private LocationRequest mLocationRequest;
// Flag that indicates if a request is underway.
private boolean mInProgress;
private static final String TAG = BackgroundLocationService.class
.getSimpleName();
private Boolean servicesAvailable = false;
public class LocalBinder extends Binder {
public BackgroundLocationService getServerInstance() {
return BackgroundLocationService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
mInProgress = false;
// Create the LocationRequest object
mLocationRequest = LocationRequest.create();
// Use high accuracy
mLocationRequest
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
// Set the update interval to 5 seconds
mLocationRequest.setInterval(Constants.UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
mLocationRequest.setFastestInterval(Constants.FASTEST_INTERVAL);
servicesAvailable = servicesConnected();
/*
* Create a new location client, using the enclosing class to handle
* callbacks.
*/
mLocationClient = new LocationClient(this, this, this);
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
return true;
} else {
return false;
}
}
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (!servicesAvailable || mLocationClient.isConnected() || mInProgress)
return START_STICKY;
setUpLocationClientIfNeeded();
if (!mLocationClient.isConnected() || !mLocationClient.isConnecting()
&& !mInProgress) {
mInProgress = true;
mLocationClient.connect();
}
return START_STICKY;
}
/*
* Create a new location client, using the enclosing class to handle
* callbacks.
*/
private void setUpLocationClientIfNeeded() {
if (mLocationClient == null)
mLocationClient = new LocationClient(this, this, this);
}
// Define the callback method that receives location updates
#Override
public void onLocationChanged(final Location location) {
// Report to the UI that the location was updated
String msg = Double.toString(location.getLatitude()) + ","
+ Double.toString(location.getLongitude());
Log.d("debug", msg);
if (location != null) {
// location has the latitude and longitude
}
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public String getTime() {
SimpleDateFormat mDateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.US);
return mDateFormat.format(new Date());
}
#Override
public void onDestroy() {
// Turn off the request flag
mInProgress = false;
if (servicesAvailable && mLocationClient != null) {
mLocationClient.removeLocationUpdates(this);
// Destroy the current location client
mLocationClient = null;
}
// Display the connection status
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new
// Date()) + ": Disconnected. Please re-connect.",
// Toast.LENGTH_SHORT).show();
super.onDestroy();
}
/*
* Called by Location Services when the request to connect the client
* finishes successfully. At this point, you can request the current
* location or start periodic updates
*/
#Override
public void onConnected(Bundle bundle) {
// Request location updates using static settings
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
/*
* Called by Location Services if the connection to the location client
* drops because of an error.
*/
#Override
public void onDisconnected() {
// Turn off the request flag
mInProgress = false;
// Destroy the current location client
mLocationClient = null;
// Display the connection status
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new
// Date()) + ": Disconnected. Please re-connect.",
// Toast.LENGTH_SHORT).show();
}
/*
* Called by Location Services if the attempt to Location Services fails.
*/
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mInProgress = false;
/*
* Google Play services can resolve some errors it detects. If the error
* has a resolution, try sending an Intent to start a Google Play
* services activity that can resolve error.
*/
if (connectionResult.hasResolution()) {
// If no resolution is available, display an error dialog
} else {
}
}
For integrating google play services please refer here