【问题标题】:FusedLocationApi with PendingIntent for background location updates. Unable to receive updates带有 PendingIntent 的 FusedLocationApi 用于后台位置更新。无法接收更新
【发布时间】:2016-02-17 13:27:21
【问题描述】:

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

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

【问题讨论】:

    标签: android android-pendingintent android-fusedlocation


    【解决方案1】:

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

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

    public abstract 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"/>
    

    【讨论】:

    • 意图服务也应该在清单文件中声明:
    • 这会从前台 Activity 中检索位置。用户要求在后台检索它
    猜你喜欢
    • 2020-11-08
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多