Оповещения о приближении работают, но выбор идентификатора не работает

Итак, вы, возможно, видели мои предыдущие сообщения о проблемах с добавлением предупреждений о приближении в приложение для поиска мусора и их срабатыванием. Предупреждения срабатывают, и, кажется, все в порядке. ОДНАКО... Я использую переменную int ID, чтобы определить, какой текст отображается при срабатывании определенного предупреждения о приближении. Это работает до некоторой степени, но по какой-то причине приложение по умолчанию использует последний идентификатор, который был введен в методе addProximityAlert, и заполняет текст только для этого последнего идентификатора, независимо от того, какое предупреждение о приближении срабатывает.

Вот полный код:

public class FCRun extends Activity implements LocationListener  {

private static final long MINIMUM_DISTANCECHANGE_FOR_UPDATE = 1;                // in meters
private static final long MINIMUM_TIME_BETWEEN_UPDATE = 5000;                   // in Milliseconds
private static final long PROX_ALERT_EXPIRATION = -1;                           // -1 is never expires
public static final String PROX_ALERT_INTENT = "com.kinghendo.android.frankcem.ProximityAlert";
//public static final int KEY_LOCATION_CHANGED = 0;
private LocationManager lm;
double latitude, longitude;
public String[] Screen;
private ProximityIntentReceiver proximityReceiver;
//private String[] locationList;

// setting default screen text
public TextView txtName;
public TextView txtInfo;
public TextView txtClue;



 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fcrun);

        @SuppressWarnings("unused")
        Resources res = getResources();

        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.first);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+PROX_ALERT_INTENT);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.first);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+PROX_ALERT_INTENT);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.first);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+PROX_ALERT_INTENT);


     // Get the location Manager  (code from http://examples.javacodegeeks.com/android/core/location/android-location-based-services-example/)
        lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        lm.requestLocationUpdates(
                LocationManager.GPS_PROVIDER,
                MINIMUM_TIME_BETWEEN_UPDATE,
                MINIMUM_DISTANCECHANGE_FOR_UPDATE,
                this
        );

        IntentFilter filter = new IntentFilter(PROX_ALERT_INTENT);
        proximityReceiver = new ProximityIntentReceiver(this);                      // registers ProximityIntentReceiver
        registerReceiver(proximityReceiver, filter);

        addProximityAlerts();

 }

 private void addProximityAlerts(){
     Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
     if (loc == null)
         Toast.makeText(this, "No location", Toast.LENGTH_SHORT).show();
     else
         addProximityAlert(loc.getLatitude(), loc.getLongitude(), 1, 0);

     addProximityAlert (38.042015, -84.492637, 10, 27);                 // test Awesome
     addProximityAlert (38.085705, -84.561101, 10, 26);                 // Test Home Location
     addProximityAlert (38.152649, -84.895205, 10, 25);                 // Test Office Location
     addProximityAlert (38.197871, -84.866924, 3, 1);                   // Information Center
     addProximityAlert (38.196001, -84.867435, 6, 2);                   // Goebel
     addProximityAlert (38.203191, -84.867674, 7, 3);                   // Chapel
     addProximityAlert (38.192173, -84.870451, 6, 4);                   // Confederate Cemetery
     addProximityAlert (38.193455, -84.868534, 2, 5);                   // O'Bannon
     addProximityAlert (38.193815, -84.864904, 2, 6);                   // Henry Clay Jr
     addProximityAlert (38.087388, -84.547503, 2, 7);                   // O'Hara
     addProximityAlert (38.191642, -84.870967, 5, 8);                   // Daniel Boone
 }


private void addProximityAlert(double latitude, double longitude, int radius, int ID) {
    Log.i("TEST", "addProximityAlert "+latitude+", "+longitude+", "+radius+", " +ID+", " + PROX_ALERT_EXPIRATION);
    Intent intent = new Intent(PROX_ALERT_INTENT);
    intent.putExtra("ID", ID);
    PendingIntent proximityIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    //lm.addProximityAlert(latitude, longitude, radius, ID, proximityIntent);
    lm.addProximityAlert(latitude, longitude, radius, PROX_ALERT_EXPIRATION, proximityIntent);

}

public void onProximityAlert(int ID, boolean entering) {
    Log.i("TEST", "LOC " +latitude+", "+longitude);
    Log.i("TEST", "onProximityAlert ID="+ID+" entering: "+entering);


     switch (ID){
     case 1:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.start);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated"+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.start);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.start);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 2:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.goebel);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.goebel);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.goebel);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 3:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.church);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.church);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.church);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 4:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.confederate);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.confederate);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.confederate);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 5:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.obannon);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.obannon);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.obannon);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 6:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.hcj);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.hcj);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.hcj);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 7:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.ohara);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.ohara);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.ohara);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 8:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.danielboone);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.danielboone);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.danielboone);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 25:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.toffice);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.toffice);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.toffice);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 26:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.thome);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.thome);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.thome);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     case 27:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.tawesome);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.tawesome);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.tawesome);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
         break;
     default:
        txtName = (TextView) findViewById(R.id.txtName);
        Screen = getResources().getStringArray(R.array.first);
        txtName.setText(Screen[0]);
        Log.i("txtName", "populated "+ID);

        txtInfo = (TextView) findViewById(R.id.txtInfo);
        Screen = getResources().getStringArray(R.array.first);
        txtInfo.setText(Screen[1]);
        Log.i("txtInfo", "populated "+ID);

        txtClue = (TextView)findViewById(R.id.txtClue);
        Screen = getResources().getStringArray(R.array.first);
        txtClue.setText(Screen[2]);
        Log.i("txtClue", "populated "+ID);
        break;
     }
}

 @Override
 public void onLocationChanged(Location location) {
     //String provider = location.getProvider();
     latitude = location.getLatitude();
     longitude = location.getLongitude();

     Log.i("TEST", "lat: "+latitude+" lng: "+longitude+" "+PROX_ALERT_INTENT);

}

 @Override
 public void onProviderDisabled(String provider) {

 }
 @Override
 public void onProviderEnabled(String provider) {

 }
 @Override
 public void onStatusChanged(String provider, int status, Bundle extras) {

 }

 @Override
 protected void onResume() {
     super.onResume();
 }

 @Override
 protected void onPause() {
     super.onPause();
 }

@Override
protected void onDestroy() {
    super.onDestroy();
    Log.i("TEST", "Close Out");
    lm.removeUpdates(this);
    unregisterReceiver(proximityReceiver);

}

}

Вот код получателя...

public class ProximityIntentReceiver extends BroadcastReceiver {

private static final int NOTIFICATION_ID = 1000;
private WeakReference<FCRun> mActivity;
long lat, lon;

public ProximityIntentReceiver(FCRun activity) {
    mActivity = new WeakReference<FCRun>(activity);
}

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

    String key = LocationManager.KEY_PROXIMITY_ENTERING;
    Bundle results = getResultExtras(true);
    Boolean entering = intent.getBooleanExtra(key, false);

    lat = intent.getLongExtra("location-lat ", lat);
    lon = intent.getLongExtra("location-lon ", lon);
    int ID = intent.getIntExtra("ID", 0);

    Log.i("ProximityIntentReceiver", "coordinate-lat " + lat );
    Log.i("ProximityIntentReceiver", "coordinate-lon " + lon );
    Log.i("ProximityIntentReceiver", String.format("ID: %d entering: %s", ID, entering?"true":"false"));
    FCRun a = mActivity.get();
    if (a != null)
        a.onProximityAlert(ID, entering);

 // Vibrate for 2 seconds
    Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
    vibrator.vibrate(2000);

    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(FCRun.PROX_ALERT_INTENT), PendingIntent.FLAG_UPDATE_CURRENT);        

    Notification noti = new Notification.Builder(context)
    .setContentTitle("Location Alert ")
    .setContentText("Entering Point of Interest")
    .setSmallIcon(R.drawable.ic_launcher)
    .setContentIntent(pendingIntent)
    .setAutoCancel(true)
    .build(); // available from API level 11 and onwards

    notificationManager.notify(NOTIFICATION_ID, noti);
 }

}

Любая помощь здесь будет принята с благодарностью. Спасибо, Хендо


person Dave Henderson    schedule 21.07.2015    source источник


Ответы (1)


Проблема здесь в том, что вы пытаетесь иметь несколько экземпляров PendingIntent в addProximityAlert, а ваши PendingIntent считаются равными, потому что они отличаются только содержимым дополнений. Это объясняется в документации для PendingIntent:

Сам PendingIntent — это просто ссылка на маркер, поддерживаемый системой, описывающий исходные данные, используемые для его извлечения. Это означает, что даже если процесс приложения-владельца будет уничтожен, сам PendingIntent останется доступным для использования другими процессами, которые ему передали. Если создающее приложение позже повторно извлечет PendingIntent того же типа (та же операция, то же действие Intent, данные, категории и компоненты и те же флаги), оно получит PendingIntent, представляющий тот же токен, если он все еще действителен, и может таким образом, вызовите cancel(), чтобы удалить его.

Из-за такого поведения важно знать, когда два Intent считаются одинаковыми для получения PendingIntent. Распространенной ошибкой людей является создание нескольких объектов PendingIntent с намерениями, которые различаются только своим «дополнительным» содержимым, ожидая каждый раз получать разные PendingIntent. Этого не происходит. Части намерения, которые используются для сопоставления, — это те же части, которые определены в Intent.filterEquals. Если вы используете два объекта Intent, которые эквивалентны Intent.filterEquals, вы получите один и тот же PendingIntent для обоих из них.

Он также дает рекомендации о том, как это исправить:

Есть два типичных способа справиться с этим.

Если вам действительно нужно несколько разных объектов PendingIntent, активных одновременно (например, для использования в качестве двух уведомлений, которые отображаются одновременно), вам нужно убедиться, что в них есть что-то другое, чтобы связать их с разными Ожидающие намерения. Это может быть любой из атрибутов Intent, рассматриваемых Intent.filterEquals, или различные целые числа кода запроса, предоставленные для getActivity(Context, int, Intent, int), getActivities(Context, int, Intent[], int), getBroadcast(Context, int , Intent, int) или getService(Context, int, Intent, int).

Поэтому, вероятно, самый простой способ исправить это — использовать ID в качестве кода запроса (при условии, что он уникален). Например.:

Изменять

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

to

PendingIntent proximityIntent = PendingIntent.getBroadcast(this, ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
person HexAndBugs    schedule 21.07.2015
comment
Это сработало, Хекс... ну... в основном. 4 точки GPS активировали свои предупреждения о приближении и отображали правильный текст. Остальные 6 либо уведомляли меня о предупреждении и не отображали текст, либо вообще не уведомляли меня. Я собираюсь пересмотреть свои точки GPS и радиус, и посмотреть, поможет ли это. Не знаю, что еще делать, если это не помогает. Спасибо, Hex, за ваше понимание и любезную помощь. - person Dave Henderson; 23.07.2015
comment
Отлично, рад, что помогло. Пожалуйста, проголосуйте и/или примите ответ, если вы нашли его полезным. Я вижу, что радиус некоторых из ваших оповещений о приближении довольно мал, поэтому, возможно, некоторые из них не срабатывают, поскольку точность GPS может быть недостаточно хорошей, если он не фиксирует достаточное количество спутников, чтобы быть в радиусе ваших точек. - person HexAndBugs; 26.07.2015