I have created an App which requires to run a operation in background for quite some time suppose 10 - 15 mins.
I am running this operation in An AsyncTask. So during this time the user is minimizing the Screen and using his other apps in his phone as usual.
When this operation is started I am creating a Progress Dialog box and then keep updating it regularly.
But this is the error which I am receiving sometimes very rarely once the operation is over
Fatal Exception: java.lang.IllegalArgumentException
View=DecorView#1234567[ABC:] not attached to window manager PackageName
And this is the detailed stack log
Fatal Exception: java.lang.IllegalArgumentException
View=DecorView#1234567[ABC:] not attached to window manager PackageName
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:508)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:417)
at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:136)
at android.app.Dialog.dismissDialog(Dialog.java:446)
at android.app.Dialog.dismiss(Dialog.java:429)
at android.app.Dialog.cancel(Dialog.java:1353)
at PACKAGENAME
at android.app.Activity.runOnUiThread(Activity.java:6078)
at PACKAGENAME
at PACKAGENAME
at android.os.AsyncTask.finish(AsyncTask.java:667)
at android.os.AsyncTask.-wrap1(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:684)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6823)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1557)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
To my knowledge this error is because the Android OS wanted to release some memory hence my App was closed since this was not visible to the user. But is there any way to tackle this thing?
Any help would be really appreciated.
EDIT: This is the code which I am using
public class load extends AsyncTask<Void, Void, Void> {
#Override
public Void doInBackground(Void... voids) {
for(int i=0;i<number;i++){
PerformSomeOperation();
UpdateTheProgress();
}
return null;
}
#Override
protected void onPostExecute(Void n) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressDialog.cancel();
CreateAnotherDialog();//This dialog is created to show the user completion of the progress.
}
});
}
You're having this crash because you're trying to update the UI when it's in the background so your Activity could be destroyed at that point. By the way, onPostExecute runs your code on the main thread already but as you're sending a separate message to the main looper you're postponing your logic a bit which can also cause a problem. Moreover, But the main question - why to update the UI if it's not visible to the user anyways?
Also, because you're using the AsyncTask as an inner class you may leak (though temporarily) your Activity object as it's referenced implicitly by the task.
From Android Documentation:
AsyncTasks should ideally be used for short operations (a few seconds
at the most.) If you need to keep threads running for long periods of
time, it is highly recommended you use the various APIs provided by
the java.util.concurrent package such as Executor, ThreadPoolExecutor
and FutureTask.
So, don't use AsyncTasks for long-running operations. A better approach would be to use:
IntentService together with BroadcastReceiver to communicate with your Activity / Fragment (in API >= 26 you should use JobIntentService as IntentService may misbehave due to new restrictions on background services).
RxAndroid (or just ExecutorService/Thread) together with Architecture-Components (more specifically with LiveData) - this way a result of your task can be cached or it can survive the config change.
My personal favourite is option 2.
There are few things to say: (1) the "onPostExecuted()" method is already executed on the UiThread/MainThread, so "runOnUiThread()" is not required. (2) if the Activity is minimized/destroyed when the Asynctask reach the final pass you get an Exception. So you have to check if the View is attached using "View. IsAttachedToWindow()" before execute some GUI methods like "mProgressDialog.cancel()". (3) you have to create a Thread or a Service to do a task that should run/work more than few seconds, or the System could kill it at anytime.
Related
Summary
Room immediately inserts entities generated through UI, but delays those sent by an asynctask until the (far) end of the generating asynctask : the entity objects received are usable and displayed on UI, but without any id from database, hampering any other operation relying on id.
The insert operation happens only when the generating asynctask is properly stopped: Why? And how to solve this?
More context
The generating asynctask
We use an asynctask to monitor a socket and send back some events (as Room entity) to the application repository (as intended by android architecture components). This asynctask basically runs continuously in background (with some sleep regularly set) and is only stopped a while before the end of use of the application (if done right). So far it hasn't caused any issue for us to deviate so much from the original concept of short-lived asynctask.
I am pretty much aware we could improve the design, but this is another subject/question/time-hole ;-).
Room insert operation
Insertion happens through a dedicated asynctask, where the returned id of the entry in database is affected back to the entity just inserted (see code below). This is logged and entities from UI are persisted "immediately", they get back their ID and all is well. The asynctask-generated entities, well they wait for their "parent" task to stop and are then all inserted.
Entity composition
At first, the entity was generated inside the asynctask and sent through progress message. Then the construction of the object was moved outside of the asynctask and at the same level of the UI event construction, yet same behavior.
These events are some longs (timestamps) and several strings.
From the generating asynctask all starts from here:
#Override
protected void onProgressUpdate(OnProgressObject... values) {
OnProgressObject onProgressObject = values[0];
if (onProgressObject instanceof OnProgressEvent) {
eventRecipient.sendAutoEvent(((OnProgressEvent) onProgressObject).autoEvent);
}
}
The eventRecipient is the EventsRepository:
public void sendAutoEvent(AutoEvent autoEvent) {
Log.d(LOG_TAG, "got an autoevent to treat...");
EventModel newEvent = EventModel.fromCub(
autoEvent.cubTimeStamp,
autoEvent.description,
autoEvent.eventType
);
addEvent(newEvent);
}
public void addEvent(EventModel event) {
new insertEventAsyncTask(event).execute(event);
// other operations using flawlessly the "event"...
}
private class insertEventAsyncTask extends AsyncTask<EventModel, Void, Long> {
private EventModel eventModel;
public insertEventAsyncTask(EventModel eventModel) {
this.eventModel = eventModel;
}
#Override
protected Long doInBackground(EventModel... eventModels) {
// inserting the event "only"
return eventDao.insert(eventModels[0]);
}
#Override
protected void onPostExecute(Long eventId) {
super.onPostExecute(eventId);
// inserting all the medias associated to this event
// only one media is expected this way though.
eventModel.id = eventId;
Log.d(LOG_TAG, "event inserted in DB, got id : " + eventId);
}
}
I am pretty much aware we could improve the design, but this is another subject/question/time-hole
Since I suspect that it is the cause of your current problem, perhaps you should not dismiss this.
My interpretation of your problem is: you have an outer AsyncTask (the one with the onPublishProgress() method shown in the first code listing). You are executing that with execute(). Inside of that outer AsyncTask you have an inner AsyncTask (the one from your repository). You are executing that with execute(). And, your complaint is that the inner AsyncTask does not run until the outer AsyncTask completes.
If so, your problem is that execute() is single-threaded, and you are tying up that thread by having an AsyncTask run indefinitely. Until your outer AsyncTask completes its background work and returns from doInBackground(), the inner AsyncTask is blocked.
The "can we keep using hacks?" solution is to continue using AsyncTask but switch to executeOnExecutor() instead of execute(), supplying a thread pool to use. AsyncTask.THREAD_POOL_EXECUTOR would be a candidate.
The "OK, can we clean this up a little bit?" solution is to replace both AsyncTask instances with either simple Thread objects or the direct use of some multi-thread thread pool (see Executors). AsyncTask is obsolete, but to the extent that it is useful, only use it when you need to do work on the main application thread (onPostExecute()) after completing the background work (doInBackground()). Neither of your AsyncTask implementations need to be doing work on the main application thread after the background work is complete, so you do not need an AsyncTask for either of them. So, for example, your run-forever thread could be a Thread, while you use a thread pool inside of your repository for your DAO calls.
(the "hey, can we get modern on our threading, to go along with our use of Architecture Components?" solution is to switch to RxJava or Kotlin coroutines, in conjunction with LiveData — this is much more work, but they each have their own merits over manual thread management)
Why ?
Basically, it was written in the AsyncTask documentation : all asynctasks are executed serially on a unique background thread.
My code, even without nested asynctask, was blocking this thread with an almost never-ending task, delaying all database operations until its completion (or app crash, hence some data loss).
A quick solution : moving an AsyncTask to a Thread
Other alternatives were nicely listed by (CommonsWare)[https://stackoverflow.com/a/56925864/9138818], here are the steps I followed that solved this issue.
The main difficulty was to redirect code that was executed on UI thread (onPreExecute, onProgressUpdate, onPostExecute) through a Handler associated to the main thread.
First step was get a reference to a handler :
// Inside Runnable task's constructor :
// get the handler of the main thread (UI), needed for sending back data.
this.uiHandler = new Handler(Looper.getMainLooper());
Then, the "doInBackground" is refactored to fit a Runnable main method signature :
// previously "public String doInBackground()"
// returned value handled through publishProgress.
#Override
public void run() {
// recommended by Android Thread documentation
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// code previously in doInBackground
Now, code in the onProgressUpdate (that was called by publishProgress inside doInBackground method) was moved into a Runnable posted on the UI thread handler :
// asynctask method onProgressUpdate was renamed publishProgress =>
// doInBackground's body is almost untouched.
private void publishProgress(final OnProgressObject... values) {
uiHandler.post(new Runnable() {
#Override
public void run() {
// move here code previously in the AsyncTask's publishProgress()
}
});
}
At last, I had to change the way the task was created, runned and stopped by using Thread.interrupted instead of isCancelled and by creating the Runnable task before the thread :
public void startCUBMonitoring() {
if (autoEventThread == null) {
Log.d(LOG_TAG, "startCUBMonitoring");
addUIEvent("CUB MONITORING STARTED", "CUB_connexion");
SessionRepository sessionRepository =
ElabsheetApplication.getInstance().getSessionRepository();
// Creation of the task
AutoEventTask autoEventTask = new AutoEventTask(
this,
sessionRepository,
sessionRepository.getCUBConfig()
);
autoEventThread = new Thread(autoEventTask);
autoEventThread.start();
}
}
public void stopCUBMonitoring() {
if (autoEventThread != null) {
Log.d(LOG_TAG, "stopCUBMonitoring");
addUIEvent("CUB MONITORING STOPPED", "CUB_connexion");
autoEventThread.interrupt();
autoEventThread = null;
}
}
Hoped it could help...
I have been scouting around for a while, but cannot locate any information for calling final() using started services... or rather, when not using bound services. There is tons of info for bound services, but I already have two pretty large "started services" without binding, so I didn't want to modify the existing services more than absolutely necessary.
My app works by reading bluetooth data every 10 seconds, and depending on the data read, the Service will change to a new activity. However, I cannot call final() from my services, so I fear that I might be endlessly stacking activities while the application/services are running.
To change activities, I had to add Intent.FLAG_ACTIVITY_NEW_TASK. Considering the below image/definition from the developer's page, this flag looks like it might already handle my stacking issue? I do NOT allow for users to use the back button on their phones as everything is handled via confirm/cancel buttons and the services. My app MUST be this way for a few reasons. Thus, keeping the stack order isn't important to my application.
Key Points -
I want to ensure i'm not stacking up activities endlessly when starting new activities
Flagging "new task" when starting activities via my services
Stack order is not important to my app
Below is a very small cut of my code with comments to explain what i'm trying to do. Please make sure to look to the onDestroy() method of this service.
public class AlertService extends Service {
final class Threader implements Runnable{
// Scans bluetooth advertisement packets every 10 seconds
// Thread Runs until interrupted
// Stops service via service ID
stopSelf(this.serviceID);
}
#Override
public void onCreate(){
super.onCreate();
}
// Runs a thread until alert is found.
// Alert calls thread.interrupt()
#Override
public int onStartCommand(Intent intent, int flags, int startID){
enableBluetooth();
// Start Thread
thread = new Thread(new Threader(startID));
thread.start();
return START_STICKY;
}
#Override
public void onDestroy(){
thread.interrupt();
Intent alertActivity = new Intent(this, AlertActivity.class)
alertActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(alertActivity);
}
// Unused Method - We will not be binding
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
EDIT via recommendation to use android:taskAffinity -
Using android:taskAffinity won't help me in this situation. By default, all activities in an application have the same affinity. When I create a new task by setting Intent.FLAG_ACTIVITY_NEW_TASK in the intent flags, the new activity will STILL be started in the same task if the activity has the same taskAffinity of the root activity in the task. Since I am just using the default affinity, everything should have the normal stack flow. I just cannot call finish(), which means that I am stacking up tons of activities.
To answer my own question, each new activity called via Intent.FLAG_ACTIVITY_NEW_TASK, was creating a new instance of each activity and putting it on the stack. This is true. However, each activity is NOT making a new Task, which was one of my fears as well.
When I create a new task by setting Intent.FLAG_ACTIVITY_NEW_TASK in the intent flags, the new activity will STILL be started in the same task (not in a new task) if the new activity has the same taskAffinity of the root activity in the task. Since I am just using the default affinity, every activity I create is being put into the same task. This means that nothing is acting any differently than the normal flow of creating activities and such.
Though, since I have disable the back button for my application, these activities created by flagging a new task are not finished, destroyed, or removed from the stack. To solve this, I will use FLAG_ACTIVITY_CLEAR_TOP, which finds a running instance of an activity in the stack (if there is one) and closes all of the activities above it.
Since my application always starts with the home screen, then ends with the home screen, flagging "clear top" will always close all activities above my home screen. So, upon return to the home screen, the only item on the stack will be the home screen.
I will have to test this, but it seems that I will not call finish() from my home activity to achieve this result - Otherwise, upon returning to the home activity, not all of the stack will be cleared.
I'm looking for a way to close an android app after some time while the app has not been in focus. For example if the user open up an other app instead, the app should exit after 5 mins. I have tried using runnable and creating a thread. But those method don't seems to work while the app is in the background (maybe they are pause I'm not sure). So how do I close the app when it is not in focus?
For those who are wonder the reason I want to do this is that the app contains some sensitives data about the user so I want to be sure it is all cleared when they aren't using it.
Something like this might work:
A field inside activity class:
private Thread t = null;
Inside onResume():
if(t!=null) {
if(t.isAlive()) {
t.interrupt();
t.join();
}
t=null;
}
Inside onPause():
t = new Thread() {
public void run() {
try {
sleep(5*60*1000);
// Wipe your valuable data here
System.exit(0);
} catch (InterruptedException e) {
return;
}
}.start();
}
I recommend calling finish() in the onPause() or onStop() callbacks. A TimerTask will not survive onPause() and a Service does not appear, on face value, to give you options. Maybe you can start a service, sleep the thread the service runs on, then kill the processes your app has after the sleep timer expires.
Alternatively, you can just implement some security libraries to help secure the data from other apps.
Here is the Google Services link.
Get the process ID of your application, and kill that process onDestroy() method
#Override
public void onDestroy()
{
super.onDestroy();
int id= android.os.Process.myPid();
android.os.Process.killProcess(id);
}
Refer- how to close/stop running application on background android
Edit- Use this with AlarmManager
The fundamental problem with what you're trying to do is that your Activity may not exist in memory at all when it's "running" in the background. The Android framework may have destroyed the activity instance and even the process it was running in. All that exists may be the persistent state you saved in onSaveInstanceState(...) and a screenshot for the recent apps list. There may be nothing for you to get a reference to and kill.
Frank Brenyah's suggestion to call finish() in onPause() will prevent your activity from running in the background at all, but this is the closest you can get to what you want. You probably only want to do this when isChangingConfigurations() is false. But even when all your app's activities are finished, Android may keep the process and Application instance around to avoid recreating them later. So you may also want to use Bhush_techidiot's suggestion of killing the process. Do this in onPause() because the activity may be destroyed without a call to onDestroy().
On my Android App, I'm implementing SignalR connection (https://github.com/erizet/SignalA) to connect to a Hub server to send requests and receive responses.
a sample of my code is as follows:
signalAConnection = new com.zsoft.SignalA.Connection(Constants.getHubUrl(), this, new LongPollingTransport())
{
#Override
public void OnError(Exception exception)
{
}
#Override
public void OnMessage(String message)
{
}
#Override
public void OnStateChanged(StateBase oldState, StateBase newState)
{
}
};
if (signalAConnection != null)
signalAConnection.Start();
There's also the sending bit
signalAConnection.Send(hubMessageJson, new SendCallback()
{
public void OnError(Exception ex)
{
}
public void OnSent(CharSequence message)
{
}
});
The sending and receiving will occur across activites, and some responses will be sent at random times regardless of the activity, also, the connection should be opened as long as the app is running (even if the app is running in the background) that's why I wish to implement the signalA connection as a background service
The question is should I implement it as:
1 - a Service (http://developer.android.com/reference/android/app/Service.html)
OR
2 - an Intent Service (http://developer.android.com/training/run-background-service/create-service.html)
Keeping in mind that I will need to send strings to the service and get response strings from the service.
I would be most grateful if someone would show me how to implement this kind of connection in code as a background service/intentservice.
Thanks for reading.
UPDATE:
Please see this demo activity made by the developer as how he implemented SignalA
https://github.com/erizet/SignalA/blob/master/Demo/src/com/zsoft/SignalADemo/DemoActivity.java
The problem is AQuery (which I know nothing about) is being used in this demo activity. Does AQuery run in the background all the time ?
The problem is, the latest update on SignalA mentions the following
I have changed the transport. LongPolling now uses basic-http-client
instead of Aquery for http communication. I've removed all
dependencies on Aquery.
Hence I'm not sure whether I should follow this demo activity or not
Update 2:
This is the thing that is confusing me most
in the IntentService, the OnHandleIntent method calls stopSelf after it finishes its tasks, when I actually want the code in the IntentService to keep running all the time
protected abstract void onHandleIntent (Intent intent)
Added in API level 3
This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf().
SignalA is running on the thread that creates and starts the connection, but all network access is done in the background. The remaining work on the starting thread is really lightweight, hence its perfectly ok to do it on the UI tread.
To answer your question, you need to have a thread running the signala connection. Therefore I think a Service is the best choice since SignalA need to be running all the time.
Regarding Aquery and the demo project. I removed all dependencies to Aquery in the libraries, not in the Demo. To be clear, you don't need Aquery to run SignalA.
In my case, what I wanted was a Service not an Intent Service, since I wanted something that would keep running until the app closes
I want to use AsyncTask for update my db4o with a server. In the doInBackground method , I connect to the server, update the db4o, and schedule a pendingintents. Not modify UI or show any toast.
Initially, I had the following error:
Can't create handler inside thread that has not called Looper.prepare()
After adding the Looper.prepare(), works fine, but only for five updates (AsyncTask). I've read this topic: AsyncTask threads never die (Android) , and I don't now that fails. When I throw the sixth update, the app crashes:
FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:200)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
Caused by: java.lang.RuntimeException: Only one Looper may be created per thread
at android.os.Looper.prepare(Looper.java:74)
(...)
I've read in the documentation that I need the Looper.loop(), but whith this, the app crashes..
Example:
protected Integer doInBackground(Void... params) {
Looper.prepare();
update = new Update();
update.checknewObjects();
update.deleteOldObjects();
update.updateObjects();
Looper.loop();
}
Why do I need Looper?
Why the app crashes after five updates?
Where can I schedule Looper.loop()?
Thanks in advance!
If you want to use AsyncTask so use it, you shouldn't mix it with Lopper...
protected Integer doInBackground(Void... params) {}
already working on background thread and there is no reason to call Lopper, for what?
If your application need to do some kind of long computation so AsyncTask is very good tool for it because offers methods which working on UI Thread and allow to update UI with some progress of work because every User that will use your application should know that application "doing something" (when it takes more than 2-5 seconds).
Also it's generic and that provide some benefits.
If you do not need to update UI just use for example Handler.
If you want to schedule tasks you should use Timer & TimerTask, from what I understand I think they should fit better to your needs.
http://developer.android.com/reference/java/util/Timer.html
in asynck Task you can't use looping in background function .it giving error