I was using iBeacon library version 0.6 and everything was fine except monitoring. In that version monitoring was happening but the monitoring notifier callback was not getting called because library used an "implicit intent" to pass this information. see Issue IBeacon getting warning Implcit intents are not safe on callback of MonitorNotifier
Recently I upgraded to the version 0.7.6 of the iBeacon android library and it solved the problem of monitoring callback but I found a new issue with this upgrade. I am getting an Exception which is android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
I am invoking my app'S method inside the ranging notifier callback and If I am wrapping it inside UI thread than that exception is not coming but it slowing down the performance of the app.
here is the code
BackgroundRangingFragment.java
@Override
public void onIBeaconServiceConnect() {
//Ranging Notifier
iBeaconManager.setRangeNotifier(new RangeNotifier() {
@Override
public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
//If beacon found in the specified Region.
if (iBeacons.size() > 0) {
MainActivity main = (MainActivity)MainActivity.mainActivityInstance;
main.setActiveBeaconsFromBackgroundRangingFragment(iBeacons);
}
}
}
MainActivity.java
public void setActiveBeaconsFromBackgroundRangingFragment(List<Beacon> tempActiveBeaconArrayList){
this.activeBeaconArrayList.clear();
activeBeaconArrayList.addAll(tempActiveBeaconArrayList);
MainRangingFragmennt fragment = (MainRangingFragmennt)getSupportFragmentManager().findFragmentByTag("beaconLogFragment");
if(fragment != null){
fragment.setActiveBeaconListForBeaconLogFromBackgroundRangingData(this.activeBeaconArrayList);
}
MainRangingFragment.java
//Refreshes Beacon log
public void setActiveBeaconListForBeaconLogFromBackgroundRangingData(List<Beacon> activeBeacons){
//Here I am updating view with currently active beacons.
LinearLayout progressBar = (LinearLayout)this.view.findViewById(R.id.beacon_log_list_progress);
progressBar.setVisibility(View.VISIBLE); //This line is raising exception .
//code continues ...
}
Exception message.
04-22 18:10:15.546: E/isNull(1435): MainRangingFragmennt{421408c0 #2 id=0x7f0c0021 beaconLogFragment}
04-22 18:10:15.546: W/dalvikvm(1435): threadid=19: thread exiting with uncaught exception (group=0x4186fba8)
04-22 18:10:15.546: E/AndroidRuntime(1435): FATAL EXCEPTION: IntentService[IBeaconIntentProcessor]
04-22 18:10:15.546: E/AndroidRuntime(1435): Process: com.example.ranging, PID: 1435
04-22 18:10:15.546: E/AndroidRuntime(1435): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:824)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.requestLayout(View.java:16431)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.requestLayout(View.java:16431)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.requestLayout(View.java:16431)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.requestLayout(View.java:16431)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.support.v4.widget.DrawerLayout.requestLayout(DrawerLayout.java:762)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.requestLayout(View.java:16431)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.requestLayout(View.java:16431)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.requestLayout(View.java:16431)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.requestLayout(View.java:16431)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.setFlags(View.java:8908)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.view.View.setVisibility(View.java:6036)
04-22 18:10:15.546: E/AndroidRuntime(1435): at com.example.ranging.MainRangingFragmennt.setActiveBeaconListForBeaconLogFromBackgroundRangingData(MainRangingFragmennt.java:309)
04-22 18:10:15.546: E/AndroidRuntime(1435): at com.example.ranging.MainActivity.setActiveBeaconsFromBackgroundRangingFragment(MainActivity.java:497)
04-22 18:10:15.546: E/AndroidRuntime(1435): at com.example.ranging.BackgroundRanging$4.didRangeBeaconsInRegion(BackgroundRanging.java:489)
04-22 18:10:15.546: E/AndroidRuntime(1435): at com.radiusnetworks.ibeacon.IBeaconIntentProcessor.onHandleIntent(IBeaconIntentProcessor.java:73)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.os.Handler.dispatchMessage(Handler.java:102)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.os.Looper.loop(Looper.java:136)
04-22 18:10:15.546: E/AndroidRuntime(1435): at android.os.HandlerThread.run(HandlerThread.java:61)
I am using fragments to load the beacon data in the UI.