我对新的Google Play服务及其GPS功能有疑问。
现在我正在使用此代码:
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);
}
}
这或多或少是最新Play商店位置服务的示例代码。无论如何,如果我想使用此代码激活服务:
NewGPSClient GPSM = new NewGPSClient();
GPSM.onCreate(savedInstanceState);
我得到以下错误日志:
05-09 18:45:11.344:I / location-settings(14284):构建GoogleApiClient 05-09 18:45:11.344:D / AndroidRuntime(14284):关闭VM 05-09 18:45:11.344:W / dalvikvm(14284):threadid = 1:线程退出时未捕获异常(group = 0x4180ac08) 05-09 18:45:11.349:E / AndroidRuntime(14284):致命异常:主要 05-09 18:45:11.349:E / AndroidRuntime(14284):进程:my.app.client,PID:14284 05-09 18:45:11.349:E / AndroidRuntime(14284):java.lang.RuntimeException:无法启动活动ComponentInfo {my.app.client / my.app.client.LauncherActivity}:java.lang.NullPointerException 05-09 18:45:11.349:E / AndroidRuntime(14284):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2449) 05-09 18:45:11.349:E / AndroidRuntime(14284):在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2509) 05-09 18:45:11.349:E / AndroidRuntime(14284):在android.app.ActivityThread.access $ 900(ActivityThread.java:172) 05-09 18:45:11.349:E / AndroidRuntime(14284):在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1308) 05-09 18:45:11.349:E / AndroidRuntime(14284):在android.os.Handler.dispatchMessage(Handler.java:102) 05-09 18:45:11.349:E / AndroidRuntime(14284):在android.os.Looper.loop(Looper.java:146) 05-09 18:45:11.349:E / AndroidRuntime(14284):在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):引起:java.lang.NullPointerException 05-09 18:45:11.349:E / AndroidRuntime(14284):在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):在android.app.Activity.performCreate(Activity.java:5541) 05-09 18:45:11.349:E / AndroidRuntime(14284):在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093) 05-09 18:45:11.349:E / AndroidRuntime(14284):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2413) 05-09 18:45:11.349:E / AndroidRuntime(14284):... 11更多
所以使用这个新代码我还是会遇到以下错误:
05-09 22:10:22.809:W / dalvikvm(25531):threadid = 1:线程退出未捕获的异常(group = 0x4180ac08) 05-09 22:10:22.809:E / AndroidRuntime(25531):致命异常:主要 05-09 22:10:22.809:E / AndroidRuntime(25531):进程:my.app.client,PID:25531 05-09 22:10:22.809:E / AndroidRuntime(25531):java.lang.RuntimeException:无法实例化活动ComponentInfo {my.app.client / my.app.client.MainActivity}:java.lang.ClassNotFoundException:Didn& #39;找到课程&#34; my.app.client.MainActivity&#34; on path:DexPathList [[zip file&#34; /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):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2321) 05-09 22:10:22.809:E / AndroidRuntime(25531):在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2509) 05-09 22:10:22.809:E / AndroidRuntime(25531):在android.app.ActivityThread.access $ 900(ActivityThread.java:172) 05-09 22:10:22.809:E / AndroidRuntime(25531):在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1308) 05-09 22:10:22.809:E / AndroidRuntime(25531):在android.os.Handler.dispatchMessage(Handler.java:102) 05-09 22:10:22.809:E / AndroidRuntime(25531):在android.os.Looper.loop(Looper.java:146) 05-09 22:10:22.809:E / AndroidRuntime(25531):在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):引起:java.lang.ClassNotFoundException:找不到类&#34; my.app.client.MainActivity&#34; on path:DexPathList [[zip file&#34; /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):在android.app.Instrumentation.newActivity(Instrumentation.java:1067) 05-09 22:10:22.809:E / AndroidRuntime(25531):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2312) 05-09 22:10:22.809:E / AndroidRuntime(25531):... 11 more
所以这里的清单:
> <?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>
事实上,GPS现在属于LauncherActivity类。
答案 0 :(得分:4)
我收到了NoClassDefFoundError
,原因是我收录了play-services-gcm
,但忘了加入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'
与您的错误并非100%相关,但在使用Google java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.location.LocationServices" on path
答案 1 :(得分:1)
我能够让您的代码处理几个小的更改,并且只使用纬度,经度和上次更新时间来测试它(我只是未注释与这些字段相关的行)。
首先,您不应该使用new NewGPSClient();
创建活动。
相反,请使用startActivity()
,如下所示:
Intent i = new Intent(this, NewGPSClient.class);
startActivity(i);
其次,在连接到SDK的异步调用完成之前,您正在调用startLocationUpdates();
。
我将调用移至startLocationUpdates();
进入onConnected(Bundle connectionHint)
,现在可以正常使用。
以下是完整的工作代码:
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);
}
}
答案 2 :(得分:0)
在您的 build.gradle 文件中添加以下行,
dependencies {
...
implementation "com.google.android.gms:play-services-location:+"
}