带有PendingIntent的FusedLocationApi用于后台位置更新。无法接收更新

时间:2015-11-16 12:35:11

标签: android android-pendingintent android-fusedlocation

谷歌的示例源代码是为了在前端轻松实现连续的位置更新,但我仍然可以使用FusedLocationApi和PendingIntent清楚地了解背景位置更新的工作原理。

LocationService类:

public class LocationService extends IntentService {
private static final String TAG = LocationService.class.getSimpleName();

private static final String ACTION_LOCATION_UPDATED = "location_updated";
private static final String ACTION_REQUEST_LOCATION = "request_location";

public static IntentFilter getLocationUpdatedIntentFilter() {
    return new IntentFilter(LocationService.ACTION_LOCATION_UPDATED);
}

public static void requestLocation(Context context) {
    Intent intent = new Intent(context, LocationService.class);
    intent.setAction(LocationService.ACTION_REQUEST_LOCATION);
    context.startService(intent);
}

public LocationService() {
    super(TAG);
}

@Override
protected void onHandleIntent(Intent intent) {
    String action = intent != null ? intent.getAction() : null;
    if (ACTION_REQUEST_LOCATION.equals(action)) {
        onRequestLocation();
    }
    else if(ACTION_LOCATION_UPDATED.equals(action)) {
        onLocationUpdated(intent);
    }
}

/**
 * Called when a location update is requested. We block until we get a result back.
 * We are using Fused Location Api.
 */
private void onRequestLocation() {
    Log.v(TAG, ACTION_REQUEST_LOCATION);
    GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .build();

    // we block here
    ConnectionResult connectionResult = googleApiClient.blockingConnect(10, TimeUnit.SECONDS);

    if (connectionResult.isSuccess() && googleApiClient.isConnected()) {

        Intent locationUpdatedIntent = new Intent(this, LocationService.class);
        locationUpdatedIntent.setAction(ACTION_LOCATION_UPDATED);

        // Send last known location out first if available
        Location location = FusedLocationApi.getLastLocation(googleApiClient);
        if (location != null) {
            Intent lastLocationIntent = new Intent(locationUpdatedIntent);
            lastLocationIntent.putExtra(
                    FusedLocationProviderApi.KEY_LOCATION_CHANGED, location);
            startService(lastLocationIntent);
        }

        // Request new location
        LocationRequest mLocationRequest = new LocationRequest()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        FusedLocationApi.requestLocationUpdates(
                googleApiClient, mLocationRequest,
                PendingIntent.getService(this, 0, locationUpdatedIntent, 0));

        googleApiClient.disconnect();
    } else {
        Log.e(TAG, String.format("Failed to connect to GoogleApiClient (error code = %d)",
                connectionResult.getErrorCode()));
    }
}

/**
 * Called when the location has been updated & broadcast the new location
 */
private void onLocationUpdated(Intent intent) {
    Log.v(TAG, ACTION_LOCATION_UPDATED);

    // Extra new location
    Location location =
            intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED);

    if (location != null) {
        LatLng latLngLocation = new LatLng(location.getLatitude(), location.getLongitude());
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }
 }
}

MainActivity 代码看起来很乱,所以我将在驱动器链接中共享代码:https://drive.google.com/open?id=0B7QMYFlbkUpOVjkxMUtfenRLXzA

但是,我已按照https://gist.githubusercontent.com/allenchi/c9659369c306752c0047/raw/16d6cd8e311013379e55b496d2b6d13347f418d6/gistfile1.txt

中的示例进行操作

示例中的以下部分是我无法理解MainActivity中的位置。如何使用广播接收器接收位置更新?我还需要清楚地了解在后台运行的FusedLocation以及我如何利用它来实现实时的gps跟踪器。

@Override
protected void onResume() {
    super.onResume();
    if(checkPlayServices()) {
        LocationService.requestLocation(this);
        LocalBroadcastManager.getInstance(getActivity())
                   .registerReceiver(locationReceiver, LocationService.getLocationUpdatedIntentFilter());
    }
}

@Override
public void onResume() {
    super.onResume();
    LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
    locationReceiver, LocationService.getLocationUpdatedIntentFilter());
}

@Override
public void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(locationReceiver);
}

private BroadcastReceiver locationReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        Location location = intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
        if (location != null) {
          LatLng latestLocation = new LatLng(location.getLatitude(), location.getLongitude());
          // do something with the location
        }
    }
};

1 个答案:

答案 0 :(得分:5)

在下面的示例中,当应用程序使用PRIORITY_HIGH_ACCURACY模式每5秒在后台运行时,您可以收到位置更新。您将通过接收指示您的位置坐标的通知来查看这些更新。

我还想测试是否可以在应用程序被系统杀死后收到更新,如here所述:

  

公共摘要PendingResult requestLocationUpdates(GoogleApiClient客户端,LocationRequest请求,PendingIntent callbackIntent)

     

此方法适用于后台使用案例,更适用于接收位置更新,即使应用程序已被系统杀死。为此,请对已启动的服务使用PendingIntent。

这就是为什么我在Activity的onBackPressed()方法中调用了System.exit(0),你当然可以省略它。

服务:

public class LocationService extends IntentService{

private static final String INTENT_SERVICE_NAME = LocationService.class.getName();

public LocationService() {
    super(INTENT_SERVICE_NAME);
}

@Override
protected void onHandleIntent(Intent intent) {
    if (null == intent) {
        return;
    }

    Bundle bundle = intent.getExtras();

    if (null == bundle) {
        return;
    }

    Location location = bundle.getParcelable("com.google.android.location.LOCATION");

    if (null == location) {
        return;
    }

    if (null != location) {
        // TODO: Handle the incoming location

        Log.i(INTENT_SERVICE_NAME, "onHandleIntent " + location.getLatitude() + ", " + location.getLongitude());

        // Just show a notification with the location's coordinates
        NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        NotificationCompat.Builder notification = new NotificationCompat.Builder(this);
        notification.setContentTitle("Location");
        notification.setContentText(location.getLatitude() + ", " + location.getLongitude());
        notification.setSmallIcon(R.drawable.ic_audiotrack);
        notificationManager.notify(1234, notification.build());
    }
}

}

活动:

public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener{

private GoogleApiClient googleApiClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

}

@Override
public void onStart() {
    super.onStart();
    googleApiClient.connect();
}

@Override
public void onStop() {
    super.onStop();
    if (googleApiClient.isConnected()) {
        googleApiClient.disconnect();
    }
}

@Override
public void onBackPressed() {
    // Check whether you receive location updates after the app has been killed by the system
    System.exit(0);
}

@Override
public void onConnected(Bundle bundle) {
    requestLocationUpdates();
}

@Override
public void onConnectionSuspended(int cause) {
    googleApiClient.connect();
}

@Override
public void onConnectionFailed(ConnectionResult result) {

}

public void requestLocationUpdates() {
    LocationRequest locationRequest = new LocationRequest()
            .setInterval(5 * 1000)
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    Intent intent = new Intent(this, LocationService.class);
    PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, pendingIntent);
}

}

清单中的权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>