【问题标题】:Android geofence BroadcastReceiverAndroid 地理围栏广播接收器
【发布时间】:2017-02-23 11:43:06
【问题描述】:

我已经使用 GoogleApiClient 实现了地理围栏 -> 触发时,服务连接到 GoogleApiClient 并添加了几个地理围栏。

在我将另一个 IntentService 注册为地理围栏事件的“回调”之前。这或多或少起作用,但仅当应用程序处于前台时。由于我还想在应用程序处于后台/关闭时获取地理围栏事件,所以我进行了一些搜索并将回调从 IntentService 移动到 BroadcastReceiver,现在当应用程序处于前台时我什至没有得到地理围栏事件。

我已经在互联网上寻求解决方案(最常见的答案:将事件侦听器从 Service 更改为 BroadCastReceiver - 但这让事情变得更糟)

这是我的设置:

清单:

    <receiver
        android:name=".service.GeofenceReceiver">
        <intent-filter>
            <action android:name="com.example.geofence.ACTION_RECEIVE" />
        </intent-filter>
    </receiver>

    <receiver android:name=".service.BootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    <service
        android:name=".service.GeofenceRegistrationService"
        android:enabled="true"
        android:exported="false" />

引导接收器:

public class BootReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
      GeofenceRegistrationService.startService(context,true);
  }
}

地理围栏接收器:

public class GeofenceReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {

      Logger.e(this, "GeofenceReceiver called");

      GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);

      if (geofencingEvent.hasError()) {
          Logger.e(this, String.valueOf(geofencingEvent.getErrorCode()));

      } else {
        Logger.i(this, geofencingEvent.getTriggeringLocation().getLatitude() + ", " +geofencingEvent.getTriggeringLocation().getLongitude());

      }
  }
}

地理围栏注册服务:

public class GeofenceRegistrationService extends Service implements ConnectionCallbacks, OnConnectionFailedListener, ResultCallback<Status> {


  public static final String KEY_FORCE_CLEAN = "FORCE_CLEAN";

  public static void startService(Context context, boolean forceClean) {

      Intent intent = new Intent(context, GeofenceRegistrationService.class);

      intent.putExtra(KEY_FORCE_CLEAN, forceClean);

      context.startService(intent);

  }

  private GoogleApiClient mGoogleApiClient;
  private PendingIntent mGeofencePendingIntent;

  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {

    if (isLocationPermissionGranted() && intent != null) {

        startGeofenceRegistration();

    } else {

        this.stopSelf(startId);

    }

    return START_REDELIVER_INTENT;
  }

  public void startGeofenceRegistration() {

    if (mGoogleApiClient == null) {
        mGoogleApiClient = buildAPIClient();
    }

    if (!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting()) {
        mGoogleApiClient.connect();
    } else {
        registerGeofences();
    }
  }


  private boolean isLocationPermissionGranted() {
    return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
  }

  private synchronized GoogleApiClient buildAPIClient() {

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

  }

  private void addGeoFences() {
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        try {
            LocationServices.GeofencingApi.addGeofences(
                    mGoogleApiClient,
                    createGeofencesRequest(),
                    getGeofencePendingIntent()
            ).setResultCallback(this);
        } catch (SecurityException securityException) {
            Logger.e(this, securityException);
        }
    }
  }

  private void removeGeoFences() {
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        try {
            LocationServices.GeofencingApi.removeGeofences(
                    mGoogleApiClient,
                    getGeofencePendingIntent()
            ).setResultCallback(this);
        } catch (SecurityException securityException) {
            Logger.e(this, securityException);
        }
    }
 }

 private PendingIntent getGeofencePendingIntent() {
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }
    //Intent intent = new Intent(this, GeofenceEventHandlingService.class);
    Intent intent = new Intent("com.example.geofence.ACTION_RECEIVE");
    mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    return mGeofencePendingIntent;
  }

  @Override
  public void onConnectionFailed(@NonNull ConnectionResult  connectionResult) {
    Logger.d(this, "CONNECTION_FAILED");
  }

  @Override
  public void onConnected(@Nullable Bundle bundle) {
    Logger.d(this, "CONNECTED");
    registerGeofences();

  }

  private void registerGeofences() {
    removeGeoFences();
    addGeoFences();
  }

  @Override
  public void onConnectionSuspended(int i) {
    Logger.d(this, "connection suspended");
  }

  private GeofencingRequest createGeofencesRequest() {
    GeofencingRequest.Builder builder = new GeofencingRequest.Builder();

    List<Poi> pois = Config.getPersistenceService().getPois();

    int counter = 0;
    for (Poi p : pois) {
        if (p.isCoordinateSet()) {
            Geofence fence = new Geofence.Builder()
                    .setRequestId(String.valueOf(p.getId()))
                    .setCircularRegion(p.getLat(), p.getLon(), 2500) // TODO
                    .setExpirationDuration(Geofence.NEVER_EXPIRE)
                    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
                    .build();

            builder.addGeofence(fence);

            counter++;
        }
    }

    Logger.i(this, "added geofences: " + counter);

    return builder.build();
  }


  @Override
  public void onDestroy() {

    if (mGoogleApiClient != null && (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting())) {
        mGoogleApiClient.disconnect();
    }

    super.onDestroy();
  }

  @Override
  public void onResult(@NonNull Status status) {
    if (status.isSuccess()) {
        Logger.d(this, "Geofences added");

    } else {
        Logger.d(this, "Failed to add geofences");
    }
  }


}

我做错了什么?我要监督什么?

【问题讨论】:

    标签: android google-api-client geofencing android-geofence


    【解决方案1】:

    这是我的工作,但请记住,我正在从 Activity 添加和删除我的地理围栏,并在 IntentService 中接收地理围栏转换。

    我认为您应该尝试构建您的 Intent 并指定 new Intent(context, YourReceiverClass) 并使用 PendingIntent.getBroadcast() 创建您的 PendingIntent。这是我使用的:

    private PendingIntent getGeofencePendingIntent(){
        // Re-use the Pending Intent if it already exists
        if(mGeofencePendingIntent != null){
            return mGeofencePendingIntent;
        }
    
        // The intent for the IntentService to receive the transitions
        Intent intent = new Intent(getContext(), GeofenceTransitionsIntentService.class);
    
        // Create the pending intent
        mGeofencePendingIntent = PendingIntent
                .getService(getContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    
        return mGeofencePendingIntent;
    }
    

    在我的 IntentService 内部:

    @Override
    protected void onHandleIntent(Intent intent) {
        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
        if (geofencingEvent.hasError()) {
            String errorMessage = GeofenceErrorMessages.getErrorString(this,
                    geofencingEvent.getErrorCode());
            Log.e(LOG_TAG, errorMessage);
            return;
        }
    
        // Get the transition type.
        int geofenceTransition = geofencingEvent.getGeofenceTransition();
    
        // Test that the reported transition was of interest.
        if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
                geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
    
            // Get the geofences that were triggered. A single event can trigger multiple geofences.
            List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
    
           // Do something with geofences
    
        }
    }
    

    【讨论】:

    • 成功了 - 谢谢 Sammy。在更改所有可能的部分时,我监督了 PendingIntent.getService(),它确实需要 PendingIntent.getBroadcast()。
    【解决方案2】:

    嗯,我遇到了类似的问题,但就我而言,我想做相反的事情,从服务更改为广播。在检查了您的问题后,我注意到您可能没有收到广播中的地理围栏转换,因为您在 getPendingIntent 方法中请求服务。

    private PendingIntent getGeofencePendingIntent() {
        (...)
        mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        (...)
      }
    

    在我的例子中,我使用了 getBroadcast 并且工作正常。

    mGeofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    

    希望对你有所帮助。

    干杯。

    【讨论】:

      【解决方案3】:

      在您发布的代码中,您的意图过滤器是错误的。

      而不是:

          <receiver
          android:name=".service.GeofenceReceiver">
          <intent-filter>
              <action android:name="com.example.geofence.ACTION_RECEIVE" />
          </intent-filter>
          </receiver>
      

      你应该用过:

          <receiver
          android:name=".service.GeofenceReceiver">
          <intent-filter>
              <action android:name="com.example.geofence.ACTION_RECEIVE_GEOFENCE" />
          </intent-filter>
          </receiver>
      

      【讨论】:

        猜你喜欢
        • 2014-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多