Android Intent open new activities but did not close the old one - java

I searched through most answers here and all suggest we add a flag to the intent to kill old activities. The problem is my activity only receive intents from other app and has no control over it.
More specifically, my activity receive an intent to load a picture, then it uses Asynctask to load and do some complicated background processing of that picture, say, may be 2 minutes.
If the user at this moment back out (assuming that only onStop is called, not yet onDestroy) and share another picture to the app , this will start a new activity, and the previous activity cannot be accessed, but its Asynctask hold up the thread so that my new activity just freeze without starting its own Asynctask.
(I later tried the parallel thread executor, but this doesn't stop the old thread from running, thus consuming computational resources).
Any idea what I should do?
(I don't want to stop the task in onStop as this is to easy to be called. But I do want to stop the task if new picture is shared, since it is no longer needed.)
(The Asynctask will spit out a huge array of self-defined Objects declared in the main activity, and thus the activity gets immediate updates of the result from the background process, and the UI updates immediately after onPostExecute is called.)

EDIT:
It seems that your problem is that you're trying to do all this image processing work in asynctasks launched by your activity. Have you considered changing your app architecture to rely all this background processing to a service?
You can use the activity to show some UI information while you process the image in your service, or if you don't need this UI just simply communicate with the service (through broadcast, for example) to provide it the image and let the service show some information of the process through notifications.
If you don't want to keep your activity alive when you exit it you can use
android:noHistory="true" in your activity declaration at the manifest
More info here

This is the workaround, and seems it is working very well for the moment:
After getting a sharedpreference prefs, do this in onCreate:
prefs.edit().putBoolean("ForceClose", true).commit();
In the onPreExecute() of the AsyncTask, put:
prefs.edit().putBoolean("ForceClose", false).commit();
In the doInBackground() of the AsyncTask, constantly check for
if (prefs.getBoolean("ForceClose", false))
cancel(true);
and call finish() in onCancelled() to finish off the activity.

Related

Android Java AsyncTask executes twice after activity restarts

I am using some AsyncTasks in background for purposes in my Native Android Java application, however when i click the button "Apply changes and Restart Activity", once the activity is restarted AsyncTasks execute twice. this is really strange. because i have some monitoring purposes with AsyncTasks, so i used new MyAsyncTask.Execute() for execute the class in a Handler up every 1 minute. if application run normally, it's very cool. but when i used to restart by the mentioned Button in Android studio, i am facing the issue. with this issue, i am in a trouble that some logs are duplicating.
It is relative to the place of your asynctask execution. By click button , in oncreateview or in oncreate of your activity. You can have debug in start of your asynctask(preexecute or doinbackground) and for every time execution check the variables of your activity(if your asynctask is inside of your activity).The best way for recognizing of time proper of your operations , is checking of some parameters of your activity inside of your asynctask and selecting of proper time for operation doing.Do not forget the place of your asynctask also is important but you must have your controls inside of the asynctask.
If you share your code it may be easy to understand, but it seems you only have a problem with the application's life cycle, see the documentation:
Understand the Activity Lifecycle
The issue is originally from android architecture. when Activity gets destroy, automatically the activity restarts several times in same thread. in case of that single execution may run several times. the following code helps to solve this issue.
#Override
protected void onDestroy() {
pusher.disconnect();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
super.onDestroy();
}

What is the difference between `finishAffinity();` and `finish()` methods in Android?

I've using some code for a sign in screen that forces the app to close if the user doesn't want to sign in. If the user chooses to not sign in/cancel, it calls the code to exit the app. I've successfully done this two ways (not at the same time) with:
finishAffinity();
System.exit(0);
and
finish();
System.exit(0);
Yet both lines of code seem to do the same thing... The app is closed to the user, yet remains in the background apps to be reopen if the user hits the 'overview' button they can select it to reopen. (Which just restarts the prompt to sign in.)
Since I notice no functional difference, I'm wondering what is the difference between finishAffinity() and finish() methods?
Bonus Question: Also, is there a way to completely shut down the app, so it also doesn't appear in the overview button app list?
finishAffinity():
Closes all the activities present in the current Stack
finish()
Closes only opened activity
Also, is there a way to completely shut down the app, so it also
doesn't appear in the overview button app list?
Yes you can add android:noHistory="true" to your activities tag in the Manifest.xml for this pupose
finishAffinity() : finishAffinity() is not used to "shutdown an application". It is used to remove a number of Activities belonging to a specific application from the current task (which may contain Activities belonging to multiple applications).
Even if you finish all of the Activities in your application, the OS process hosting your app does not automatically go away (as it does when you call System.exit()). Android will eventually kill your process when it gets around to it. You have no control over this (and that is intentional).
finish() : When calling finish() in an activity, the method onDestroy() is executed this method can do things like:
Dismiss any dialogs the activity was managing.
Close any cursors the activity was managing.
Close any open search dialog.
finishAndRemoveTask() method pop out all your activities from stack and removes the application from recent task list simple finish this current activity as well as all activities immediately below it in the current task that have the same affinity,
finish() method pop out your current activity from stack.
for detail document link
finishAffinity(): finish the current activity and all activities immediately below it in the current task that have the same affinity.
finishAndRemoveTask(): call this when your activity is done and should be closed and the task should be completely removed as a part of finishing the root activity of the task.

How to stop UI thread until network operation is completed

I am using volley library to perform network operations. On Application launch, I hit the service, I want to stop all the operations until i get the response from the service.
So i want to perform this synchronously. As I am using Volley which by default works in a separate thread. So how can i do this.
I have created custom Interface/listener to handle this, but does Android provide some way to achieve this.
I have done following.
Splash Activity implements an interface, and it goes to Main Activity after data is loaded
#Override
public void onContainerLoaded() {
//startActivity(MainActivity)
}
Even if you want to, you should definitely never EVER run any network-related task synchronously.
What you can do instead is starting your activity normally, and replace your layout with a progressbar logo, that is set to visibility.gone when your task is completed.
EDIT : By the way, if you are just starting your app and you haven't done anything concrete yet, I would recommend you to use an AsyncTask instead of Volley, which is often causing layer-coupling mistakes.
Use some event bus such as Otto
Create an event, make your main activity subscribe to the event using the event bus, start your operation, display a "Loading..." or something ProgressDialog in your main activity. From your worker thread when it completes send an event to your main activity. Make your main activity close the "Loading" dialog when it receives the event,
I guess a better question would be why you want to force it on the main thread?
As far as I know, volley won't let you do that but you might be able to if you make your own network operation. After Honeycomb, you will get a NetworkOnMainThreadException so you will need to override the policies.

invoke a method from activity in another

i know that this question was asked before but i had tried all the solution and get Error
i have two activity on android studio ...
the first called 'MainActivity' and contain a method ' deleteFromArrayList() '
the secound on called 'DeletButtonActivity' and contain a method ' delete(View v) '
i want to invoke 'deleteFromArrayList ()' wihtout creating another class or make the method static .... becouse i have an ArrayList inside deleteFromArrayList()
note : i send value of index i want to delete from array list using Intent ..the code in DeleteButtonActivity is
public void delete(View v) {
try {
Intent i = new Intent(DeleteButton.this, MainActivity.class);
i.putExtra("index", (int) spinner2.getSelectedItemId());
(new MainActivity()).DeletButtonActivity();
Toast.makeText(getApplicationContext(), "it was deleted", Toast.LENGTH_SHORT).show();
}
catch(Exception e){
Toast.makeText(getApplicationContext(), e+"", Toast.LENGTH_SHORT).show();
}
}
and the code in MainActivity
public void deleteFromArrayList (){
this.arrayList.remove(getIntent().getIntExtra("index",-1));
}
when i run the app i got an Error NullPointerException,,,
can anyone help me ..please
hope that i describe the problem very well
Activities in Android are no just a simple class but they also have a Lifecycle:
An activity has essentially four states:
If an activity is in the foreground of the screen (at the top of the
stack), it is active or running. If an activity has lost focus but is
still visible (that is, a new non-full-sized or transparent activity
has focus on top of your activity), it is paused.
A paused activity is
completely alive (it maintains all state and member information and
remains attached to the window manager), but can be killed by the
system in extreme low memory situations.
If an activity is completely
obscured by another activity, it is stopped. It still retains all
state and member information, however, it is no longer visible to the
user so its window is hidden and it will often be killed by the system
when memory is needed elsewhere.
If an activity is paused or stopped,
the system can drop the activity from memory by either asking it to
finish, or simply killing its process. When it is displayed again to
the user, it must be completely restarted and restored to its previous
state.
So the problem with your code is that when you want to access the array in a stopped activity, the instance you have been using before might not be alive anymore.
How to solve your problem
A very simple approach is to use parameter passing before you do the transition from one activity to the other, for this you'd pass your Array as an intent extra and then you "get the result back" when you finish the second activity by using onActivityResult() callback.
A second approach could be to use a Service that is something similar to an Activity but it has no UI and it has its own lifecycle. Being able to be alive even when you app it is not. Using a Service, you'll keep the Array inside the service and you'll communicate with the array to do the usual operations.
A third approach could be to use an EventBus. A very simple communication mechanism between Activities, Fragments, Threads, Services. There's a great talk titled Android Application Architecture on Android Dev Summit 2015 that uses EventBus as a communication mechanism and to implement a MVC architecture pattern on a REST Android App.
Back to your question. If you just need to 'share' an array between two activities, use the first approach. The second and third are just examples of different alternatives for the case you need a lot more than that.
You must not do this. There are mechanism to communicate between activities or fragments.
On can be, using startActivityForResult, this is Activity A calls Activity B, then in B you do something, and communicate the result back to Activity A.
You can have another workaround to what you want. If you can access the data in both of your activities, you can modified in ether one of them, when the activity starts, it will show the updated data.
Please first read well about an Activity here, and also provides more context of your question.

Howto to associate a progressdialog with a service in Android

I have a sync service using AsyncTask. Due to its objective (sync), I prefer to block the user and show him a progressdialog. (And error if exists)
Another difficulty is that I have about 8 AsyncTask running simultaneously. So I can't do a simple call to the progress dialog page when I begin the work and a close when it's finished. It's more complex.
Can someone help me with that task ?
Regards
onPreExecute(), onProgressUpdate(Progress...) and onPostExecute(Result) in AsyncTask are invoked on the UI thread. You can use these to display a progress bar, update it as the syncing progresses and hiding it when the work is finished.
As to the 8 simultaneous async tasks, do you really need 8 concurrent tasks? Can't you run them sequentially on one background thread using a single AsyncTask?
In the first place the point of the Service is that you don't need/want to block user to do stuff because it happens in the background. To that aspect, a Service doesn't have a UI thread, so if you want a progress bar shown in your Activity you'll have to send an Intent back to your activity (using broadcast receivers), such that you can switch the progress bar on/off and do other magic.
I would not recommend blocking the user though, because the tasks you are doing might take a very long time, giving a nasty user experience. You might even want to reconsider using a Service at all (if the data you are fetching is only used locally; for example fetch the latest twitter messages or something) and just go with an ASyncTask in your Activity, unless the data your Service fetches is used in other parts of your app as well (widgets for example) and you want that data available even if the activity isn't running.
You can make use of progress dialog to show wait cursor kinda thing.
Also you can imitate the concept of CountDownLatch in your application to dismiss the cursor. Like you can have a static function in a class like updateTaskComplete and update a static counter. And once the counter is equal to number of async task then in the function updateTaskComplete cancel the progress cursor. I mean you have to do something on this line.

Categories

Resources