2013-10-21 12 views
32

Googleのジオフェンシングサンプルコードで始まったアプリがあります。それは数日間うまくいく、と私は予想通りにすべての移行の意図を取得します。しかし、ちょっとした時間の後、3日のようなものが、これらの意図を得るのを止めると、理由はわかりません。Androidジオフェンスの最終的な移行インテントの取得を停止

私は私のフェンスを作成するときに、私はここでGeofence.NEVER_EXPIRE

に有効期限の期間を設定していますが、彼らは動作を停止する前に、私は移行インテントを取得し、私のIntentServiceである:ここでは

public class ReceiveTransitionsIntentService extends IntentService { 
    @Override 
    protected void onHandleIntent(Intent intent) { 

     Intent broadcastIntent = new Intent(); 

     broadcastIntent.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES); 

     // First check for errors 
     if (LocationClient.hasError(intent)) { 
       ...handle errors 
     } else { 

      // Get the type of transition (entry or exit) 
      int transition = LocationClient.getGeofenceTransition(intent); 

      // Test that a valid transition was reported 
      if ((transition == Geofence.GEOFENCE_TRANSITION_ENTER) 
        || (transition == Geofence.GEOFENCE_TRANSITION_EXIT)) { 

       // Post a notification 
       NEVER GETS HERE 
      } else { 
       ...log error 
      } 
     } 
    } 
} 

は適切ですマニフェストの一部:

<service 
      android:name="com.aol.android.geofence.ReceiveTransitionsIntentService" 
      android:exported="false" > 
     </service> 

私のGeofenceRequesterクラスでは、サンプルコードとほぼ同じです。関連するパーツは次のとおりです。

// Get a PendingIntent that Location Services issues when a geofence transition occurs 
     mGeofencePendingIntent = createRequestPendingIntent(); 

     // Send a request to add the current geofences 
     mLocationClient.addGeofences(mCurrentGeofences, mGeofencePendingIntent, this); 

private PendingIntent createRequestPendingIntent() { 

      // Create an Intent pointing to the IntentService 
      Intent intent = new Intent(context, ReceiveTransitionsIntentService.class); 

      return PendingIntent.getService(
        context, 
        0, 
        intent, 
        PendingIntent.FLAG_UPDATE_CURRENT); 
     } 
    } 

これがなぜ機能しなくなるのでしょうか?

+2

3日間のテスト中にデバイスを再起動していないことを確認してください。再起動時にジオフェンスを再登録するのを忘れていた可能性がありますか? 確認して更新してください。 – Anuj

+0

android.intent.action.BOOT_COMPLETED – powder366

答えて

55

これでちょっと遊んだあと、サンプルコードで定義されているReceiveTransitionsIntentServiceは、アプリが周囲にいないときに通知を受け取るのを止めるようです。私はこれがサンプルコードの大きな問題だと思う...それは私のような人々を旅行するように見えます。

私は代わりにブロードキャストレシーバーを使用しましたが、これまでのところ私のテストでは動作しているようです。

マニフェストにこれを追加します。

<receiver android:name="com.aol.android.geofence.GeofenceReceiver" 
     android:exported="false"> 
     <intent-filter > 
      <action android:name="com.aol.android.geofence.ACTION_RECEIVE_GEOFENCE"/> 
     </intent-filter> 
    </receiver> 

を次にGeofenceRequesterクラスにあなたはそれがあなたのBroadcastReceiverの代わりReceiveTransitionsIntentServiceに行くように

private PendingIntent createRequestPendingIntent() { 

     // If the PendingIntent already exists 
     if (null != mGeofencePendingIntent) { 

      // Return the existing intent 
      return mGeofencePendingIntent; 

     // If no PendingIntent exists 
     } else { 

      // Create an Intent pointing to the IntentService 
      Intent intent = new Intent("com.aol.android.geofence.ACTION_RECEIVE_GEOFENCE"); 
//   Intent intent = new Intent(context, ReceiveTransitionsIntentService.class); 
      /* 
      * Return a PendingIntent to start the IntentService. 
      * Always create a PendingIntent sent to Location Services 
      * with FLAG_UPDATE_CURRENT, so that sending the PendingIntent 
      * again updates the original. Otherwise, Location Services 
      * can't match the PendingIntent to requests made with it. 
      */ 
      return PendingIntent.getBroadcast(
        context, 
        0, 
        intent, 
        PendingIntent.FLAG_UPDATE_CURRENT); 
     } 
    } 

それから私は追加createRequestPendingIntent方法を変更する必要があります次のようなGeofenceReceiverクラス:

public class GeofenceReceiver extends BroadcastReceiver { 
    Context context; 

    Intent broadcastIntent = new Intent(); 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     this.context = context; 

     broadcastIntent.addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES); 

     if (LocationClient.hasError(intent)) { 
      handleError(intent); 
     } else { 
      handleEnterExit(intent); 
     } 
    } 

    private void handleError(Intent intent){ 
     // Get the error code 
     int errorCode = LocationClient.getErrorCode(intent); 

     // Get the error message 
     String errorMessage = LocationServiceErrorMessages.getErrorString(
       context, errorCode); 

     // Log the error 
     Log.e(GeofenceUtils.APPTAG, 
       context.getString(R.string.geofence_transition_error_detail, 
         errorMessage)); 

     // Set the action and error message for the broadcast intent 
     broadcastIntent 
       .setAction(GeofenceUtils.ACTION_GEOFENCE_ERROR) 
       .putExtra(GeofenceUtils.EXTRA_GEOFENCE_STATUS, errorMessage); 

     // Broadcast the error *locally* to other components in this app 
     LocalBroadcastManager.getInstance(context).sendBroadcast(
       broadcastIntent); 
    } 


    private void handleEnterExit(Intent intent) { 
     // Get the type of transition (entry or exit) 
     int transition = LocationClient.getGeofenceTransition(intent); 

     // Test that a valid transition was reported 
     if ((transition == Geofence.GEOFENCE_TRANSITION_ENTER) 
       || (transition == Geofence.GEOFENCE_TRANSITION_EXIT)) { 

      // Post a notification 
      List<Geofence> geofences = LocationClient 
        .getTriggeringGeofences(intent); 
      String[] geofenceIds = new String[geofences.size()]; 
      String ids = TextUtils.join(GeofenceUtils.GEOFENCE_ID_DELIMITER, 
        geofenceIds); 
      String transitionType = GeofenceUtils 
        .getTransitionString(transition); 

      for (int index = 0; index < geofences.size(); index++) { 
       Geofence geofence = geofences.get(index); 
       ...do something with the geofence entry or exit. I'm saving them to a local sqlite db 

      } 
      // Create an Intent to broadcast to the app 
      broadcastIntent 
        .setAction(GeofenceUtils.ACTION_GEOFENCE_TRANSITION) 
        .addCategory(GeofenceUtils.CATEGORY_LOCATION_SERVICES) 
        .putExtra(GeofenceUtils.EXTRA_GEOFENCE_ID, geofenceIds) 
        .putExtra(GeofenceUtils.EXTRA_GEOFENCE_TRANSITION_TYPE, 
          transitionType); 

      LocalBroadcastManager.getInstance(MyApplication.getContext()) 
        .sendBroadcast(broadcastIntent); 

      // Log the transition type and a message 
      Log.d(GeofenceUtils.APPTAG, transitionType + ": " + ids); 
      Log.d(GeofenceUtils.APPTAG, 
        context.getString(R.string.geofence_transition_notification_text)); 

      // In debug mode, log the result 
      Log.d(GeofenceUtils.APPTAG, "transition"); 

      // An invalid transition was reported 
     } else { 
      // Always log as an error 
      Log.e(GeofenceUtils.APPTAG, 
        context.getString(R.string.geofence_transition_invalid_type, 
          transition)); 
     } 
    } 

    /** 
    * Posts a notification in the notification bar when a transition is 
    * detected. If the user clicks the notification, control goes to the main 
    * Activity. 
    * 
    * @param transitionType 
    *   The type of transition that occurred. 
    * 
    */ 
    private void sendNotification(String transitionType, String locationName) { 

     // Create an explicit content Intent that starts the main Activity 
     Intent notificationIntent = new Intent(context, MainActivity.class); 

     // Construct a task stack 
     TaskStackBuilder stackBuilder = TaskStackBuilder.create(context); 

     // Adds the main Activity to the task stack as the parent 
     stackBuilder.addParentStack(MainActivity.class); 

     // Push the content Intent onto the stack 
     stackBuilder.addNextIntent(notificationIntent); 

     // Get a PendingIntent containing the entire back stack 
     PendingIntent notificationPendingIntent = stackBuilder 
       .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 

     // Get a notification builder that's compatible with platform versions 
     // >= 4 
     NotificationCompat.Builder builder = new NotificationCompat.Builder(
       context); 

     // Set the notification contents 
     builder.setSmallIcon(R.drawable.ic_notification) 
       .setContentTitle(transitionType + ": " + locationName) 
       .setContentText(
         context.getString(R.string.geofence_transition_notification_text)) 
       .setContentIntent(notificationPendingIntent); 

     // Get an instance of the Notification manager 
     NotificationManager mNotificationManager = (NotificationManager) context 
       .getSystemService(Context.NOTIFICATION_SERVICE); 

     // Issue the notification 
     mNotificationManager.notify(0, builder.build()); 
    } 
} 

うまくいけば、それは他の人を助けてくれるでしょう。

+0

hi @ b-ryceで追加できます。私は同じ問題があります。私の質問[http://stackoverflow.com/questions/19745345/unable-to-display-notification-when-entering-geofence-in-android]がそれについて語ります。私はBroadcastreceiverを使用しましたが、通知を受け取ることができません。助けてください。 –

+0

@ b-ryce u r同じ放送を受信するクラスの受信者からの放送を送ります。それはどうやって動くの? – Droidme

+0

@Droidme GeofenceReceiverはジオフェンスのトランジション(Androidからpendingintentとして送信されます)を処理し、そのアクションを別のBroadcastReceiverにローカルにブロードキャストします。 – black

1

次の理由は、Googleの公式の公式ドキュメントに基づいて保留中のインテントが取得されない理由です。
1.デバイスが再起動されます。
2.アプリケーションがアンインストールされ、再インストールされています。
3.アプリケーションのデータが消去されます。
4.Google Playサービスのデータが消去されます。
5.アプリケーションがGEOFENCE_NOT_AVAILABLEアラートを受信しました(Androidロケーションプロバイダがオフになった場合)

これらのイベントの後にジオフェンスを再登録する必要があります。

私のケースでは、ロケーションプロバイダーの電源をオフにしてデバイスをリブートするのは、保留中のインテントを取得できない理由です。

+1

ロケーションプロバイダがオフの場合にジオフェンスを再登録する必要がある理由 –

+0

アンドロイドのドキュメントによれば、システムはジオフェンスを回復できないため、ジオファンスを再登録する必要があります。 次のリンクを参照してください - https://developer.android.com/training/location/geofencing.html –

関連する問題