make GMS location tracking work in background - android

My Activity is like this:
public class MainMap extends FragmentActivity implements OnMarkerClickListener, OnMapReadyCallback,
ConnectionCallbacks, OnConnectionFailedListener, LocationListener, ActivityCompat.OnRequestPermissionsResultCallback {
private static final int REQUEST_ACCESS_FINE_LOCATION = 0;
protected GoogleApiClient mGoogleApiClient;
protected Location mCurrentLocation;
protected LocationRequest mLocationRequest;
// ...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(NativeLib.get_location_update_interval_in_mil());
mLocationRequest.setFastestInterval(NativeLib.get_location_fastest_update_interval_in_mil());
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
protected void onStart() {
if (debug_mode) { Log.i(TAG, "onStart");}
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
if (debug_mode) { Log.i(TAG, "onStop");}
super.onStop();
mGoogleApiClient.disconnect();
}
#Override
public void onConnected(Bundle connectionHint) {
if (debug_mode) { Log.i(TAG, "onConnected");}
// permissions
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
request_fine_location_permission();
}
// location
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onLocationChanged(Location location) {
// CALL either do_background or do_foreground
}
private void do_background() {
// DO WORK
}
private void do_foreground() {
// DO WORK
}
}
The code works just fine in the foreground - what I want to do is to make sure that location is constantly tracked (even when the app is in the background or the phone is in sleep mode) and launch the appropriate function in my Activity.

Related

FusedLocationApi is not working while scheduling it with JobScheduler

Calling FusedLocationApi within jobscheduler doesn't work. I have tried in 2 ways but onConnected() are never called in both of them. How can I make it work? Thankyou
MainActivity.class
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStartJob = (Button)findViewById(R.id.startjob);
jobScheduler = (JobScheduler)getSystemService(JOB_SCHEDULER_SERVICE);
btnStartJob.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
ComponentName jobService =
new ComponentName(getPackageName(), MyJobService.class.getName());
PersistableBundle bundle = new PersistableBundle();
bundle.putString("lat", latitude+"");
bundle.putString("lon", longitude+"");
JobInfo jobInfo =
new JobInfo.Builder(MYJOBID, jobService).setPeriodic(10000).
setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY).
setRequiresCharging(false).
setRequiresDeviceIdle(false).
setPersisted(true).
setExtras(bundle).
build();
int jobId = jobScheduler.schedule(jobInfo);
if(jobScheduler.schedule(jobInfo)>0){
}else{
}
}
});
}
}
Try 1:
Here I have implemented ConnectionCallbacks, OnConnectionFailedListener in JobService but its onConnected() method is never called...
public class MyJobService extends JobService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
protected JobParameters mJobParameters;
private GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
public MyJobService() {
}
#Override
public boolean onStartJob(JobParameters jobParameters) {
Log.e("token", "Start Job Called");
setUpLocationClientIfNeeded();
mLocationRequest = LocationRequest.create();
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(5000);
return true;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Toast.makeText(this,
"MyJobService.onStopJob()",
Toast.LENGTH_SHORT).show();
return false;
}
#Override
public void onConnected(#Nullable Bundle bundle) {
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) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(this.mGoogleApiClient,
mLocationRequest, this); // This is the changed line.
Log.e("onConnected", "onConnected");
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
private void setUpLocationClientIfNeeded()
{
if(mGoogleApiClient == null)
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
this.mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
this.mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
Log.e("token",location.getLatitude()+""+location.getLongitude());
}
}
Try 2:
Called innerClass that implements ConnectionCallbacks, OnConnectionFailedListener in onStartJob of JobService but still onConnected method is never called
public class MyJobService extends JobService {
private Location mLastLocation;
String latitude = null;
String longitude = null;
protected JobParameters mJobParameters;
private class GetLocation extends AsyncTask<Integer, Void, Integer> implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
protected Integer doInBackground(Integer... jobID) {
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(getBaseContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
return jobID[0];
}
protected void onPostExecute(Integer jobID) {
//h2 = new Handler();
//Runnable run = new Runnable() {
// #Override
// public void run() {
// long millis = System.currentTimeMillis() - 0;
// int seconds = (int) (millis / 1000);
// int minutes = seconds / 60;
// seconds = seconds % 60;
// Log.i("JobSchedulerTest","Job Finished!");
// h2.postDelayed(this, 1500);
jobFinished(mJobParameters, true);
}
};
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.e("onConnected " , "onConnected" );
createLocationRequest();
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(MyJobService.this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MyJobService.this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationCallback() {
#Override
public void onLocationResult(final LocationResult locationResult) {
latitude = locationResult.getLastLocation().getLatitude() + "";
longitude = locationResult.getLastLocation().getLongitude() + "";
Log.e("onLocationResult lat", latitude);
Log.e("onLocationResult Lon", longitude);
}
#Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
}
}, null);
}
}
public MyJobService() {
}
#Override
public boolean onStartJob(JobParameters jobParameters) {
Log.d("onstart", "onStartJob() :: ");
mJobParameters=jobParameters;
Integer i=new Integer(jobParameters.getJobId());
new GetLocation().execute(i);
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Toast.makeText(this,
"MyJobService.onStopJob()",
Toast.LENGTH_SHORT).show();
return false;
}
}

using Location Services fusedlocationapi in Android service -- Receiving only one location update

I'm trying my hand at making a background service that I'd like to run when the app is closed and terminate when the app is open.
as you can see in the code below, I have a Toast message that is supposed that is supposed to display in onLocationChanged(). I am only seeing that message appear once.
Here is what the permission looks like in the manifest:
<application
...
<activity android:name=".activities.ChatUsersActivity" />
<activity android:name=".activities.RequestsActivity"></activity>
<service android:name=".pops.PopService"
android:exported="false"
android:icon="#drawable/usericonmdpi"/>
</application>
And also, here is my Service extended class:
public class PopService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(2);
Runnable backgroundCollector = new BackgroundPopCollector();
private GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
Location mLastLocation;
private PopCityCollection cities;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
// Code to execute when the service is first created
super.onCreate();
buildGoogleApiClient();
}
#Override
public void onDestroy() {
super.onDestroy();
threadPoolExecutor.shutdownNow();
}
#Override
public void onLocationChanged(Location location) {
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
UserLocation.setLatitude(location.getLatitude());
UserLocation.setLongitude(location.getLongitude());
Toast.makeText(getBaseContext(), "Latitude is " + location.getLatitude(), Toast.LENGTH_SHORT).show();
System.out.println(UserLocation.getLatitude()+", "+UserLocation.getLongitude()+" --->BACKGROUND!!");
if(cities==null) {
cities = new PopCityCollection(new LatLng(location.getLatitude(), location.getLongitude()));
cities.findMyCity(this);
}
DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("pops");
db.push().setValue("test");
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(100);
mLocationRequest.setFastestInterval(100);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
threadPoolExecutor.scheduleAtFixedRate(backgroundCollector, 0, 10, TimeUnit.SECONDS);
return START_NOT_STICKY;
}
}
Thank you for any insights you can provide!
-T
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
the above condition will remove the location updates , after first time so remove this code
removeLocationUpdates
Removes all location updates for the given location listener.

GoogleApiClient stops to work properly after GPS turned on/off

I'm trying to implement abstract Activity, whose inheritants would be able to get Location data. I'm strictly following this guide, that seems pretty straightforward.
But after all I have a few problems. Google API should pass location data even if GPS is off, getting this from network data or even passive data from other apps. But in my case it works only with GPS enabled.
Another question is what happens when I turn GPS off/on. In my case after that I can't het any data at all.
Here's the class that makes everything done.
public abstract class LocationProviderActivity extends BaseDrawerActivity
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private final String TAG = "LOCATION";
GoogleApiClient client;
protected Location location;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (client == null) {
client = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
#Override
protected void onStart() {
client.connect();
Log.i(TAG, "Connected");
super.onStart();
}
#Override
protected void onStop() {
client.disconnect();
Log.i(TAG, "Disconnected");
super.onStop();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
//TODO
return;
}
location = LocationServices.FusedLocationApi.getLastLocation(client);
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Location services connected.");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Location services suspended. Please reconnect.");
}
#Override
public void onLocationChanged(Location location) {
}
}

Location Based Services on Android

I have following activity which uses GoogleApiClient:
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener
{
private final String TAG = "My App";
private TextView textView;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG,"After layout setting");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
textView = (TextView) findViewById(R.id.location);
Log.v(TAG,"After mGoogleClient");
}
#Override
protected void onStart() {
Log.v(TAG,"On Start");
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
Log.v(TAG,"On Stop");
mGoogleApiClient.disconnect();
super.onStop();
}
#Override
public void onConnected(Bundle bundle) {
Log.v(TAG,"on Connected");
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(1000);
Log.v(TAG,"After Setting mLocationRequest");
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) {
// 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.
Log.v(TAG,"Checking block");
return;
}
Log.v(TAG,"After Checking block");
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
Log.v(TAG,"After Request Location Updates");
}
#Override
public void onConnectionSuspended(int i) {
Log.v(TAG,"Suspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.v(TAG,connectionResult.toString());
}
#Override
public void onLocationChanged(Location location) {
Log.v(TAG,location.toString());
textView.setText(location.toString());
}
}
After running this piece of code I get a message in logcat stating:
ConnectionResult{statusCode=SERVICE_VERSION_UPDATE_REQUIRED, resolution=null, message=null}
Which is due to execution of OnConnectionFailed function ..
How to resolve this problem?
You need to update your Google Play Services. Are you running your code in emulator? If so, try again with higher API level. This code works fine in real device.
It looks like the version of Google Play Services that you're building your app with is higher than the version you currently have installed on your test device, as previously answered here:
When does isGooglePlayServicesAvailable return SERVICE_VERSION_UPDATE_REQUIRED?

on locaton changed never gets called in android google client api

I am developing app which require location services my code is as follow.
The main problem is on location changed never gets called
public class MainActivity extends ActionBarActivity implements
ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
protected GoogleApiClient mGoogleApiClient;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 100;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
protected LocationRequest mLocationRequest;
protected static final String TAG = "location-updates-sample";
protected Location mCurrentLocation;
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button)findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG,"btn is clicked");
buildGoogleApiClient();
Log.i(TAG,"build google api completed");
mGoogleApiClient.connect();
Log.i(TAG,"client conneted");
}
});
}
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
Log.i(TAG,"from onconnected method");
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
Log.i(TAG,"on location changed");
Log.i(TAG,String.valueOf(mCurrentLocation.getLongitude()));
Log.i(TAG,String.valueOf(mCurrentLocation.getLatitude()));
Toast.makeText(this,"liocation changed", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
I have done "ACCESS_FINE_LOCATION" in manifest. also set the setting to be ''gps'' device only.
i am getting the result when i click on button
location-updates-sample﹕ btn is clicked
location-updates-sample﹕ Building GoogleApiClient
location-updates-sample﹕ build google api completed
location-updates-sample﹕ client conneted
location-updates-sample﹕ from onconnected method
whats wrong with my code
I use the same code to handle locations.
Don't know if it's the correct solution but try to replace
mLocationRequest = new LocationRequest();
with
mLocationRequest = LocationRequest.create();
Works for me.
I don't know english. Hope i can help:
I think your UPDATE_INTERVAL_IN_MILLISECONDS = 100( 0,1 s) and FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS ( 100/ 2 = 0.05s) is very fast with gps chip . you should set it > 1s . some thing like this
UPDATE_INTERVAL_IN_MILLISECONDS = 10 * 1000;// 10s
FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 5 *1000; // 5s
Make Sure you have added .addApi(LocationServices.API)
I was not getting onLocationChanged(Location location) call in my emulator.
current_location =LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Using this can find current location.
Hope this will help you.

Categories

Resources