我在传递给PendingIntent
LocationServices.FusedLocationApi.requestLocationUpdates(GoogleApiClient client, LocationRequest request, PendingIntent callbackIntent)
的字符串时遇到问题。
看来,加入Intent
的用户名额外信息是requestLocationUpdates
试图将IntentService
移交给intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED)
null
的位置。返回User
。
编辑
我已尝试制作一个Parcelable
类来实现mRequestLocationUpdatesIntent.putExtra("username", new User(username));
并将其作为额外内容添加:
Parcelable User
我还尝试将Bundle
置于Bundle userBundle = new Bundle();
userBundle.putParcelable("user", new User(username));
mRequestLocationUpdatesIntent.putExtra("user", userBundle);
内,如此错误报告https://code.google.com/p/android/issues/detail?id=81812中的评论所示:
Bundle userBundle = intent.getBundleExtra("user");
User user = userBundle.getParcelable("user");
String username = user.getUsername();
在我的服务中:
IntentService
然而,这些方法都没有任何区别。每当我对我的意图添加任何额外内容时,在更新发生时,该位置永远不会添加到意图中。
我设置此public class LocationUpdateService extends IntentService {
private final String TAG = "LocationUpdateService";
public LocationUpdateService() {
super("LocationUpdateService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent");
Bundle extras = intent.getExtras();
Log.d(TAG, "keys found inside intent: " + TextUtils.join(", ", extras.keySet()));
String username = intent.getStringExtra("username");
if (username != null) {
Log.d(TAG, "username: " + username);
} else {
Log.d(TAG, "username: null");
}
if (!intent.hasExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED)) {
Log.d(TAG, "intent does not have location :(");
}
Location location = intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
if (location == null) {
Log.d(TAG, "location == null :(");
}
Log.d(TAG, "latitude " + String.valueOf(location.getLatitude()));
Log.d(TAG, "longitude " + String.valueOf(location.getLongitude()));
...
}
}
来处理位置更新:
startLocationUpdates
当用户点击按钮时,我的主要活动中会调用...
Boolean mLocationUpdatesEnabled = false;
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(LOCATION_UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(LOCATION_UPDATE_FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
protected void startLocationUpdates() {
Log.d(TAG, "startng location updates...");
mLocationUpdatesEnabled = true;
if (mLocationRequest == null) {
createLocationRequest();
}
// create the Intent to use WebViewActivity to handle results
Intent mRequestLocationUpdatesIntent = new Intent(this, LocationUpdateService.class);
// create a PendingIntent
mRequestLocationUpdatesPendingIntent = PendingIntent.getService(getApplicationContext(), 0,
mRequestLocationUpdatesIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
// request location updates
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest,
mRequestLocationUpdatesPendingIntent);
Log.d(TAG, "location updates started");
}
protected void stopLocationUpdates() {
Log.d(TAG, "stopping location updates...");
mLocationUpdatesEnabled = false;
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient,
mRequestLocationUpdatesPendingIntent);
Log.d(TAG, "location updates stopped");
}
:
主要活动类:
toggleLocationUpdates
这一切都运作良好;当用户按下按钮时,系统会调用LocationServices.FusedLocationApi.requestLocationUpdates
,调用LocationUpdateService
来调用Intent
,我可以获取该位置。
当我尝试使用Intent.putExtra(String,String)将字符串额外添加到...
protected void startLocationUpdates(String username) {
....
// create the Intent to use WebViewActivity to handle results
Intent mRequestLocationUpdatesIntent = new Intent(this, LocationUpdateService.class);
//////////////////////////////////////////////////////////////////
//
// When I put this extra, IntentService sees my username extra
// but the parcelableExtra `location` == null :(
//
//////////////////////////////////////////////////////////////////
mRequestLocationUpdatesIntent.putExtra("username", username);
...
}
...
时出现问题:
主要活动类:
IntentService
编辑 我开始下一句话作为陈述而不是问题:"我正在使用......"
我是否使用正确的方法向此位置更新处理#include <iostream>
#include <typeinfo>
struct Bar
{
Bar(double); // some non-default ctor
double f(); // some function of which return type we want to get
};
using Barref = Bar&&; // emulating std::declval<Bar>()
int main()
{
// FUNKY, compiles in g++, not in clang++
// error: unexpected type name 'Barref': expected expression
decltype(Barref.f()) x; // (1)
std::cout << typeid(x).name() << std::endl; // i -> int INCORRECT
// OK, just for testing
decltype(std::declval<Bar>().f()) y; // (2)
std::cout << typeid(y).name() << std::endl; // d -> double CORRECT
}
发送一些额外数据,还是有更合理的方法来解决这个问题?
这是一个错误还是只是糟糕的文档?
答案 0 :(得分:-1)
使用与FusedLocationProviderAPI结合的IntentService会出现问题。来自标题为接收位置更新的开发者文档:
根据请求的形式,融合位置提供商 或者调用
LocationListener.onLocationChanged()
回调 方法并将其传递给Location对象,或者发出PendingIntent
包含其扩展数据中的位置。准确性和频率 您所拥有的位置权限会影响更新 请求以及您在位置请求对象中设置的选项
此外,PendingIntent
用于扩展另一段代码(Google Play服务中的FusedLocationProviderAPI
)的权限,以便在您的apk中执行其代码。 IntentService
用于启动在apk范围内定义的服务。
因此,该方法需要实现LocationListener
用于前景更新,或PendingIntent
用于与广播接收器配合的后台更新。
这是一些用于从PendingIntent
请求位置更新并附加额外值的方法的工作示例。
注意:LocalStorage.java
是用于存储局部变量的实用程序类,它不是Android API的一部分
<强> GPSPlotter 强>
/**
* Private helper method to initialize the Google Api Client with the
* LocationServices Api and Build it for use.
*/
private void initializeGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
/**
* Private helper method to determine whether or not GooglePlayServices
* are installed on the local system.
*
* @return services are installed.
*/
private boolean googlePlayServicesInstalled() {
int result = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);
return result == ConnectionResult.SUCCESS;
}
/**
* Private method to build the Api Client for use with the LocationServices API.
*/
private synchronized void buildApiClient() {
Log.w(TAG, "Building Google Api Client...");
initializeGoogleApiClient();
}
/**
* Private method used to connect the ApiClient to the Api hosted by Google for
* Accessing Locations.
*/
private void connectClient() {
mGoogleApiClient.connect();
}
/**
* User passes in a requested interval polling time in seconds as an
* integer.
*
* @param theAccount is a reference to the parent activity used for updating views.
*/
public void beginManagedLocationRequests(MyAccount theAccount) {
if (mAccount == null)
mAccount = theAccount;
startBackgroundUpdates();
}
/**
* Public method to end the managed Location Requests.
*/
public void endManagedLocationRequests() {
endBackgroundUpdates();
}
/**
* This method handles the switch in polling rates by stopping and then starting once more the
* background udpates, which in turn sets the interval in another method in the call stack.
* @param theInterval the desired interval polling rate
*/
public void changeRequestIntervals(int theInterval) {
mIntentInterval = theInterval;
if (LocalStorage.getRequestingBackgroundStatus(mContext)) {
endBackgroundUpdates();
startBackgroundUpdates();
}
}
/**
* Private helper method to build an Intent that will be couple with a pending intent uses
* for issuing background Location requests.
*
* @return theIntent
*/
private Intent buildBackgroundRequestIntent() {
Intent intent = new Intent(mContext, BackgroundLocationReceiver.class);
intent.setAction(BACKGROUND_ACTION);
intent.putExtra(User.USER_ID, mUserID);
return intent;
}
/**
* Private helper method used to generate a PendingIntent for use when the User requests background service
* within the FusedLocationApi until the Interval is changed.
*
* @return pendingIntent
*/
private PendingIntent buildRequestPendingIntent(Intent theIntent) {
Log.w(TAG, "building pending intent");
return PendingIntent.getBroadcast(mContext, 0, theIntent, 0);
}
/**
* Private method to start the Location Updates using the FusedLocation API in the background.
*/
private void startBackgroundUpdates() {
Log.w(TAG, "Starting background updates");
if (googlePlayServicesInstalled()) {
LocalStorage.putBackgroundRequestStatus(true, mContext);
LocalStorage.putLocationRequestStatus(true, mContext);
registerAlarmManager();
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, buildLocationRequest(), buildRequestPendingIntent(buildBackgroundRequestIntent()));
}
}
/**
* Private method to end background updates.
*/
private void endBackgroundUpdates() {
Log.w(TAG, "Ending background updates");
LocalStorage.putBackgroundRequestStatus(false, mContext);
LocalStorage.putLocationRequestStatus(false, mContext);
unregisterAlarmManager();
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, buildRequestPendingIntent(buildBackgroundRequestIntent()));
}
<强> BackgroundLocationReceiver 强>
public class BackgroundLocationReceiver extends BroadcastReceiver {
private static final String TAG = "BLocRec: ";
private static final String UPLOAD_ERROR_MESSAGE = "Background Service to Upload Coordinates Failed.";
private static final String UPLOAD_MESSAGE = "Coordinate Batch Pushed to Database.";
public BackgroundLocationReceiver() {
//Default, no-arg constructor
}
/**
* This method handles any location updates received when the app is no longer in focus. Coordinates are
* stored in the local database and uploaded once every hour.
* @param context the application context
* @param intent is the pending intent
*/
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().matches(GPSPlotter.BACKGROUND_ACTION)) {
Log.w(TAG, "BLR Received-background");
Location location = intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
storeLocation(location, context, intent.getStringExtra(User.USER_ID));
}
修改强>
以下方法构建了调用requestLocationUpdates()
方法所必需的LocationRequest
/**
* Private helper method used to generate a LocationRequest which will be used to handle all location updates
* within the FusedLocationApi until the Interval is changed.
*
* @return locationRequest
*/
private LocationRequest buildLocationRequest() {
int dateConversion = 1000;
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(mIntentInterval * dateConversion);
locationRequest.setFastestInterval((mIntentInterval / 2) * dateConversion);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
Log.w(TAG, "Building location request");
return locationRequest;
}
修改强> 经过与Catherine聊天的长时间讨论后,我们得出结论,Google Play服务库7.5有一个错误,当其他额外内容被放入Intent时,它不会处理从FusedLocationProviderAPI传递的Parcelable Extra Location。但是,7.0确实提供了这种功能。她说她会提交一个错误,我们会看到Android团队需要多长时间来解决