我使用的是iBeacon库版本0.6,除了监控外,一切都很好。在该版本中,监控正在进行,但监控通知程序回调未被调用,因为库使用了"隐含意图"传递这些信息。 请参阅问题IBeacon getting warning Implcit intents are not safe on callback of MonitorNotifier
最近我升级到iBeacon android库的0.7.6版本,它解决了监控回调的问题,但我发现了这个升级的新问题。 我得到的例外是 android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图。
我在测距通知程序回调中调用我的应用程序方法,如果我将其包装在UI线程中,则该异常不会发生,但会降低应用程序的性能。
这是代码
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 ...
}
异常消息。
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)
我正在使用片段在UI中加载信标数据。
答案 0 :(得分:4)
当从AndroidIBeaconLibrary接收异步调用时,您必须包含任何更新用户界面的代码,如下所示:
runOnUiThread(new Runnable() {
public void run() {
...
}
}
这是构建Android应用程序的一般规则,并不是从Android iBeacon库的0.6到0.7.6版本特别改变的。有时线程处理是不确定的,因此当然可能这在0.6版本中大部分或全部工作。事实仍然是您需要确保在UI线程上运行此处理。它不应该影响性能。
我认为最有可能解释为什么你看到“延迟”和一些信标“被忽略”是因为setActiveBeaconListForBeaconLogFromBackgroundRangingData
方法的设计方式。您必须编写它以考虑到不会获取每个回调中所有可见信标的完整列表这一事实。您必须在UI中维护一个单独的列表,并合并到传递给此方法的任何新显示的iBeacons中。同样,您必须以编程方式从此列表中删除任何未报告在几秒钟内可见的iBeacons。
同样,这不是库版本之间特别改变的东西,但我不怀疑微妙的时序差异可能会在升级后使问题更加严重。