2016-12-25 33 views
0

我正在使用Android Beacon庫爲Android應用掃描Eddystone信標。我在信標服務連接後開始監控,然後在找到信標時開始測距。停止掃描信標:stopRangingBeaconsInRegion()不起作用

我需要根據用戶的選擇停止掃描信標(停止監測和測距)。我正在使用

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

停止掃描我的stopScan()。但是,範圍並沒有停止,儘管監測停止了。有什麼我做錯了嗎?

下面是完整的代碼:

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); 
     } 
    }; 


} 

下面是我的掃描中觀察到的日誌。即使信標掃描停止後,它們仍會繼續出現。

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 

出於某種原因,我看到onBeaconServiceConnect()中的代碼運行兩次。這可能是原因。讓我知道爲什麼這可能會發生。

+0

該代碼看起來不錯。你是否說過,儘管停止了測試,你還會繼續進行回調測試?將日誌行添加到測距回調並附加LogCat摘錄可能有助於弄清楚發生了什麼。 – davidgyoung

+0

是的,即使在停止測距後,我也會收到各種回調。發佈LogCat以幫助您更好地理解。請看一下。 –

回答

1

我認爲這個問題是由Android生命週期創建BlankFragment的多個副本造成的。每次創建BlankFragment時,都會調用onCreate方法,並將代碼綁定到掃描服務並開始測距。由於多個碎片是在不調用onDestroy的情況下創建的,因此最終會同時生成多個不同的實例。當調用stopScan時,它僅停止對最近創建的Fragment實例進行測距。

解決方法之一是停止測距和監測,然後在片段不可見時取消綁定。

+0

我想你已經正確地確定了問題。我嘗試綁定到onResume()中的掃描服務,然後在onPause()中停止測距和監視以及解除綁定,這樣每次碎片離開視圖時,它都是未綁定的。但是這沒有幫助。這可能是因爲我在一個活動中使用FragmentPagerAdapter來創建保存對先前副本的引用的片段。不知何故,它每次創建活動時都會創建新副本,並仍保留舊副本。我將不得不深入瞭解這個問題。謝謝! –

+0

我進一步挖掘,發現問題在我退出應用程序(包含BlankFragment的活動是精確的)時重現,然後重新打開它。之前我使用BluetoothLeScanner進行相同的任務,並以類似的方式管理生命週期,以便在碎片不再可見時停止掃描。它工作正常,沒有顯示使用Android Beacon庫時發現的問題。你可以點亮兩種掃描方式的區別嗎? –

+0

我不確定你爲什麼沒有使用BluetoothLeScanner的類似問題。爲了使片段成爲BeaconConsumer並進行這項工作,您可能需要手動撥打電話,以防止每個片段在掃描時停止掃描。不過,我認爲更簡單的方法是將活動作爲BeaconConsumer,或者甚至是參考活動擁有的POJO。 – davidgyoung