1

我使用的是 iBeacon 库版本 0.6,除了监控之外一切都很好。在那个版本中,监控正在发生,但没有调用监控通知回调,因为库使用“隐式意图”来传递此信息。请参阅问题IBeacon 在 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 中加载信标数据。

4

1 回答 1

4

当接收来自 AndroidIBeaconLibrary 的异步调用时,您必须将任何更新用户界面的代码包装在如下块中:

    runOnUiThread(new Runnable() {
        public void run() {
           ...
        }
     }

这是构建 Android 应用程序的一般规则,并不是从 0.6 到 0.7.6 版本的 Android iBeacon 库的具体更改。有时线程处理是不确定的,所以这在 0.6 版本中很可能发生在大部分时间或所有时间。事实仍然是,您需要确保此处理在 UI 线程上运行。它不应该影响性能。

我认为为什么你看到“延迟”和一些信标“被忽略”的最可能的解释是因为setActiveBeaconListForBeaconLogFromBackgroundRangingData方法的设计方式。您必须编写它以考虑到您不会在每次回调时获得所有可见信标的完整列表这一事实。您必须在 UI 中维护一个单独的列表,并合并任何新可见的 iBeacon 传递给此方法。同样,您必须以编程方式从该列表中删除任何未报告在几秒钟内可见的 iBeacon。

同样,这并不是库版本之间特别改变的东西,但我不怀疑细微的时间差异可能会使升级后问题更加严重。

于 2014-04-22T18:45:47.473 回答