I am making an android app about locating friends on map. So far I have the map up and running, and the fused location also running but from a different class which extends thread so the app will keep listening to location changed throughout its life cycle.
I have a problem when I initialize the map, the problem is either the locationListener will keep working but the map won't load, or the map will load but the locationListener will take a long time to get a new location.
I also have a problem when sending the current location from the Thread activity to the map activity so i animate the camera to a new loaction.
Here is the error i get :
12-22 23:22:38.847 17339-17339/com.example.swampsoftware.blbmonitor
W/dalvikvm: threadid=1: thread exiting with uncaught exception
(group=0x41ee6300) 12-22 23:22:38.852
17339-17339/com.example.swampsoftware.blbmonitor E/AndroidRuntime:
FATAL EXCEPTION: main
java.lang.NullPointerException
at
com.example.swampsoftware.blbmonitor.Maps.gotoLocation(Maps.java:232)
at
com.example.swampsoftware.blbmonitor.GetLocation.onLocationChanged(GetLocation.java:81)
at
com.google.android.gms.location.internal.zzk$zzb.handleMessage(Unknown
Source)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4898)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
at dalvik.system.NativeStart.main(Native Method)
So the problem happens once the method "onLocationChanged" is called.
I believe that this is a thread caused problem, but I don't understand what is the problem nor how to fix it, here is the code i made :
Maps.class :
public class Maps extends FragmentActivity implements OnMapReadyCallback{
private GoogleMap mMap;
private Double locationLat;
private Double locationLng;
private Context context;
private static boolean isVisible;
// Defining parse object
ParseObject locationObject;
//Declaring Tabhost
TabHost tabHost;
public Maps() {
}
public Maps(Context context) {
this.context = context;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isVisible = true;
setContentView(R.layout.activity_gpslocation);
// Initialize google map
initMap();
}
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
// Initialize GoogleMap -> mMap
public void initMap() {
if (mMap == null) {
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
} else {
Toast.makeText(getApplicationContext(), "Can't start map", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
// Method that saves current location
private void setCurrentLocation(Double lat, Double lng) {
locationLat = lat;
locationLng = lng;
}
// Get method for lng
public Double getLocationLat() {
return locationLat;
}
public Double getLocationLng() {
return locationLng;
}
// Method that animates the camera to a new location
public void gotoLocation(Location location) {
LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(ll, 15);
mMap.animateCamera(update);
}
#Override
protected void onResume() {
super.onResume();
initMap();
isVisible = true;
}
#Override
protected void onPause() {
super.onPause();
isVisible = false;
}
protected void onDestroy() {
super.onDestroy();
isVisible = false;
}
public boolean getIsVisible() {
return isVisible;
}
// Method that is called when map is connected, initializes the locationRequest.
public void onConnected(Bundle bundle) {
}
And this is the Thread class that will keep listening to the new location using fused location :
GetLocation :
public class GetLocation extends Thread implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient googleApiClient; // Object that is used to connect to google maps API, must be built to use fused location
private LocationRequest locationRequest; //Object that requests a quality of service for location updates from fused location
public Context context;
public volatile boolean isRunning = true; // boolean to stop the thread loop
// Declaring location variables
private Double locationLat;
private Double locationLng;
// Declaring objects
private ParseData parseData;
private Maps maps = new Maps();
/***
* run method for thread
***/
public void run() {
//Initializing objects
parseData = new ParseData();
googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
googleApiClient.connect();
}
public void terminate() {
isRunning = false;
}
// Getters
public Double getLocationLat() {
return locationLat;
}
public Double getLocationLng() {
return locationLng;
}
/***
* Auto-generated methods
***/
#Override
public void onLocationChanged(Location location) {
if (!isRunning) {
googleApiClient.disconnect();
return;
} else if (location != null) {
locationLat = location.getLatitude();
locationLng = location.getLongitude();
parseData.GetLocationParse(locationLat, locationLng);
System.out.println(locationLat + " " + locationLng);
// Check is map is active
if(maps.getIsVisible()) {
System.out.println("Maps is in foreground");
maps.gotoLocation(location);
} else {
System.out.println("Maps isn't running");
}
}
}
#Override
public void onConnected(Bundle bundle) {
locationRequest = locationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(7000);
locationRequest.setFastestInterval(5000);
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
Thank you.
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I've created a LocationBuddy class that is responsible for providing the location for all my other Fragments and activity that needs it. I create an instance of this class in the fragments for instance and then call the method getUpdatedLocation() to receive the location.
The problem is that the getUpdatedLocation method returns null when called outside of the LocationBuddy class and I think that I've initialized everything fine.
LocationBuddy Class
public class LocationBuddy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener
{
GoogleApiClient client;
Context context;
// Private instance variables
private Location updatedLocation;
private boolean clientConnected = false;
private boolean locationUpdated = false;
private int updateInterval;
private final static String TAG = "LocationBuddy";
private String lastUpdateTime;
private Location lastLocation;
// Create the LocationBuddy Object and initialize it with the current context
public LocationBuddy (Context c, int milliseconds)
{
this.context = c;
this.updateInterval = milliseconds;
this.updatedLocation = null;
this.lastLocation = null;
Log.d(TAG, "LocationBuddy created with an update Interval of "+updateInterval+" milliseconds.");
}
// Google Location methods
#Override
public void onConnected(#Nullable Bundle bundle)
{
lastLocation = LocationServices.FusedLocationApi.getLastLocation(client);
if (lastLocation != null)
{
updatedLocation = lastLocation;
}
// Create a location request called locationRequest
LocationRequest locationRequest = LocationRequest.create();
// Set it's priority to high accuracy
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set it to update to an interval set on object creation
locationRequest.setInterval(updateInterval);
// If another app is requesting location updates
locationRequest.setFastestInterval(updateInterval);
// Call requestLocationUpdates in the Api with this request
LocationServices.FusedLocationApi.requestLocationUpdates(client, locationRequest, this);
}
#Override
public void onConnectionSuspended(int i)
{
Log.d(TAG, "The Google API client has been suspended");
}
#Override
public void onLocationChanged(Location location)
{
Log.d(TAG, "The location has been changed to " + location.toString());
locationUpdated = true;
lastLocation = location;
updatedLocation = lastLocation;
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult)
{
}
// Public Methods
public void initialize()
{
// Build the GoogleApi Client
client = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
connectToGoogleApiClient();
}
public void connectToGoogleApiClient()
{
client.connect();
clientConnected = true;
}
public void disconnectFromGoogleApiClient()
{
client.disconnect();
clientConnected = false;
}
public String statusReport()
{
return "Location Buddy: Client connected: "+clientConnected+", Location updated: "+locationUpdated+", Update interval: "+updateInterval;
}
public Location getUpdatedLocation()
{
return updatedLocation;
}
public int getUpdateInterval()
{
return updateInterval;
}
public boolean isLocationUpdated()
{
return locationUpdated;
}
public boolean isClientConnected()
{
return clientConnected;
}
// Return a String description of this instance
public String toString()
{
return "LocationBuddy[updatedLocation=" + updatedLocation + ",interval=" + updateInterval + ", clientConnected="+clientConnected+ ", locationUpdated="+locationUpdated+"]";
}
}
This is a snippet from the PackageListFragment.java class which uses this LocationBuddy object.
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
courier = new Courier(getContext());
buddy = new LocationBuddy(getContext(), 1000);
buddy.initialize();
}
And this is called from the OnActivityCreated method in PackageListFragment class
currentLocation = buddy.getUpdatedLocation();
And this is the error from logcat:
07-22 16:13:24.351 27538-27538/com.shipwebsource.courier E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.shipwebsource.courier, PID: 27538
java.lang.NullPointerException
at com.shipwebsource.courier.Extras.LocationBuddy.getUpdatedLocation(LocationBuddy.java:146)
at com.shipwebsource.courier.PackageListFragment.onActivityCreated(PackageListFragment.java:306)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1983)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1092)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
07-22 16:13:26.119 27538-28841/com.shipwebsource.courier D/dalvikvm:GC_FOR_ALLOC freed 1427K, 18% free 7077K/8620K, paused 8ms, total 8ms
You never set the client variable to be anything. It is only created and never assigned to a new GoogleApiClient until you set up your other stuff (from what I can tell).
I'm trying to build an app that will show me my location in googleMap and will update my location every few seconds.
here is my code:
public class MapsActivity extends FragmentActivity implements
ConnectionCallbacks, OnConnectionFailedListener, LocationListener, OnMapReadyCallback {
protected static final String TAG = "location-updates-sample";
/**
* The desired interval for location updates. Inexact. Updates may be more or less frequent.
*/
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
/**
* The fastest rate for active location updates. Exact. Updates will never be more frequent
* than this value.
*/
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
// Keys for storing activity state in the Bundle.
protected final static String REQUESTING_LOCATION_UPDATES_KEY = "requesting-location-updates-key";
protected final static String LOCATION_KEY = "location-key";
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
protected Location mCurrentLocation;
/**
* Tracks the status of the location updates request. Value changes when the user presses the
* Start Updates and Stop Updates buttons.
*/
protected Boolean mRequestingLocationUpdates;
private GoogleMap mMap;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mRequestingLocationUpdates = false;
updateValuesFromBundle(savedInstanceState);
buildGoogleApiClient();
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
LatLng loc = new LatLng(-34,151);
mMap.addMarker(new MarkerOptions().position(loc).title("my location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(loc));
startUpdates();
}
private void updateValuesFromBundle(Bundle savedInstanceState) {
Log.i(TAG, "Updating values from bundle");
if (savedInstanceState != null) {
if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(
REQUESTING_LOCATION_UPDATES_KEY);
}
// Update the value of mCurrentLocation from the Bundle and update the UI to show the
// correct latitude and longitude.
if (savedInstanceState.keySet().contains(LOCATION_KEY)) {
// Since LOCATION_KEY was found in the Bundle, we can be sure that mCurrentLocation
// is not null.
mCurrentLocation = savedInstanceState.getParcelable(LOCATION_KEY);
}
updateUI();
}
}
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);
}
public void startUpdates() { // start updating location
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
public void stopUpdates() { // stop updating location
if (mRequestingLocationUpdates) {
mRequestingLocationUpdates = false;
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
/**
* Updates the latitude, the longitude, and the last location time in the UI.
*/
private void updateUI() {
LatLng loc = new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
mMap.addMarker(new MarkerOptions().position(loc).title("my location"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(loc));
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
#Override
protected void onPause() {
super.onPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "Connected to GoogleApiClient");
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
updateUI();
}
if (mRequestingLocationUpdates) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
updateUI();
Toast.makeText(this, getResources().getString(R.string.location_updated_message),
Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionSuspended(int cause) {
// 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 onConnectionFailed(ConnectionResult result) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
/**
* Stores activity data in the Bundle.
*/
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, mRequestingLocationUpdates);
savedInstanceState.putParcelable(LOCATION_KEY, mCurrentLocation);
super.onSaveInstanceState(savedInstanceState);
}
}
This code is a part from a sample code from google but i've changed a few things and added the googleMap, its just crashing after onMapReady().
stacktrace:
java.lang.IllegalStateException: GoogleApiClient is not connected yet.
at com.google.android.gms.common.api.internal.zzh.zzb(Unknown Source)
at com.google.android.gms.common.api.internal.zzl.zzb(Unknown Source)
at com.google.android.gms.common.api.internal.zzj.zzb(Unknown Source)
at com.google.android.gms.location.internal.zzd.requestLocationUpdates(Unknown Source)
at com.idanofek.photomap.MapsActivity.startUpdates(MapsActivity.java:135)
at com.idanofek.photomap.MapsActivity.onMapReady(MapsActivity.java:91)
at com.google.android.gms.maps.SupportMapFragment$zza$1.zza(Unknown Source)
at com.google.android.gms.maps.internal.zzo$zza.onTransact(Unknown Source)
at android.os.Binder.transact(Binder.java:387)
at com.google.android.gms.maps.internal.be.a(SourceFile:82)
at com.google.maps.api.android.lib6.e.fb.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Before any operation is executed, the GoogleApiClient must be connect using the 'connect()' method. The client is not considered connected until the onConnected(Bundle) callback has been called.
You should instantiate a client object in your Activity's 'onCreated(Bundle)' method then call connect() on onStart()
You may call startLocationUpdate() from the onConnected() callback
#Override
public void onConnected(Bundle connectionHint) {
...
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
Here's a Google Documentation regarding Location Updates: http://developer.android.com/training/location/receive-location-updates.html
I ask, how to create a script, for android, to get a current location with google maps api v2 for android.
Now my scrpt take the location specifying the cordinates.
I post it my java file:
private GoogleMap mMap;
static final LatLng TutorialsPoint = new LatLng(46.493168,11.3306379);
private GoogleMap googleMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
try {
if (googleMap == null) {
googleMap = ((MapFragment) getFragmentManager().
findFragmentById(R.id.map)).getMap();
}
googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
Marker TP = googleMap.addMarker(new MarkerOptions().
position(TutorialsPoint).title("TutorialsPoint"));
}
catch (Exception e) {
e.printStackTrace();
}
}
In your onCreate() method, type this:
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.mapfragment);
mapFragment.getMapAsync(this);
Make your Activity implement LocationListener, onMapReadyCallback and GoogleApiClient.ConnectionCallbacks interfaces. In the methods of that interfaces:
onMapReady (from onMapReadyCallbacks):
public void onMapReady(GoogleMap map) {
//mapa is your GoogleMap variable
mapa=map;
}
Doing this, you make sure your map is ready for working.
In onConnected method (from GoogleApiClient.ConnectionCallbacks interface) you get your location:
#Override
public void onConnected(Bundle bundle) {
Location lkn=LocationServices.FusedLocationApi.getLastLocation(
gApiClient);
if(myLocation==null){
myLocation=new Location("");
}
if(lkn!=null){
myLocation.setLatitude(lkn.getLatitude());
myLocation.setLongitude(lkn.getLongitude());
}
LocationServices.FusedLocationApi.requestLocationUpdates(
gApiClient, mLocationRequest, this);
}
And finally, in onLocationChanged (from LocationListener interface):
#Override
public void onLocationChanged(Location location) {
//myLocation is a class variable, type Location
myLocation.setLatitude(location.getLatitude());
myLocation.setLongitude(location.getLongitude());
}
So, every time the phone have a new location you will receive it in that method.
You will need to implement this two methods too:
//call this method in your onCreate()
protected synchronized void buildGoogleApiClient() {
//gApiClient is a class variable, type GoogleApiClient
gApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i("Map", "Conection failed");
}
})
.addApi(LocationServices.API)
.build();
gApiClient.connect();
createLocationRequest();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
We have this crash in crashlytics, the weird thing is it happens in onConnected() callback when requesting location updates.
Code:
abstract public class MainService_6_LocationClient extends MainService_5_DriverGpsLocationStoring
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private LocationListener highAccuracyListener;
private GoogleApiClient googleApiClient;
private LocationRequest gpsRequest;
#Override
public void onCreate() {
super.onCreate();
lazyInit();
googleApiClient.connect();
}
#Override public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
lazyInit();
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, gpsRequest,
highAccuracyListener);
}
private void lazyInit() {
if (highAccuracyListener == null) {
highAccuracyListener = new HighAccuracyLocationListener();
}
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this).addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
if (gpsRequest == null) {
gpsRequest = new LocationRequest().setInterval(2000)
.setFastestInterval(1000)
.setSmallestDisplacement(0)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
}
#Override public void onConnectionSuspended(int i) {
Log.w(TAG, "onConnectionSuspended");
lazyInit();
googleApiClient.reconnect();
}
#Override public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(TAG, "onConnectionFailed");
}
#Override public void onDestroy() {
Log.d(TAG, "onDestroy");
if (googleApiClient != null) {
if (googleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient,
highAccuracyListener);
googleApiClient.disconnect();
}
googleApiClient = null;
}
highAccuracyListener = null;
gpsRequest = null;
super.onDestroy();
}
Crash log:
java.lang.IllegalStateException: GoogleApiClient is not connected yet.
at com.google.android.gms.common.internal.o.a()
at com.google.android.gms.common.api.b.b()
at com.google.android.gms.internal.lu.requestLocationUpdates()
at ee.mtakso.driver.service.orderState.MainService_6_LocationClient.onConnected(MainService_6_LocationClient.java:33)
at com.google.android.gms.common.internal.f.d()
at com.google.android.gms.common.api.b.gm()
at com.google.android.gms.common.api.b.d()
at com.google.android.gms.common.api.b$2.onConnected()
at com.google.android.gms.common.internal.f.d()
at com.google.android.gms.common.internal.f.dL()
at com.google.android.gms.common.internal.e$h.b()
at com.google.android.gms.common.internal.e$h.g()
at com.google.android.gms.common.internal.e$b.gU()
at com.google.android.gms.common.internal.e$a.handleMessage()
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4947)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(NativeStart.java)
Doesn't onConnected() imply GoogleApiClient is connected and ready to be used? How can I resolve this?
https://developer.android.com/reference/com/google/android/gms/common/api/GoogleApiClient.html
You should instantiate a client object in your Activity's onCreate(Bundle) method and then call connect() in onStart() and disconnect() in onStop(), regardless of the state.
The implementation of the GoogleApiClient appears designed for only a single instance. It's best to instantiate it only once in onCreate, then perform connections and disconnections using the single instance.
Maybe you should notice, GoogleApiClient.Builder has a method setAccountName(). You should invoke this method with your Google account name. I have tried, and succeeded. I used the following code:
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.setAccountName("李江涛")
.build();
}
if (mLocationRequest == null) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
Try using com.google.android.gms.location.LocationClient instead of GoogleApiClient. Note that the ConnectionCallbacks and OnConnectionFailedListener interfaces that you implement will be slightly different.
Here's a quick example:
class LocationHandler implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener {
private LocationClient client;
void getLocation(Context context) {
client = new LocationClient(context, this, this);
client.connect();
}
#Override
public void onConnected(Bundle connectionHint) {
LocationRequest request = LocationRequest.create();
request.setNumUpdates(1);
client.requestLocationUpdates(request, this);
client.unregisterConnectionCallbacks(this);
}
#Override
public void onDisconnected() { }
#Override
public void onConnectionFailed(ConnectionResult result) {
// handle connection failure
}
#Override
public void onLocationChanged(Location location) {
client.removeLocationUpdates(this);
client.disconnect();
// do stuff with the location
}
}
I have the following code:
public class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
// called when the listener is notified with a location update from the GPS
Log.d("Latitude", Double.toString(loc.getLatitude()));
Log.d("Longitude", Double.toString(loc.getLongitude()));
}
#Override
public void onProviderDisabled(String provider) {
// called when the GPS provider is turned off (user turning off the GPS on the phone)
}
#Override
public void onProviderEnabled(String provider) {
// called when the GPS provider is turned on (user turning on the GPS on the phone)
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
and in my MainActivity
LocationListener locationListener = new MyLocationListener();
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
Now, all I want is to receive the current position of the device ONCE to the MainActivity class (get altitude and longitude variables to use later in the application).
A. how do I stop receiving the location after a single time? The function lm.removeUpdates(listener) can only be called in the MainActivity class.
B. basically the same. How do I connect between the MyLocationListener class and the MainActivity one?
Sorry, I'm a newbie to Android and Java development.
And thanks!
You may use the following sample code:
public class LocationGetter {
private final Context context;
private Location location = null;
private final Cordinate gotLocationLock = new Cordinate();
private final LocationResult locationResult = new LocationResult() {
#Override
public void gotLocation(Location location) {
synchronized (gotLocationLock) {
LocationGetter.this.location = location;
gotLocationLock.notifyAll();
Looper.myLooper().quit();
}
}
};
public LocationGetter(Context context) {
if (context == null)
throw new IllegalArgumentException("context == null");
this.context = context;
}
public void getLocation(int maxWaitingTime, int updateTimeout) {
try {
final int updateTimeoutPar = updateTimeout;
synchronized (gotLocationLock) {
new Thread() {
public void run() {
Looper.prepare();
LocationResolver locationResolver = new LocationResolver();
locationResolver.prepare();
locationResolver.getLocation(context, locationResult, updateTimeoutPar);
Looper.loop();
}
}.start();
gotLocationLock.wait(maxWaitingTime);
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
gteAddress ();
}
public double getLatitude() {
return location.getLatitude();
}
public double getLongitude() {
return location.getLongitude();
}
In your activity use:
_locationGetter=new LocationGetter(context);
_locationGetter.getLocation(200000000, 10000000);
_locationGetter.getLongitude();
_locationGetter.getLatitude();
You can also use LocationManager.removeUpdates after obtining the coordinates (and possibly checking if the coordinates are sufficient for your needs):
#Override
public void onLocationChanged(Location loc) {
// called when the listener is notified with a location update from the GPS
Log.d("Latitude", Double.toString(loc.getLatitude()));
Log.d("Longitude", Double.toString(loc.getLongitude()));
lm.removeUpdates(this);
}