发送额外requestLocationUpdates intentService打破位置更新

我无法发送额外的string与我的PendingIntent ,我传递给LocationServices.FusedLocationApi.requestLocationUpdates(GoogleApiClient client, LocationRequest request, PendingIntent callbackIntent)

看来,额外的用户名放在Intent是mangling的位置, requestLocationUpdates试图切换到我的IntentService intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED)返回null

编辑

我试着做一个实现ParcelableUser类,把它作为一个额外的:

 mRequestLocationUpdatesIntent.putExtra("username", new User(username)); 

而且我也试图把Parcelable User放在一个Bundle里面,就像这个bug报告中的评论一样https://code.google.com/p/android/issues/detail?id=81812 :

 Bundle userBundle = new Bundle(); userBundle.putParcelable("user", new User(username)); mRequestLocationUpdatesIntent.putExtra("user", userBundle); 

在我的服务:

 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())); ... } } 

当用户点击一个button时,在我的主要活动中调用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"); } 

这一切运作良好, 当用户按下button时, toggleLocationUpdates被调用,调用LocationServices.FusedLocationApi.requestLocationUpdates调用我的LocationUpdateService ,我可以获取位置。

麻烦来了,当我试图把一个额外的string到我的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还是有更多的方法来解决这个问题?

这是一个错误还是只是糟糕的文档?

Related of "发送额外requestLocationUpdates intentService打破位置更新"

使用IntentService和FusedLocationProviderAPI将会出现问题。 在标题为“ 接收位置更新 ”的开发人员文档中:

根据请求的forms,融合位置提供程序要么调用LocationListener.onLocationChanged()callback方法,并将其传递给一个Location对象,要么发出一个PendingIntent ,该PendingIntent包含扩展数据中的位置。 更新的准确性和频率受到您请求的位置权限以及您在位置请求对象中设置的选项的影响

此外, PendingIntent用于扩展另一段代码(Google Play服务中的FusedLocationProviderAPI )的权限,以在您的apk内执行其代码。 IntentService用于启动在您的apk范围内定义的服务。

所以,这个方法需要为前台更新实现LocationListener ,或者需要一个PendingIntent来实现后台更新以及广播接收器。

这是一些用于从PendingIntent请求位置更新以及额外值的方法的示例。

注意: LocalStorage.java是存储局部variables的工具类,它不是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)); } 

编辑 下面的方法构build一个调用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; } 

编辑 经过长时间的讨论与凯瑟琳聊天后,我们得出的结论是,谷歌播放服务库7.5有一个错误,不会处理从FusedLocationProviderAPI传递的其他额外部分被放入意图时,Parcelable额外的位置。 但是,7.0提供这种function。 她说,她会提交一个错误,我们会看到Android团队需要多长时间来解决