2015-04-16 15 views
6

Tôi biết câu hỏi tương tự đã được hỏi trước nhưng câu trả lời không hoàn hảo.Geofences không hoạt động khi ứng dụng bị giết

Tôi đã tạo một ứng dụng có geofences sử dụng mã mẫu từ trang web dành cho nhà phát triển Android. Tôi không sử dụng bất kỳ tùy chọn được chia sẻ nào để lưu trữ geofences vì ​​tôi không xóa các geofences. Tôi đang thử nghiệm các ứng dụng từ bên trong geofence, nhưng điện thoại thông minh của tôi nhận được thông báo mỗi khi ứng dụng chạy và không có thông báo được quan sát thấy khi ứng dụng bị giết. Lý do tại sao điều này xảy ra? Tôi nghĩ rằng tôi phải nhận được thông báo ngay cả khi ứng dụng bị giết.

MainActivity

public class MainActivity extends ActionBarActivity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.drawer_layout); 
    ..... 
GeofencingTask myTask = new GeofencingTask(); 
    myTask.execute(); 
} 
private class GeofencingTask extends AsyncTask<String,Void,String> implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { 

    @Override 
    protected void onPreExecute() { 


    } 


    @Override 
    protected String doInBackground(String... params) { 


     mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 

     mGoogleApiClient.connect(); 
     mGeofenceList = new ArrayList<Geofence>(); 

     mGeofenceList.add(new Geofence.Builder() 
       .setRequestId("1") 

       .setCircularRegion(
         Constants.MyAPP_LOCATION_LATITUDE, 
         Constants.MyAPP_LOCATION_LONGITUDE, 
         Constants.MyAPP_RADIUS 
       ) 
       .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_TIME) 
       .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | 
         Geofence.GEOFENCE_TRANSITION_EXIT) 
       .build()); 
     return null; 

    } 

    protected void onPostExecute(String s) { 
     if (s == null) { 
      return; 

     } 
    } 

    @Override 
    public void onConnected(Bundle bundle) { 

     LocationServices.GeofencingApi.addGeofences(
       mGoogleApiClient, 
       getGeofencingRequest(), 
       getGeofencePendingIntent() 
     ); 

     Toast.makeText(MainActivity.this, "Starting gps", Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    public void onConnectionSuspended(int i) { 

    } 

    @Override 
    public void onConnectionFailed(ConnectionResult connectionResult) { 

     if (connectionResult.hasResolution()) { 
      try { 
       connectionResult.startResolutionForResult(MainActivity.this, 
         Constants.CONNECTION_FAILURE_RESOLUTION_REQUEST); 
      } catch (IntentSender.SendIntentException e) { 
       Log.e(TAG, "Exception while resolving connection error.", e); 
      } 
     } else { 
      int errorCode = connectionResult.getErrorCode(); 
      Log.e(TAG, "Connection to Google Play services failed with error code " + errorCode); 
     } 
    } 

} 

GeofenceTransitionsIntentService.java

public class GeofenceTransitionsIntentService extends IntentService{ 

String TAG = "GeofenceTransitionsIntentService"; 
int geofenceTransition; 

public GeofenceTransitionsIntentService() { 
    super("name"); 

} 

@Override 
public void onCreate() { 
    super.onCreate(); 
} 

@Override 
protected void onHandleIntent(Intent intent) { 
    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); 
    if (geofencingEvent.hasError()) { 
     int errorCode = geofencingEvent.getErrorCode(); 
     Log.e(TAG, "Location Services error: " + errorCode); 
    } 
    geofenceTransition = geofencingEvent.getGeofenceTransition(); 

    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 triggeringGeofences = geofencingEvent.getTriggeringGeofences(); 

     // Get the transition details as a String. 
     String geofenceTransitionDetails = getGeofenceTransitionDetails(
       this, 
       geofenceTransition, 
       triggeringGeofences 
     ); 
     Log.i("GeofenceTransitionDetails",geofenceTransitionDetails); 

     // Send notification and log the transition details. 
     sendNotification(geofenceTransitionDetails); 
     sendInOutsTask myTask = new sendInOutsTask(); 
     myTask.execute(); 

     Log.i(TAG, geofenceTransitionDetails); 
    } else { 
     // Log the error. 
     Log.e(TAG, getString(R.string.geofence_transition_invalid_type, 
       geofenceTransition)); 
    } 

} 

private String getGeofenceTransitionDetails(
     Context context, 
     int geofenceTransition, 
     List<Geofence> triggeringGeofences) { 

    String geofenceTransitionString = getTransitionString(geofenceTransition); 

    // Get the Ids of each geofence that was triggered. 
    ArrayList triggeringGeofencesIdsList = new ArrayList(); 
    for (Geofence geofence : triggeringGeofences) { 
     triggeringGeofencesIdsList.add(geofence.getRequestId()); 
    } 
    String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList); 

    return geofenceTransitionString; 

} 

/** 
* Posts a notification in the notification bar when a transition is detected. 
* If the user clicks the notification, control goes to the MainActivity. 
*/ 
private void sendNotification(String notificationDetails) { 

    Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class); 
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); 
    stackBuilder.addParentStack(MainActivity.class); 
    stackBuilder.addNextIntent(notificationIntent); 
    PendingIntent notificationPendingIntent = 
      stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); 
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 
    builder.setSmallIcon(R.mipmap.zemoso_logo) 
      .setLargeIcon(BitmapFactory.decodeResource(getResources(), 
        R.mipmap.zemoso_logo)) 
      .setColor(Color.RED) 
      .setContentTitle(notificationDetails) 
      .setContentText(getString(R.string.geofence_transition_notification_text)) 
      .setContentIntent(notificationPendingIntent); 
    builder.setAutoCancel(true); 

    NotificationManager mNotificationManager = 
      (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 

    mNotificationManager.notify(0, builder.build()); 
} 

private String getTransitionString(int transitionType) { 
    switch (transitionType) { 
     case Geofence.GEOFENCE_TRANSITION_ENTER: 
      return Constants.WELCOME_NOTIFICATION; 
     case Geofence.GEOFENCE_TRANSITION_EXIT: 
      return Constants.EXIT_NOTIFICATION; 
     default: 
      return null; 
    } 
} 

}

+0

hiển thị mã của bạn ... –

+1

Vui lòng kiểm tra câu hỏi này khác. Đã trả lời ở đây: [android geofence chỉ hoạt động với ứng dụng đã mở] (http://stackoverflow.com/questions/19434999/android-geofence-only-works-with-opened-app) –

+0

tôi có cùng bạn giải quyết nó tôi sử dụng câu trả lời dưới đây, nhưng từ phát sóng GeofenceTransationService không gọi là tôi đang làm một số điều worng –

Trả lời

8

Ok, Có thể là hơi muộn nhưng tôi sẽ gửi câu trả lời về cách tôi cố định vấn đề này bản thân mình. Hai điều:

1) Tôi đã thêm các giới hạn địa lý mỗi khi tôi chạy MainActivity và giới hạn địa lý API gây nên sự kiện geofencing, nếu bạn thêm các giới hạn địa lý khi bạn đã bên trong geofence quy định (tức là bắt đầu ứng dụng geofence khi bạn đã ở bên trong geofence). Vì vậy, tôi đã thay đổi mã của mình trong phương thức onConnected để thêm các geofences chỉ khi chúng chưa được thêm vào trước đó. (Thực hiện một kiểm tra sử dụng các ưu đãi chung)

public void onConnected(Bundle bundle) { 

    Log.i(TAG, "Connected to GoogleApiClient"); 
    SharedPreferences sharedPrefs = MainActivity.this.getSharedPreferences("GEO_PREFS", Context.MODE_PRIVATE); 
    String geofencesExist = sharedPrefs.getString("Geofences added", null); 

    if (geofencesExist == null) { 
     LocationServices.GeofencingApi.addGeofences(
       mGoogleApiClient, 
       getGeofencingRequest(), 
       getGeofencePendingIntent(this) 
     ).setResultCallback(new ResultCallback<Status>()   { 
      @Override 
      public void onResult(Status status) { 
       if (status.isSuccess()) { 
        SharedPreferences sharedPrefs = MainActivity.this.getSharedPreferences("GEO_PREFS", Context.MODE_PRIVATE); 
        SharedPreferences.Editor editor = sharedPrefs.edit(); 
        editor.putString("Geofences added", "1"); 
        editor.commit(); 
       } 
      } 
     }); 
    } 
} 

2) Hóa ra lý do không nhận được thông báo khi ứng dụng không có sẵn là

i) Hoặc là tôi toggled dịch vụ định vị trên điện thoại (trên/off/tiết kiệm pin/thiết bị chỉ/độ chính xác cao) ít nhất một lần sau khi tôi thêm các geofences hoặc,

ii) Thiết bị đã được khởi động lại.

Để khắc phục điều này, tôi đã thêm bộ thu phát sóng để nghe khởi động lại thiết bị và dịch vụ vị trí đang bật. Trong bộ thu, tôi sẽ thêm lại geofences nếu thiết bị được khởi động lại hoặc dịch vụ vị trí được bật.

public class BootReceiver extends BroadcastReceiver implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> { 

private static GoogleApiClient mGoogleApiClient; 
private static List<Geofence> mGeofenceList; 
private static PendingIntent mGeofencePendingIntent; 
private static final String TAG = "BootReceiver"; 
Context contextBootReceiver; 

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


    contextBootReceiver = context; 

    SharedPreferences sharedPrefs; 
    SharedPreferences.Editor editor; 
    if ((intent.getAction().equals("android.location.MODE_CHANGED") && isLocationModeAvailable(contextBootReceiver)) || (intent.getAction().equals("android.location.PROVIDERS_CHANGED") && isLocationServciesAvailable(contextBootReceiver))) { 
     // isLocationModeAvailable for API >=19, isLocationServciesAvailable for API <19 
     sharedPrefs = context.getSharedPreferences("GEO_PREFS", Context.MODE_PRIVATE); 
     editor = sharedPrefs.edit(); 
     editor.remove("Geofences added"); 
     editor.commit(); 
     if (!isGooglePlayServicesAvailable()) { 
      Log.i(TAG, "Google Play services unavailable."); 
      return; 
     } 

     mGeofencePendingIntent = null; 
     mGeofenceList = new ArrayList<Geofence>(); 

     mGeofenceList.add(new Geofence.Builder() 
       .setRequestId("1") 

       .setCircularRegion(
         Constants.MyAPP_LOCATION_LATITUDE, 
         Constants.MyAPP_LOCATION_LONGITUDE, 
         Constants.MyAPP_LOCATION_RADIUS 
       ) 
       .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_TIME) 
       .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_DWELL | 
         Geofence.GEOFENCE_TRANSITION_EXIT) 
       .setLoiteringDelay(30000) 
       .build()); 


     mGoogleApiClient = new GoogleApiClient.Builder(contextBootReceiver) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 


     mGoogleApiClient.connect(); 
    } 
} 

private boolean isLocationModeAvailable(Context context) { 

    if (Build.VERSION.SDK_INT >= 19 && getLocationMode(context) != Settings.Secure.LOCATION_MODE_OFF) { 
     return true; 
    } 
    else return false; 
} 

public boolean isLocationServciesAvailable(Context context) { 
    if (Build.VERSION.SDK_INT < 19) { 
     LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 
     return (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) || lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)); 

    } 
    else return false; 
} 

public int getLocationMode(Context context) { 
    try { 
     return Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE); 
    } catch (Settings.SettingNotFoundException e) { 
     e.printStackTrace(); 
    } 

    return 0; 
} 

@Override 
public void onConnected(Bundle bundle) { 
    Log.i(TAG, "Connected to GoogleApiClient"); 
    SharedPreferences sharedPrefs = contextBootReceiver.getSharedPreferences("GEO_PREFS", Context.MODE_PRIVATE); 
    String geofencesExist = sharedPrefs.getString("Geofences added", null); 

    if (geofencesExist == null) { 
     LocationServices.GeofencingApi.addGeofences(
       mGoogleApiClient, 
       getGeofencingRequest(), 
       getGeofencePendingIntent(contextBootReceiver) 
     ).setResultCallback(new ResultCallback<Status>() { 
      @Override 
      public void onResult(Status status) { 
       if (status.isSuccess()) { 
        SharedPreferences sharedPrefs = contextBootReceiver.getSharedPreferences("GEO_PREFS", Context.MODE_PRIVATE); 
        SharedPreferences.Editor editor = sharedPrefs.edit(); 
        editor.putString("Geofences added", "1"); 
        editor.commit(); 
       } 
      } 
     }); 

    } 

} 

@Override 
public void onConnectionSuspended(int i) { 

} 

@Override 
public void onConnectionFailed(ConnectionResult connectionResult) { 
    if (connectionResult.hasResolution()) { 
     try { 
      connectionResult.startResolutionForResult((android.app.Activity) contextBootReceiver, 
        Constants.CONNECTION_FAILURE_RESOLUTION_REQUEST); 
     } catch (IntentSender.SendIntentException e) { 
      Log.i(TAG, "Exception while resolving connection error.", e); 
     } 
    } else { 
     int errorCode = connectionResult.getErrorCode(); 
     Log.i(TAG, "Connection to Google Play services failed with error code " + errorCode); 
    } 

} 

@Override 
public void onResult(Status status) { 

} 

private boolean isGooglePlayServicesAvailable() { 
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(contextBootReceiver); 
    if (resultCode != ConnectionResult.SUCCESS) { 
     if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) { 
      GooglePlayServicesUtil.getErrorDialog(resultCode, (android.app.Activity) contextBootReceiver, 
        Constants.PLAY_SERVICES_RESOLUTION_REQUEST).show(); 
     } else { 
      Log.i(TAG, "This device is not supported."); 
     } 
     return false; 
    } 
    return true; 
} 

static GeofencingRequest getGeofencingRequest() { 
    GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); 
    builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_DWELL); 
    builder.addGeofences(mGeofenceList); 
    return builder.build(); 
} 


static PendingIntent getGeofencePendingIntent(Context context) { 

    if (mGeofencePendingIntent != null) { 
     return mGeofencePendingIntent; 
    } 
    Intent intent = new Intent(context, GeofenceTransitionsIntentService.class); 
    return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 
} 

}

Android Manifest

. 
. 
. 
<receiver 
     android:name=".BootReceiver" 
     android:enabled="true" 
     android:exported="false" > 
     <intent-filter> 
      <action android:name="android.intent.action.BOOT_COMPLETED" /> 
      <action android:name="android.location.MODE_CHANGED" /> 
      <action android:name="android.location.PROVIDERS_CHANGED" /> 
     </intent-filter> 
    </receiver> 
. 
. 
+0

tôi sử dụng cùng một mã nhưng phát sóng nhận không bắt đầu GeofenceTransitionsIntentServic bất kỳ trợ giúp? –

+0

ahhh tôi đã được GeofencingRequest.INITIAL_TRIGGER_DWELL và nó đã được trigring thông báo inital i thay đổi nó để GeofencingRequest.INITIAL_TRIGGER_ENTER và nó làm việc cảm ơn bạn đã giúp đỡ –

+0

Làm thế nào bạn lưu trữ latittude và kinh độ của bạn trong tập tin hằng số của bạn, tôi hiện đang lưu trữ của tôi trong một hashmap: LANDMARKS.put ("Test", new LatLng (-29.78976400000001,30.822186999999985)); Vì vậy, sẽ không thể truy cập chúng triển khai mã bạn đã sử dụng –

Các vấn đề liên quan