Recently my error reporting tool started to show this crash (varies slightly depending on the manufacturer of the device due to the webviews implementation)
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4317)
at android.view.ViewRootImpl.invalidateChild(ViewRootImpl.java:892)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:941)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:4019)
at android.view.View.invalidate(View.java:8621)
at android.webkit.WebView.invalidate(WebView.java:1743)
at android.webkit.WebView.viewInvalidate(WebView.java:4065)
at android.webkit.WebView.invalidateContentRect(WebView.java:4084)
at android.webkit.WebView.setNewPicture(WebView.java:14353)
at android.webkit.WebView$PrivateHandler.handleMessage(WebView.java:13747)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.os.HandlerThread.run(HandlerThread.java:60)
I think this error comes from the Mopub's implementation (or from other ads sdk mediated with mopub) since I have no webviews in my app.
How can I isolate and determinate if is an error I introduced or a bug in the SDK?
Only UIThread can handle the views (ui), so try to use this code to notify your app UI
runOnUiThread(new Runnable() {
#Override
public void run() { // add your code here
}});
Or you can use the AsyncTask
This error occur when you try to update a UI view in a background thread. Make sure you are not updating any view in your background thread like edit text, text view etc. Update your views in a UI thread. See this for example.
Related
The problem seems to be known, but I could not find the right solution.
I will describe the scenario:
There is an application making requests to the API. In some FirstActivity, a request is made to the API, upon positive result of which startActivity () is called in SecondActivity. The problem is that if, while sending the request, the application is minimized to the background (that is, startActivity () will be called in the background), then:
If android version> = 29 then startActivity () basically won't work. The one following startActivity () finish () will work and upon restarting the application will restart (which is logical)
If the android version is < 29, then startActivity () will fire and bring this SecondActivity to the foreground.
Based on this, the question is. How can I force the application, regardless of version, to transition between activities and not bring them to the front?
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
finish();
As per documentation
Android 10 (API level 29) and higher place restrictions on when apps
can start activities when the app is running in the background.
Workaround : In specific situations, your app might need to get the user's attention urgently, such as an ongoing alarm or incoming call. You might have previously configured your app for this purpose by launching an activity while your app was in the background.
To provide similar behavior on a device running Android 10 (API level 29) or higher, complete the steps described in this guide.
you can show a high-priority notification with a full-screen intent.
More Details
Updated answer for new requirement: For your comment
(Well, please tell me how to make startActivity () in the background start the activity also in the background, and not raise the application from the background)
you can add a LifecycleObserver that will be notified when the LifecycleOwner changes state.
Inside your activity api response callback use the following condition
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
// Activity is in resumed state, Open new activity immediately
} else {
// else add a LifecycleObserver that will be notified when the LifecycleOwner changes state
lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
// remove observer immediately so that it will not get triggered all the time
lifecycle.removeObserver(this)
// Activity is in start state again, Open new activity here
}
})
}
Full exception : Unhandeled exception: The content of the adapter has
changed but ListView did not receive a notification. Make sure the
content of your adapter is not modified from a background thread, but
only from the UI thread. Make sure your adapter calls
notifyDataSetChanged() when its content changes. [in
ListView(2131296364, class android.widget.ListView) with Adapter(class
elfar.insitemobile.Tabs.EventTable$EventTableListAdapter)]
It happens only when the app starts (the list is updating with the pending events), and it happens only sometimes.
I noticed that it happened when there are a lot of pending events to update in the list when the app starts. If there are only few items to update it wont happen.
I tried to run those list changes inside of a thread and placed notifyDataSetChanged() after each update, but it still happens.
Well this might seem obvious but it happens very often - make sure you aren't adding items to your ArrayList (or any other list that you are using) outside the UI thread. So be sure to add the items and call notifyDataSetChanged() in the UI thread. This SO post might be of further assistance: Android, ListView IllegalStateException: "The content of the adapter has changed but ListView did not receive a notification"
Hopefully this helps!
UPDATE: i solved the following issue by inserting the calls of the Add and Remove functions into a new Runnable of a handler that was created with the mainLooper.
private static Handler mHandler = new Handler(Looper.getMainLooper());
mHandler.post(new Runnable() {
#Override
public void run() {
lMessages.add(0,message);
...
}
I need to detect the system ui visibility (full screen) from a service. I tried creating a custom view and adding setOnSystemUiVisibilityChangeListener but it never gets called.
public void setListener() {
setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
#Override
public void onSystemUiVisibilityChange(int i) {
Log.e(TAG, "onSystemUiVisibilityChange =" + i);
}
});
}
I run setListener from my service's onStartCommand. What's wrong here? Or is there any other method to detect when the system ui is visible or not? Thanks for any help.
You wrote:
...from a service. I tried creating a custom view...
The custom View in your Service in not added to the View hierarchy that's drawn. That's why the method is not called. In an Activity you could do mRootView.add(mCustomView) and then check but that doesn't work from a Service since you don't have a reference to a visible layout.
For a (hacky) solution see this answer: Receiving hidden status bar/entering a full screen activity event on a Service
If you have an Activity visible while the Service is running there are more options. You can bind the Service to an Activity and send updates from asetOnSystemUiVisibility() inside the Activity to the Service.
See: http://developer.android.com/guide/components/bound-services.html
Or just send out a broadcast from the Activity when the UI state changes, which the Service listens for.
You can add one view (with full height) and use OnGlobalLayoutListener to listerner layout change, in onGlobalLayout check view.getHeight with max Y of screen.
if (mMaxY == helperWnd.getHeight()) {
//full screen
} else {
//none full screen
}
Hope help you
My company is developing a complex android project which is not available on google play. They sell tablets with the app already installed and the updates are done through our ftp.
Recently we've started having some sporadic crashes in field, that never happen when the tablet is connected to the computer (so I can never see the logcat). So I've implemented a crash report system that sends the logcat file and crash report through email, with uncaughtExceptionHandler called in onCreate of the main activity:
protected void onCreate(Bundle savedInstanceState) {
Thread.setDefaultUncaughtExceptionHandler(handleAppCrash);
super.onCreate(savedInstanceState);
}
private Thread.UncaughtExceptionHandler handleAppCrash = new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
#crash report stuff here
};
};
Although pretty much all crashes are getting caught with this method, that specific and sporadic one which I'm searching for is not. The 'app has stopped' dialog appears, but this method is never called. After this I started using Splunk Mint (http://www.splunk.com/en_us/homepage.html), hoping that the library was more powerful, but I have the exact same behavior.
So my question is: which type of crashes are not caught with this uncaughtExceptionHandler? Could be a crash on Java itself? Is there a way to go around this to understand where the crash comes from?
Thank you!
I have service and a mapActivity.
I wish to update mapview outfrom serivce (draw new oerlays lets say each 15 sec.)
I get error:
can't create handler inside thread that has not called looper.prepare();
my code:
private void startService() {
timer.scheduleAtFixedRate( new TimerTask() {
public void run() {
MyMap map = new MyMap(); // here is where app crashes...}
}
}
You can't have UI code in a background service. Anything running in a service runs on a background thread rather than on the app's UI thread, meaning that you cannot make UI changes from there. That's why you get the error.
If you sit back and think about it, architecturally there is no reason to have UI code in a background service. Drawing the map is a purely foreground operation and ceases to matter as soon as the map activity is dismissed. Hence no need to have background code stick around in a service -- all the overlay code belongs in the foreground map activity.