2017-02-23 163 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>