3

I'm facing a weird issue. My code has a broadcast-receiver, which does this in its onReceive():

view.post(new Runnable() {
    @Override
    public void run() {
    view.refreshUI();
}});

I'm confused about the reason for this code to present the android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

I'm already posting the refreshUI() call inside Runnable onto view. So how does it not run on the UI-thread?

Another weird observation is that the broadcast-sending service hasn't even sent the broadcast in the case where I see this crash. I know this because there are statements logged to the logcat on both the sender & receiver side. But one of this are present before the crash.

To give some background, the above code is written inside the Android framework, for the keyguard (OR lock-screen). I'm working on Android 4.3 source-code which is customized for our hardware/board.

The above code is present as it is since last 1.5 years. The issue has been seen only twice in the last few months though nothing has been changed here.

I've already gone through Running on UIThread and posting to view, still get CalledFromWrongThreadException & other similar questions, but they are mostly dealing with AsyncTasks. I do not have any AsyncTask in my case.

Any thoughts?

Community
  • 1
  • 1
Kiran Parmar
  • 788
  • 9
  • 26
  • Use Activity.runOnUIThread(new Runnable...) – Nanoc Nov 25 '15 at 11:12
  • I cannot do that. As I mentioned, my code is in the default Android-keyguard, which is not an Activity. It is a view that is attached on the UI directly through the WindowManager. – Kiran Parmar Nov 25 '15 at 11:14
  • Can you do ((Activity)view.getContext()).runOnUIThread... ? – Nanoc Nov 25 '15 at 11:20
  • @Nanoc It is not an Activity. Typecasting it won't work. The context used is same as the one created by SystemServer process. – Kiran Parmar Nov 25 '15 at 11:36
  • 1
    You should have a way to call runOnUIThread, post more of your code please. – Nanoc Nov 25 '15 at 12:08
  • @Nanoc runOnUIThread() method is available only for Activity. I cannot show my code due to the company-policy, but I can point you to the default Andoird file I'm changing. It is here: https://android.googlesource.com/platform/frameworks/base/+/android-4.3_r1/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java I have added a refreshUI() method here & a broadcastReceiver that is registered in onFinishInflate(). The remaining is described in my question. – Kiran Parmar Nov 26 '15 at 06:09
  • Try using handler like this: http://stackoverflow.com/questions/7860384/android-how-to-runonuithread-in-other-class – Nanoc Nov 26 '15 at 09:02
  • view.post() internally calls the runnable on the Handler. So how is this different? See the code here: https://android.googlesource.com/platform/frameworks/base/+/android-4.3_r1/core/java/android/view/View.java#10701 – Kiran Parmar Nov 26 '15 at 11:00
  • Cant see the call to getMainLooper so i will not bet is the same, can you just try it? – Nanoc Nov 26 '15 at 11:13

1 Answers1

0

You have to use runOnUiThread() when you want to update your UI from a Non-UI Thread. For eg- If you want to update your UI from a background Thread. You can also use Handler for the same thing.

you Should to use this:

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            view.refreshUI();
        }
    });
  • Care to elaborate for the op? Direct answers only aren't very good, even if they do answer the question. – Emz Nov 26 '15 at 17:00
  • runOnUiThread isn't available outside of Activity. As I mentioned in the question, this code doesn't run in an activity – Kiran Parmar Apr 16 '19 at 07:04