2016-12-25 12 views
0

私はAndroidビーコンライブラリを使用して、Android Appの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

コードはOKです。レンジングをやめてもコールバックを取得し続けると言っていますか?レンジングコールバックにログ行を追加し、LogCatの抜粋を添付すると、何が起こっているのかを理解するのに役立ちます。 – davidgyoung

+0

はい、レンジングを停止した後でもコールバックを取得しています。あなたの理解を助けるためにLogCatを掲載しました。見てください。 –

答えて

1

この問題は、AndroidのライフサイクルがBlankFragmentの複数のコピーを作成していることが原因と考えています。 BlankFragmentが作成されるたびに、onCreateメソッドが呼び出され、コードがスキャンサービスにバインドされ、レンダリングが開始されます。複数のフラグメントは、onDestroyを呼び出さずに作成されるため、複数のインスタンスが同時に存在することになります。 stopScanが呼び出されると、最も最近作成されたFragmentインスタンスのレンジングだけが停止します。

解決策の1つは、レンジングとモニタリングを停止し、断片が表示外になったときにバインドを解除することです。

+0

問題を正しく特定したと思います。私はonResume()でサービスをスキャンしてから、レンダリングを止め、onPause()でモニタリングとアンバインドを試みました。フラグメントが見えなくなるたびにアンバインドされます。しかし、これは役に立たない。これはおそらく、以前のコピーへの参照を保持するフラグメントを作成するアクティビティでFragmentPagerAdapterを使用しているためです。どういうわけか、アクティビティが作成されるたびに新しいコピーを作成していて、古いものを保持しています。私はこの問題を理解するためにさらに掘り下げなければならない。ありがとう! –

+0

私はさらに掘り下げて、アプリケーションを終了すると(正確にはBlankFragmentを含むアクティビティ)、問題を再現してから再度開くことがわかりました。以前は同じタスクでBluetoothLeScannerを使用していましたが、同様の方法でライフサイクルを管理していたため、フラグメントが見えなくなった時点でスキャンが停止しました。それは正常に動作していたし、Androidビーコンライブラリを使用している間に記載されている問題は表示されませんでした。両方のスキャン方法の違いは何ですか? –

+0

BluetoothLeScannerと同様の問題がない理由はわかりません。フラグメントをBeaconConsumerにしてこの作業を行うには、各フラグメントが視界から外れたときにそれをスキャンしないように手作業で呼び出しを行う必要があります。しかし、これを行う簡単な方法は、アクティビティをBeaconConsumer、または参照がアクティビティによって所有されているPOJOにすることです。 – davidgyoung

関連する問題