2016-12-25 2 views
0

J'utilise Android Beacon Library pour rechercher des balises Eddystone pour l'application Android. Je commence la surveillance après que le service de balise soit connecté et commence alors à s'étendre quand une balise est trouvée.Arrêtez l'analyse des balises: stopRangingBeaconsInRegion() ne fonctionne pas

Je dois arrêter la recherche de balises (arrêter la surveillance et la télémétrie) en fonction du choix de l'utilisateur. J'utilise

beaconManager.stopMonitoringBeaconsInRegion(region); 
beaconManager.stopRangingBeaconsInRegion(region); 

pour arrêter le balayage dans mon stopScan(). Mais la télémétrie ne s'arrête pas, bien que la surveillance s'arrête. Y a-t-il quelque chose que je fais de mal?

Voici le code complet:

public class BlankFragment extends Fragment implements BeaconConsumer { 


    public BlankFragment() { 
     // Required empty public constructor 
    } 

    private static final int PERMISSION_REQUEST_FINE_LOCATION = 1; 
    private Region region; 
    private Map<String /* uid */, Beacon> deviceToBeaconMap = new HashMap<>(); 

    String LOG_TAG = BlankFragment.class.getSimpleName(); 
    SharedPreferences sp; 
    View rootView; 


    private BeaconManager beaconManager; 
    boolean isScanning = false; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); 
     sp.registerOnSharedPreferenceChangeListener(listener); 


     beaconManager = BeaconManager.getInstanceForApplication(getContext()); 

     beaconManager.getBeaconParsers().add(new BeaconParser(). 
       setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19")); 

     beaconManager.bind(this); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     rootView = inflater.inflate(R.layout.fragment_near_me, container, false); 
     return rootView; 
    } 

    @Override 
    public void onStop() { 
     super.onStop(); 

     if (isScanning) 
      stopScan(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 

     deviceToBeaconMap.clear(); 
     beaconManager.unbind(this); 
    } 

    @Override 
    public void onBeaconServiceConnect() { 

     region = new Region("nearMeScanning", null, null, null); 
     Log.i(LOG_TAG, "OnBeaconServiceConnect called"); 

     beaconManager.addMonitorNotifier(new MonitorNotifier() { 
      @Override 
      public void didEnterRegion(Region region) { 
       try { 
        beaconManager.startRangingBeaconsInRegion(region); 
        Log.i(LOG_TAG, "In beacon region"); 
       } catch (RemoteException e) { 
        Log.e(LOG_TAG, "Remote Exception while starting Ranging", e); 
       } 
      } 

      @Override 
      public void didExitRegion(Region region) { 
       try { 
        beaconManager.stopRangingBeaconsInRegion(region); 
        Log.i(LOG_TAG, "Exited beacon region"); 
       } catch (RemoteException e) { 
        Log.e(LOG_TAG, "Remote Exception while stoping Ranging", e); 
       } 
      } 

      @Override 
      public void didDetermineStateForRegion(int i, Region region) { 
       Log.i(LOG_TAG, "State of region changed " + i); 

      } 
     }); 

     beaconManager.addRangeNotifier(new RangeNotifier() { 
      @Override 
      public void didRangeBeaconsInRegion(Collection<org.altbeacon.beacon.Beacon> beacons, Region region) { 
       if (beacons.size() > 0) { 
        for (org.altbeacon.beacon.Beacon scannedBeacon : beacons) { 

         setOnLostRunnable(); 

         String deviceUUID = scannedBeacon.getId1().toString().substring(2) + scannedBeacon.getId2().toString().substring(2); 
         String deviceAddress = scannedBeacon.getBluetoothAddress(); 
         int rssi = scannedBeacon.getRssi(); 

         Beacon beacon; 

         if (!deviceToBeaconMap.containsKey(deviceUUID)) { 

          beacon = new Beacon(deviceAddress, rssi, deviceUUID); 
          deviceToBeaconMap.put(deviceUUID, beacon); 

          if (BuildConfig.DEBUG) 
           Log.d(LOG_TAG, "New Beacon added " + deviceUUID + " DeviceAddress " + deviceAddress); 


         } else { 
          deviceToBeaconMap.get(deviceUUID).lastSeenTimestamp = System.currentTimeMillis(); 
          deviceToBeaconMap.get(deviceUUID).rssi = rssi; 
         } 

        } 
       } 
      } 
     }); 

     if (sp.getBoolean(Constants.SharedPreferences.IS_VISIBILITY_ON, false)) { 
      refreshScan(); 
     } else { 
      visbilityOffTasks(); 
     } 
    } 

    @Override 
    public Context getApplicationContext() { 
     return getActivity().getApplicationContext(); 
    } 

    @Override 
    public void unbindService(ServiceConnection serviceConnection) { 
     getActivity().unbindService(serviceConnection); 
    } 

    @Override 
    public boolean bindService(Intent intent, ServiceConnection serviceConnection, int i) { 
     return getActivity().bindService(intent, serviceConnection, i); 
    } 

    private void refreshScan() { 

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      if (getActivity().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
       if (BuildConfig.DEBUG) 
        Log.d(LOG_TAG, "Will check for permissions"); 
       requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 
         PERMISSION_REQUEST_FINE_LOCATION); 
      } else { 
       if (sp.getBoolean(Constants.SharedPreferences.IS_VISIBILITY_ON, false)) 
        startScan(); 
      } 
     } else { 
      if (sp.getBoolean(Constants.SharedPreferences.IS_VISIBILITY_ON, false)) 
       startScan(); 
     } 
    } 

    private void startScan() { 
     if (sp.getBoolean(Constants.SharedPreferences.IS_VISIBILITY_ON, false)) { 
      Log.i(LOG_TAG, "Starting scanning"); 
      try { 
       beaconManager.startMonitoringBeaconsInRegion(region); 
       isScanning = true; 
      } catch (RemoteException e) { 
       Log.e(LOG_TAG, "Remote Exception while starting Ranging", e); 
      } 
     } 
    } 

    private void stopScan() { 
     try { 
      beaconManager.stopMonitoringBeaconsInRegion(region); 
      beaconManager.stopRangingBeaconsInRegion(region); 
      isScanning = false; 
     } catch (RemoteException e) { 
      Log.e(LOG_TAG, "Remote Exception while stoping Ranging", e); 
     } 
     Log.i(LOG_TAG, "Stopping scanning"); 
    } 

    SharedPreferences.OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() { 
     public void onSharedPreferenceChanged(SharedPreferences sp, String key) { 
      if (key.equalsIgnoreCase(Constants.SharedPreferences.IS_VISIBILITY_ON) && getActivity() != null) { 
       if (sp.getBoolean(Constants.SharedPreferences.IS_VISIBILITY_ON, false)) { 

        Log.i(LOG_TAG, "Visibility turned ON"); 
        refreshScan(); 
       } else { 
        Log.i(LOG_TAG, "Visibility turned off"); 
        visbilityOffTasks(); 
       } 
      } 
     } 
    }; 

    private void visbilityOffTasks() { 
     stopScan(); 
     deviceToBeaconMap.clear(); 
    } 

    int onLostTimeoutMillis = 15000; 

    private void setOnLostRunnable() { 
     removeHandler.postDelayed(removeLostDevices, onLostTimeoutMillis); 
    } 

    private static final Handler removeHandler = new Handler(Looper.getMainLooper()); 
    Runnable removeLostDevices = new Runnable() { 
     @Override 
     public void run() { 
      long time = System.currentTimeMillis(); 
      Iterator<Map.Entry<String, Beacon>> itr = deviceToBeaconMap.entrySet().iterator(); 
      while (itr.hasNext()) { 
       Beacon beacon = itr.next().getValue(); 
       if (beacon != null && !beacon.deviceAddress.equalsIgnoreCase("default")) 
        if ((time - beacon.lastSeenTimestamp) > onLostTimeoutMillis) { 
         itr.remove(); 
         if (BuildConfig.DEBUG) 
          Log.d(LOG_TAG, "Removing beacon " + beacon.deviceAddress + " Time is " + (time - beacon.lastSeenTimestamp)); 
        } 
      } 
      removeHandler.postDelayed(this, onLostTimeoutMillis); 
     } 
    }; 


} 

Voici les journaux que j'ai observées pour le balayage. Même après l'arrêt du balayage des balises, elles continuent à apparaître.

12-25 22:27:59.103 30207-30207/com.robocats.main I/BlankFragment: Visibility turned ON 
12-25 22:27:59.104 30207-30207/com.robocats.main I/BlankFragment: Starting scanning 
12-25 22:27:59.105 30207-30207/com.robocats.main I/BlankFragment: State of region changed 0 
12-25 22:27:59.105 30207-30207/com.robocats.main I/BlankFragment: State of region changed 0 
12-25 22:27:59.105 30207-30207/com.robocats.main I/BlankFragment: State of region changed 0 
12-25 22:27:59.105 30207-30207/com.robocats.main I/BlankFragment: State of region changed 0 
12-25 22:27:59.105 30207-30207/com.robocats.main I/BlankFragment: State of region changed 0 
12-25 22:27:59.105 30207-30207/com.robocats.main I/BlankFragment: State of region changed 0 
12-25 22:27:59.105 30207-30207/com.robocats.main I/BlankFragment: State of region changed 0 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: State of region changed 1 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: In beacon region 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: State of region changed 1 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: In beacon region 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: State of region changed 1 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: In beacon region 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: State of region changed 1 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: In beacon region 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: State of region changed 1 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: In beacon region 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: State of region changed 1 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: In beacon region 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: State of region changed 1 
12-25 22:28:00.061 30207-2969/com.robocats.main I/BlankFragment: In beacon region 
12-25 22:28:09.515 30207-30207/com.robocats.main D/BlankFragment: Removing beacon 0C:F3:EE:09:3A:77 Time is 15036 
12-25 22:28:09.642 30207-30207/com.robocats.main D/BlankFragment: Removing beacon 0C:F3:EE:09:3A:77 Time is 15161 
12-25 22:28:13.497 30207-3224/com.robocats.main D/BlankFragment: New Beacon added 6bd54ac521c218b8f418000000000073 DeviceAddress 0C:F3:EE:09:3A:77 
12-25 22:28:13.510 30207-3224/com.robocats.main D/BlankFragment: New Beacon added 6bd54ac521c218b8f418000000000073 DeviceAddress 0C:F3:EE:09:3A:77 
12-25 22:28:19.086 30207-3381/com.robocats.main D/BlankFragment: New Beacon added 2f234454f4911ba9ffa100000d5181da DeviceAddress 0C:F3:EE:09:3C:63 
12-25 22:28:19.096 30207-3381/com.robocats.main D/BlankFragment: New Beacon added 2f234454f4911ba9ffa100000d5181da DeviceAddress 0C:F3:EE:09:3C:63 
12-25 22:28:22.886 30207-30207/com.robocats.main I/BlankFragment: Visibility turned off 
12-25 22:28:22.887 30207-30207/com.robocats.main I/BlankFragment: Stopping scanning 
12-25 22:28:23.586 30207-3468/com.robocats.main D/BlankFragment: New Beacon added 2f234454f4911ba9ffa100000d5181da DeviceAddress 0C:F3:EE:09:3C:63 
12-25 22:28:23.589 30207-3468/com.robocats.main D/BlankFragment: New Beacon added 4b3833f4b99a463283e84bfcc601a926 DeviceAddress 48:59:02:49:FA:3F 
12-25 22:28:24.706 30207-3483/com.robocats.main D/BlankFragment: New Beacon added 6bd54ac521c218b8f418000000000073 DeviceAddress 0C:F3:EE:09:3A:77 

Pour une raison quelconque, je vois que le code à l'intérieur onBeaconServiceConnect() est en cours d'exécution deux fois. Cela pourrait être la raison. Dites-moi pourquoi cela a pu arriver.

+0

Le code semble OK. Êtes-vous en train de dire que vous continuez à recevoir des rappels de télémétrie malgré l'arrêt de la télémétrie? Ajouter une ligne de journal au callback de télémétrie et attacher un extrait LogCat pourrait être utile pour comprendre ce qui se passe. – davidgyoung

+0

Oui, je reçois des rappels allant même après l'arrêt de la télémétrie. Publié le LogCat pour vous aider à mieux comprendre. S'il vous plaît, jetez un oeil. –

Répondre

1

Je crois que le problème est causé par le cycle de vie Android en créant plusieurs copies de BlankFragment. Chaque fois que BlankFragment est créé, la méthode onCreate est appelée et le code se lie au service de numérisation et commence à s'étendre. Étant donné que plusieurs fragments sont créés sans que onDestroy soit appelé, vous vous retrouvez avec plusieurs instances s'étendant en même temps. Lorsque stopScan est appelé, il s'arrête uniquement pour la dernière instance de fragmentation créée.

Une solution consisterait à arrêter la télémétrie et la surveillance, puis à les dissocier lorsque le fragment disparaît.

+0

Je suppose que vous avez correctement identifié le problème. J'ai essayé de me lier aux services d'analyse dans onResume(), puis d'arrêter la télémétrie et la surveillance et la déconnexion dans onPause(), de sorte que chaque fragment de temps soit hors de vue, il n'est pas lié. Mais cela n'aide pas. C'est probablement parce que j'utilise FragmentPagerAdapter dans une activité pour créer des fragments qui contiennent des références aux copies précédentes. D'une manière ou d'une autre, il crée de nouvelles copies chaque fois qu'une activité est créée et tient toujours les plus anciennes. Je devrai creuser plus loin pour comprendre le problème. Merci! –

+0

J'ai creusé plus loin et j'ai trouvé que le problème se reproduisait quand je quittais l'application (activité contenant le BlankFragment pour être précis) et que je le rouvrais ensuite. Auparavant, j'utilisais BluetoothLeScanner pour la même tâche et la gestion du cycle de vie d'une manière similaire afin que l'analyse s'arrête lorsque le fragment n'est plus visible. Il fonctionnait bien et n'a pas montré les problèmes qui sont notés lors de l'utilisation de la bibliothèque Beacon Android. Pouvez-vous jeter un peu de lumière sur quelles sont les différences dans les deux sens de la numérisation? –

+0

Je ne sais pas pourquoi vous n'avez pas eu des problèmes similaires avec le BluetoothLeScanner. Afin de faire un Fragment BeaconConsumer et avoir ce travail, vous devrez peut-être faire un appel manuellement pour arrêter chaque fragment de l'analyse quand il est hors de vue. Cependant, je pense qu'un moyen plus simple de le faire serait de faire de l'activité le BeaconConsumer, ou même un POJO dont la référence est la propriété de l'activité. – davidgyoung