Reputation: 17
I have a problem with the new Google Play Service and its GPS function.
Right now I am using this code:
package my.app.client;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import java.text.DateFormat;
import java.util.Date;
/**
* Using location settings.
* <p/>
* Uses the {@link com.google.android.gms.location.SettingsApi} to ensure that the device's system
* settings are properly configured for the app's location needs. When making a request to
* Location services, the device's system settings may be in a state that prevents the app from
* obtaining the location data that it needs. For example, GPS or Wi-Fi scanning may be switched
* off. The {@code SettingsApi} makes it possible to determine if a device's system settings are
* adequate for the location request, and to optionally invoke a dialog that allows the user to
* enable the necessary settings.
* <p/>
* This sample allows the user to request location updates using the ACCESS_FINE_LOCATION setting
* (as specified in AndroidManifest.xml). The sample requires that the device has location enabled
* and set to the "High accuracy" mode. If location is not enabled, or if the location mode does
* not permit high accuracy determination of location, the activity uses the {@code SettingsApi}
* to invoke a dialog without requiring the developer to understand which settings are needed for
* different Location requirements.
*/
public class NewGPSClient extends ActionBarActivity implements
ConnectionCallbacks,
OnConnectionFailedListener,
LocationListener,
ResultCallback<LocationSettingsResult> {
protected static final String TAG = "location-settings";
/**
* Constant used in the location settings dialog.
*/
protected static final int REQUEST_CHECK_SETTINGS = 0x1;
/**
* 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 KEY_REQUESTING_LOCATION_UPDATES = "requesting-location-updates";
protected final static String KEY_LOCATION = "location";
protected final static String KEY_LAST_UPDATED_TIME_STRING = "last-updated-time-string";
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest;
/**
* Stores the types of location services the client is interested in using. Used for checking
* settings to determine if the device has optimal location settings.
*/
protected LocationSettingsRequest mLocationSettingsRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation;
// UI Widgets.
protected Button mStartUpdatesButton;
protected Button mStopUpdatesButton;
protected TextView mLastUpdateTimeTextView;
protected TextView mLatitudeTextView;
protected TextView mLongitudeTextView;
/**
* Tracks the status of the location updates request. Value changes when the user presses the
* Start Updates and Stop Updates buttons.
*/
protected Boolean mRequestingLocationUpdates;
/**
* Time when the location was updated represented as a String.
*/
protected String mLastUpdateTime;
@Override
public void onCreate(Bundle savedInstanceState) {
//super.onCreate(savedInstanceState);
//setContentView(R.layout.main_activity);
// Locate the UI widgets.
/*mStartUpdatesButton = (Button) findViewById(R.id.start_updates_button);
mStopUpdatesButton = (Button) findViewById(R.id.stop_updates_button);
mLatitudeTextView = (TextView) findViewById(R.id.latitude_text);
mLongitudeTextView = (TextView) findViewById(R.id.longitude_text);
mLastUpdateTimeTextView = (TextView) findViewById(R.id.last_update_time_text);*/
Log.e(TAG, "NEWGPSCLIENT created successfully!");
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
// Update values using data stored in the Bundle.
//updateValuesFromBundle(savedInstanceState);
// Kick off the process of building the GoogleApiClient, LocationRequest, and
// LocationSettingsRequest objects.
buildGoogleApiClient();
createLocationRequest();
buildLocationSettingsRequest();
startLocationUpdates();
}
/**
* Updates fields based on data stored in the bundle.
*
* @param savedInstanceState The activity state saved in the Bundle.
*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// Update the value of mRequestingLocationUpdates from the Bundle, and make sure that
// the Start Updates and Stop Updates buttons are correctly enabled or disabled.
if (savedInstanceState.keySet().contains(KEY_REQUESTING_LOCATION_UPDATES)) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(
KEY_REQUESTING_LOCATION_UPDATES);
}
// Update the value of mCurrentLocation from the Bundle and update the UI to show the
// correct latitude and longitude.
if (savedInstanceState.keySet().contains(KEY_LOCATION)) {
// Since KEY_LOCATION was found in the Bundle, we can be sure that mCurrentLocation
// is not null.
mCurrentLocation = savedInstanceState.getParcelable(KEY_LOCATION);
}
// Update the value of mLastUpdateTime from the Bundle and update the UI.
if (savedInstanceState.keySet().contains(KEY_LAST_UPDATED_TIME_STRING)) {
mLastUpdateTime = savedInstanceState.getString(KEY_LAST_UPDATED_TIME_STRING);
}
updateUI();
}
}
/**
* 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();
}
/**
* 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();
// 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(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(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* Uses a {@link com.google.android.gms.location.LocationSettingsRequest.Builder} to build
* a {@link com.google.android.gms.location.LocationSettingsRequest} that is used for checking
* if a device has the needed location settings.
*/
protected void buildLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
/**
* Check if the device's location settings are adequate for the app's needs using the
* {@link com.google.android.gms.location.SettingsApi#checkLocationSettings(GoogleApiClient,
* LocationSettingsRequest)} method, with the results provided through a {@code PendingResult}.
*/
protected void checkLocationSettings() {
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(
mGoogleApiClient,
mLocationSettingsRequest
);
result.setResultCallback(this);
}
/**
* The callback invoked when
* {@link com.google.android.gms.location.SettingsApi#checkLocationSettings(GoogleApiClient,
* LocationSettingsRequest)} is called. Examines the
* {@link com.google.android.gms.location.LocationSettingsResult} object and determines if
* location settings are adequate. If they are not, begins the process of presenting a location
* settings dialog to the user.
*/
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
Log.i(TAG, "All location settings are satisfied.");
startLocationUpdates();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to" +
"upgrade location settings ");
/* try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
// status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.i(TAG, "PendingIntent unable to execute request.");
}*/
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog " +
"not created.");
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
Log.i(TAG, "User agreed to make required location settings changes.");
startLocationUpdates();
break;
case Activity.RESULT_CANCELED:
Log.i(TAG, "User chose not to make required location settings changes.");
break;
}
break;
}
}
/**
* Handles the Start Updates button and requests start of location updates. Does nothing if
* updates have already been requested.
*/
public void startUpdatesButtonHandler(View view) {
checkLocationSettings();
}
/**
* Handles the Stop Updates button, and requests removal of location updates.
*/
public void stopUpdatesButtonHandler(View view) {
// 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.
stopLocationUpdates();
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient,
mLocationRequest,
this
).setResultCallback(new ResultCallback<Status>() {
public void onResult(Status status) {
mRequestingLocationUpdates = true;
//setButtonsEnabledState();
}
});
}
/**
* Updates all UI fields.
*/
private void updateUI() {
//setButtonsEnabledState();
updateLocationUI();
}
/**
* Disables both buttons when functionality is disabled due to insuffucient location settings.
* Otherwise ensures that only one button is enabled at any time. The Start Updates button is
* enabled if the user is not requesting location updates. The Stop Updates button is enabled
* if the user is requesting location updates.
*/
/*private void setButtonsEnabledState() {
if (mRequestingLocationUpdates) {
mStartUpdatesButton.setEnabled(false);
mStopUpdatesButton.setEnabled(true);
} else {
mStartUpdatesButton.setEnabled(true);
mStopUpdatesButton.setEnabled(false);
}
}*/
/**
* Sets the value of the UI fields for the location latitude, longitude and last update time.
*/
private void updateLocationUI() {
if (mCurrentLocation != null) {
mLatitudeTextView.setText(String.valueOf(mCurrentLocation.getLatitude()));
mLongitudeTextView.setText(String.valueOf(mCurrentLocation.getLongitude()));
mLastUpdateTimeTextView.setText(mLastUpdateTime);
}
}
/**
* 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.
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient,
this
).setResultCallback(new ResultCallback<Status>() {
public void onResult(Status status) {
mRequestingLocationUpdates = false;
//setButtonsEnabledState();
}
});
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
public void onResume() {
super.onResume();
// Within {@code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
@Override
protected void onPause() {
super.onPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
@Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "Connected to GoogleApiClient");
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
}
}
/**
* Callback that fires when the location changes.
*/
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
/*Toast.makeText(this, getResources().getString(R.string.location_updated_message),
Toast.LENGTH_SHORT).show();*/
}
public void onConnectionSuspended(int cause) {
Log.i(TAG, "Connection suspended");
}
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(KEY_REQUESTING_LOCATION_UPDATES, mRequestingLocationUpdates);
savedInstanceState.putParcelable(KEY_LOCATION, mCurrentLocation);
savedInstanceState.putString(KEY_LAST_UPDATED_TIME_STRING, mLastUpdateTime);
super.onSaveInstanceState(savedInstanceState);
}
}
Which is more or less an example code of the newest Play Store location services. Anyway if I want to activate the service by using this code:
NewGPSClient GPSM = new NewGPSClient();
GPSM.onCreate(savedInstanceState);
There is the following error log I get:
05-09 18:45:11.344: I/location-settings(14284): Building GoogleApiClient 05-09 18:45:11.344: D/AndroidRuntime(14284): Shutting down VM 05-09 18:45:11.344: W/dalvikvm(14284): threadid=1: thread exiting with uncaught exception (group=0x4180ac08) 05-09 18:45:11.349: E/AndroidRuntime(14284): FATAL EXCEPTION: main 05-09 18:45:11.349: E/AndroidRuntime(14284): Process: my.app.client, PID: 14284 05-09 18:45:11.349: E/AndroidRuntime(14284): java.lang.RuntimeException: Unable to start activity ComponentInfo{my.app.client/my.app.client.LauncherActivity}: java.lang.NullPointerException 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2449) 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2509) 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.app.ActivityThread.access$900(ActivityThread.java:172) 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1308) 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.os.Handler.dispatchMessage(Handler.java:102) 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.os.Looper.loop(Looper.java:146) 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.app.ActivityThread.main(ActivityThread.java:5694) 05-09 18:45:11.349: E/AndroidRuntime(14284): at java.lang.reflect.Method.invokeNative(Native Method) 05-09 18:45:11.349: E/AndroidRuntime(14284): at java.lang.reflect.Method.invoke(Method.java:515) 05-09 18:45:11.349: E/AndroidRuntime(14284): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291) 05-09 18:45:11.349: E/AndroidRuntime(14284): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107) 05-09 18:45:11.349: E/AndroidRuntime(14284): at dalvik.system.NativeStart.main(Native Method) 05-09 18:45:11.349: E/AndroidRuntime(14284): Caused by: java.lang.NullPointerException 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.content.ContextWrapper.getMainLooper(ContextWrapper.java:109) 05-09 18:45:11.349: E/AndroidRuntime(14284): at com.google.android.gms.common.api.GoogleApiClient$Builder.(Unknown Source) 05-09 18:45:11.349: E/AndroidRuntime(14284): at my.app.client.NewGPSClient.buildGoogleApiClient(NewGPSClient.java:183) 05-09 18:45:11.349: E/AndroidRuntime(14284): at my.app.client.NewGPSClient.onCreate(NewGPSClient.java:142) 05-09 18:45:11.349: E/AndroidRuntime(14284): at my.app.client.LauncherActivity.onCreate(LauncherActivity.java:97) 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.app.Activity.performCreate(Activity.java:5541) 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093) 05-09 18:45:11.349: E/AndroidRuntime(14284): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2413) 05-09 18:45:11.349: E/AndroidRuntime(14284): ... 11 more
So with that new code I get the following errors anyway:
05-09 22:10:22.809: W/dalvikvm(25531): threadid=1: thread exiting with uncaught exception (group=0x4180ac08) 05-09 22:10:22.809: E/AndroidRuntime(25531): FATAL EXCEPTION: main 05-09 22:10:22.809: E/AndroidRuntime(25531): Process: my.app.client, PID: 25531 05-09 22:10:22.809: E/AndroidRuntime(25531): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{my.app.client/my.app.client.MainActivity}: java.lang.ClassNotFoundException: Didn't find class "my.app.client.MainActivity" on path: DexPathList[[zip file "/data/app/my.app.client-68.apk"],nativeLibraryDirectories=[/data/app-lib/my.app.client-68, /vendor/lib, /system/lib]] 05-09 22:10:22.809: E/AndroidRuntime(25531): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2321) 05-09 22:10:22.809: E/AndroidRuntime(25531): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2509) 05-09 22:10:22.809: E/AndroidRuntime(25531): at android.app.ActivityThread.access$900(ActivityThread.java:172) 05-09 22:10:22.809: E/AndroidRuntime(25531): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1308) 05-09 22:10:22.809: E/AndroidRuntime(25531): at android.os.Handler.dispatchMessage(Handler.java:102) 05-09 22:10:22.809: E/AndroidRuntime(25531): at android.os.Looper.loop(Looper.java:146) 05-09 22:10:22.809: E/AndroidRuntime(25531): at android.app.ActivityThread.main(ActivityThread.java:5694) 05-09 22:10:22.809: E/AndroidRuntime(25531): at java.lang.reflect.Method.invokeNative(Native Method) 05-09 22:10:22.809: E/AndroidRuntime(25531): at java.lang.reflect.Method.invoke(Method.java:515) 05-09 22:10:22.809: E/AndroidRuntime(25531): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291) 05-09 22:10:22.809: E/AndroidRuntime(25531): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107) 05-09 22:10:22.809: E/AndroidRuntime(25531): at dalvik.system.NativeStart.main(Native Method) 05-09 22:10:22.809: E/AndroidRuntime(25531): Caused by: java.lang.ClassNotFoundException: Didn't find class "my.app.client.MainActivity" on path: DexPathList[[zip file "/data/app/my.app.client-68.apk"],nativeLibraryDirectories=[/data/app-lib/my.app.client-68, /vendor/lib, /system/lib]] 05-09 22:10:22.809: E/AndroidRuntime(25531): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:67) 05-09 22:10:22.809: E/AndroidRuntime(25531): at java.lang.ClassLoader.loadClass(ClassLoader.java:497) 05-09 22:10:22.809: E/AndroidRuntime(25531): at java.lang.ClassLoader.loadClass(ClassLoader.java:457) 05-09 22:10:22.809: E/AndroidRuntime(25531): at android.app.Instrumentation.newActivity(Instrumentation.java:1067) 05-09 22:10:22.809: E/AndroidRuntime(25531): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2312) 05-09 22:10:22.809: E/AndroidRuntime(25531): ... 11 more
So here the manifest:
> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.app.client"
android:versionCode="59"
android:versionName="2.7.1" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:debuggable="true">
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
<service android:name="my.app.client.Client" >
<intent-filter>
<action android:name=".Client" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
<service android:name=".GPSClient">
<intent-filter>
<action android:name=".GPSClient" />
</intent-filter>
</service>
<activity android:name="my.app.client.LauncherActivity" android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
In fact, the GPS is now in the class LauncherActivity.
Upvotes: 0
Views: 5130
Reputation: 15726
Add the following line in your build.gradle file,
dependencies {
...
implementation "com.google.android.gms:play-services-location:+"
}
Upvotes: 0
Reputation: 12823
I was receiving a NoClassDefFoundError
and it was because I had included play-services-gcm
but forgot to include play-services-location
.
compile 'com.google.android.gms:play-services-gcm:7.5.0'
compile 'com.google.android.gms:play-services-location:7.5.0'
Not 100% related to your error, but this post is in the top 10 when googling java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.location.LocationServices" on path
Upvotes: 6
Reputation: 43342
I was able to get your code working with a couple minor changes, and just used the latitude, longitude, and last update time to test it (I just un-commented the lines pertaining to those fields).
First of all, you should never create the Activity using new NewGPSClient();
.
Instead, use startActivity()
like below:
Intent i = new Intent(this, NewGPSClient.class);
startActivity(i);
Second, you were calling startLocationUpdates();
before the asynchronous call to connect to the SDK had completed.
I moved the call to startLocationUpdates();
into onConnected(Bundle connectionHint)
, and now it works.
Here is the full working code:
public class NewGPSClient extends ActionBarActivity implements
ConnectionCallbacks,
OnConnectionFailedListener,
LocationListener,
ResultCallback<LocationSettingsResult> {
protected static final String TAG = "location-settings";
/**
* Constant used in the location settings dialog.
*/
protected static final int REQUEST_CHECK_SETTINGS = 0x1;
/**
* 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 KEY_REQUESTING_LOCATION_UPDATES = "requesting-location-updates";
protected final static String KEY_LOCATION = "location";
protected final static String KEY_LAST_UPDATED_TIME_STRING = "last-updated-time-string";
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest;
/**
* Stores the types of location services the client is interested in using. Used for checking
* settings to determine if the device has optimal location settings.
*/
protected LocationSettingsRequest mLocationSettingsRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation;
// UI Widgets.
protected Button mStartUpdatesButton;
protected Button mStopUpdatesButton;
protected TextView mLastUpdateTimeTextView;
protected TextView mLatitudeTextView;
protected TextView mLongitudeTextView;
/**
* Tracks the status of the location updates request. Value changes when the user presses the
* Start Updates and Stop Updates buttons.
*/
protected Boolean mRequestingLocationUpdates;
/**
* Time when the location was updated represented as a String.
*/
protected String mLastUpdateTime;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
// Locate the UI widgets.
/*mStartUpdatesButton = (Button) findViewById(R.id.start_updates_button);
mStopUpdatesButton = (Button) findViewById(R.id.stop_updates_button);
*/
mLatitudeTextView = (TextView) findViewById(R.id.latitude_text);
mLongitudeTextView = (TextView) findViewById(R.id.longitude_text);
mLastUpdateTimeTextView = (TextView) findViewById(R.id.last_update_time_text);
Log.e(TAG, "NEWGPSCLIENT created successfully!");
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
// Update values using data stored in the Bundle.
//updateValuesFromBundle(savedInstanceState);
// Kick off the process of building the GoogleApiClient, LocationRequest, and
// LocationSettingsRequest objects.
buildGoogleApiClient();
createLocationRequest();
buildLocationSettingsRequest();
//startLocationUpdates(); //Don't call this here, the SDK is not connected yet
}
/**
* Updates fields based on data stored in the bundle.
*
* @param savedInstanceState The activity state saved in the Bundle.
*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// Update the value of mRequestingLocationUpdates from the Bundle, and make sure that
// the Start Updates and Stop Updates buttons are correctly enabled or disabled.
if (savedInstanceState.keySet().contains(KEY_REQUESTING_LOCATION_UPDATES)) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(
KEY_REQUESTING_LOCATION_UPDATES);
}
// Update the value of mCurrentLocation from the Bundle and update the UI to show the
// correct latitude and longitude.
if (savedInstanceState.keySet().contains(KEY_LOCATION)) {
// Since KEY_LOCATION was found in the Bundle, we can be sure that mCurrentLocation
// is not null.
mCurrentLocation = savedInstanceState.getParcelable(KEY_LOCATION);
}
// Update the value of mLastUpdateTime from the Bundle and update the UI.
if (savedInstanceState.keySet().contains(KEY_LAST_UPDATED_TIME_STRING)) {
mLastUpdateTime = savedInstanceState.getString(KEY_LAST_UPDATED_TIME_STRING);
}
updateUI();
}
}
/**
* 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();
}
/**
* 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();
// 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(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(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* Uses a {@link com.google.android.gms.location.LocationSettingsRequest.Builder} to build
* a {@link com.google.android.gms.location.LocationSettingsRequest} that is used for checking
* if a device has the needed location settings.
*/
protected void buildLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
/**
* Check if the device's location settings are adequate for the app's needs using the
* {@link com.google.android.gms.location.SettingsApi#checkLocationSettings(GoogleApiClient,
* LocationSettingsRequest)} method, with the results provided through a {@code PendingResult}.
*/
protected void checkLocationSettings() {
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(
mGoogleApiClient,
mLocationSettingsRequest
);
result.setResultCallback(this);
}
/**
* The callback invoked when
* {@link com.google.android.gms.location.SettingsApi#checkLocationSettings(GoogleApiClient,
* LocationSettingsRequest)} is called. Examines the
* {@link com.google.android.gms.location.LocationSettingsResult} object and determines if
* location settings are adequate. If they are not, begins the process of presenting a location
* settings dialog to the user.
*/
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
Log.i(TAG, "All location settings are satisfied.");
startLocationUpdates();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to" +
"upgrade location settings ");
/* try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
// status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.i(TAG, "PendingIntent unable to execute request.");
}*/
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog " +
"not created.");
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
Log.i(TAG, "User agreed to make required location settings changes.");
startLocationUpdates();
break;
case Activity.RESULT_CANCELED:
Log.i(TAG, "User chose not to make required location settings changes.");
break;
}
break;
}
}
/**
* Handles the Start Updates button and requests start of location updates. Does nothing if
* updates have already been requested.
*/
public void startUpdatesButtonHandler(View view) {
checkLocationSettings();
}
/**
* Handles the Stop Updates button, and requests removal of location updates.
*/
public void stopUpdatesButtonHandler(View view) {
// 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.
stopLocationUpdates();
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient,
mLocationRequest,
this
).setResultCallback(new ResultCallback<Status>() {
public void onResult(Status status) {
mRequestingLocationUpdates = true;
//setButtonsEnabledState();
}
});
}
/**
* Updates all UI fields.
*/
private void updateUI() {
//setButtonsEnabledState();
updateLocationUI();
}
/**
* Disables both buttons when functionality is disabled due to insuffucient location settings.
* Otherwise ensures that only one button is enabled at any time. The Start Updates button is
* enabled if the user is not requesting location updates. The Stop Updates button is enabled
* if the user is requesting location updates.
*/
/*private void setButtonsEnabledState() {
if (mRequestingLocationUpdates) {
mStartUpdatesButton.setEnabled(false);
mStopUpdatesButton.setEnabled(true);
} else {
mStartUpdatesButton.setEnabled(true);
mStopUpdatesButton.setEnabled(false);
}
}*/
/**
* Sets the value of the UI fields for the location latitude, longitude and last update time.
*/
private void updateLocationUI() {
if (mCurrentLocation != null) {
mLatitudeTextView.setText(String.valueOf(mCurrentLocation.getLatitude()));
mLongitudeTextView.setText(String.valueOf(mCurrentLocation.getLongitude()));
mLastUpdateTimeTextView.setText(mLastUpdateTime);
}
}
/**
* 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.
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient,
this
).setResultCallback(new ResultCallback<Status>() {
public void onResult(Status status) {
mRequestingLocationUpdates = false;
//setButtonsEnabledState();
}
});
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
public void onResume() {
super.onResume();
// Within {@code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
@Override
protected void onPause() {
super.onPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
@Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "Connected to GoogleApiClient");
startLocationUpdates(); //add this here
// If the initial location was never previously requested, we use
// FusedLocationApi.getLastLocation() to get it. If it was previously requested, we store
// its value in the Bundle and check for it in onCreate(). We
// do not request it again unless the user specifically requests location updates by pressing
// the Start Updates button.
//
// Because we cache the value of the initial location in the Bundle, it means that if the
// user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
}
}
/**
* Callback that fires when the location changes.
*/
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
/*Toast.makeText(this, getResources().getString(R.string.location_updated_message),
Toast.LENGTH_SHORT).show();*/
}
public void onConnectionSuspended(int cause) {
Log.i(TAG, "Connection suspended");
}
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(KEY_REQUESTING_LOCATION_UPDATES, mRequestingLocationUpdates);
savedInstanceState.putParcelable(KEY_LOCATION, mCurrentLocation);
savedInstanceState.putString(KEY_LAST_UPDATED_TIME_STRING, mLastUpdateTime);
super.onSaveInstanceState(savedInstanceState);
}
}
Upvotes: 1