android - FusedLocationApi 与 PendingIntent 用于后台位置更新。无法接收更新

标签 android android-pendingintent android-fusedlocation

来自 google 的示例源代码很容易在前端实现连续位置更新,但我仍然无法清楚地了解或理解后台位置更新如何使用 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);
    }
 }
}

主要 Activity 代码看起来很乱,所以我将在驱动器链接中共享代码: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
        }
    }
};

最佳答案

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

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

public abstract PendingResult requestLocationUpdates (GoogleApiClient client, LocationRequest request, PendingIntent callbackIntent)

This method is suited for the background use cases, more specifically for receiving location updates, even when the app has been killed by the system. In order to do so, use a PendingIntent for a started service.

这就是我在 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());
    }
}

Activity :

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

list 中的权限:

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

关于android - FusedLocationApi 与 PendingIntent 用于后台位置更新。无法接收更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33735536/

相关文章:

android - 完成一个未决 Intent 开始的 Activity

Android Play 服务 FusedLocatioAPI getLastLocation 因 SecurityException 而崩溃

android - FusedLocationProviderClient getLastLocation elapsedRealtimeNanos moSTLy 当前系统时间

android - 在发布中删除 Android 调试资源

android - 更改警报管理器使用的 pendingintent 的 Intent

android - 如何在不同的类中使用 PendingIntents 取消 AlarmManager?

android - 融合位置 Api 的准确性不佳

android - 使用 JDBC 从 android 中的 mySQL 检索多个数据

java - ContextCompat.getColor 方法忽略夜间模式

java - 如何解密在 Laravel 中使用 Crypt 加密的 Java (Android) 文本?