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.
Related
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.
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.
I have the following simple class, which is my main activity. I essentially followed this verbatim from the Android docs. I am running this from my phone through Android Studio. The problem I am running into is I absolutely never get a legitimate location out of this setup. The location object is always null. In reality, I want the location immediately in a similar fashion to how a browser quickly grabs the location through navigator.geolocation.
Is there something weird with the way I have this set up? If not, how do I force a location out of the Fused Location Provider API?
public class MyActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private Location location;
private GoogleApiClient mGoogleApiClient;
private static LocationRequest locationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// Create an instance of GoogleAPIClient.
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
}
#Override
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
private void requestLocationUpdates() {
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(1000);
locationRequest.setFastestInterval(500);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
requestLocationUpdates();
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
location = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
#Override
public void onConnectionSuspended(int i) {}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {}
}
High accuracy means its going to require GPS. If you can't actually contact the GPS satellies (for example, you're inside a building without a clear line to the sky) then it will never send a result. This is actually correct behavior- you wanted high accuracy, its waiting until you have it.
If you're ok with less accuracy, use a different priority type. Otherwise you'll have to accept that you may never get a response.
DO expect it to take a few seconds even under optimal conditions, BTW. It has to find a half dozen sattelites in space before it can give an answer, that takes time.
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?
I have used Fused Location API to get location updates. I am getting updates while setting LocationRequest based on setTimeInterval. But I need only updates on 10m Movement. So i placed setSmallestDisplacement(10) .But when i put setSmallestDisplacement(10), i didnt get updates. Following is my LocationUpdate class
public class LocationManger implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {
GoogleApiClient mLocationClient;
Location mCurrentLocation;
LocationRequest mLocationRequest;
Context mContext;
public LocationManger(Context context) {
super();
mLocationClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mContext = context;
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Helper.showToast("failed", mContext);
}
#Override
public void onConnected(Bundle arg0) {
if (mLocationRequest == null) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setSmallestDisplacement(10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
mLocationClient.connect();
}
/**
* Function to start the location updates
*/
public void startLocationUpdates() {
if (!mLocationClient.isConnected())
mLocationClient.connect();
}
/**
* function to stop the location updates
*/
public void stopUpdatingLocation() {
if (mLocationClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mLocationClient, this);
}
mLocationClient.disconnect();
}
/**
* function to get the current latitude
*/
public double getCurrentLatitude() {
if (mCurrentLocation != null) {
return mCurrentLocation.getLatitude();
}
return 0;
}
/**
* function to get the current longitude
*/
public double getCurrentLongitude() {
if (mCurrentLocation != null) {
return mCurrentLocation.getLongitude();
}
return 0;
}
/**
* function to get the current location
*/
public Location getCurrentLocation() {
return LocationServices.FusedLocationApi.getLastLocation(mLocationClient);
}
}
Please give me a solution if anyone know the issue. Thanks in advance
Use setFastestInterval(0) to allow updates more frequently than called for by setInterval. Otherwise you will miss some updates from displacement