2017-02-23 76 views
2

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

在我将另一个IntentService注册为地理围栏事件的“回调”之前。这或多或少,但只有当应用程序在前台。由于我想在应用程序处于后台/关闭状态时还想获取地理栅栏事件,我搜索了一下,并将IntentService的回调移至了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" /> 

BootReceiver:

public class BootReceiver extends BroadcastReceiver { 

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

GeofenceReceiver:

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

     } 
    } 
} 

GeofenceRegistrationService:

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


} 

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

回答

2

下面是我得到的工作,但请记住,我正在从活动中添加和删除地理围栏并在IntentService中接收地理围栏转场。

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

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 

    } 
} 
+1

这奏效了 - 感谢萨米。在更改所有可能的部分时,我监督了PendingIntent.getService(),它确实需要PendingIntent.getBroadcast()。 –

1

嗯,我正面临着类似的问题,但对我来说,我想反其道而行之,从服务变化到广播。在检查了您的问题后,我注意到您可能没有收到广播的地理围栏过渡,因为您在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); 

希望它对你有所帮助。

干杯。

0

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

相反的:你应该用

<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>