I have a class, that executes some command in background. Class method is executed asynchronously (by using AsyncTask) and when command finishes, it posts event with command result. Then, new activity is started. To do this, I added inside OnCreate method to MainActitity:
ssh = new SshSupport();
ssh.Connect();
ssh.ExecuteCommand(commandType);
//..................................
ssh.eventHandler = new ISshEvents()
{
#Override
public void SshCommandExecuted(SshCommandsEnum commandType, String result)
{
if (progressDialogExecuting.isShowing()) progressDialogExecuting.dismiss();
Intent intent = new Intent(MainActivity.this, ResultListActivity.class);
intent.putExtra("result", result);
intent.putExtra("commandType", commandType);
startActivity(intent);
}
So it works as should. My commands starts in background and when finished, my event fires and displays new activity with results (all results are received via getIntent().getExtras() and then formatted to be displayed as should).
Problem: on result activity I have "Refresh" button. When pressed, all data should be refreshed. So I need to execute ssh.ExecuteCommand(commandType); again to get refreshed data. Note that I don't want to open new ssh connection for this. Instead, I want to use already opened connection and simply execute my command again.
So I made my 'ssh' static and I used MainActivity.ssh.ExecuteCommand(commandType); on refresh button press. It works, but obviously, it causes to create second instance of ResultListActivity, instead of refreshing data on existing one.
I can even avoid to creating result activity again by checking if it's already exists (for example by adding 'active' boolean static variable to it). However, it won't help me because I still have no any possibility to refresh data inside my existing activity.
So, how can I do it?
No responses, so I'm answering to my own question. My solution was:
- Change my activity launchMode to singleTop
- Override method onNewIntent
In this case each time I start this activity: if activity already exists it won't be created again. Instead, onNewIntent method will be called.
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
http://developer.android.com/reference/android/app/Activity.html#onNewIntent%28android.content.Intent%29
However, I'm not sure if approach like this is good. How do you think?
Related
I have receiver and when some action is happening I need to reopen current activity(I am in HideSettingsActivity and I want to close that Activity and open the new one HideSettingsActivity). For this I'm just finishing current activity and open the new one via intent. Code below.
Intent reopenCurrentActivityIntent = new Intent(this, HideSettingsActivity.class);
reopenCurrentActivityIntent.putExtra(CURRENT_PASSWORD, passwordDialog.getPassword());
startActivity(reopenCurrentActivityIntent);
finish();
The problem is, that it's working only for first time,when receiver is gettings some action. Next times, opening new activity is not working. Other lines of code, which are before and after that piece of code, which I described above, they works fine.
So the question is, why it is happening like that? And maybe there are some others way, to reopen current activity?
Add flag intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)); to your intent.. like :-
reopenCurrentActivityIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
then,
startActivity(reopenCurrentActivityIntent);
and its better to use this :-
Intent reopenCurrentActivityIntent = new Intent(HideSettingsActivity.this, HideSettingsActivity.class);
I have created a startup activity from where I am calling another activity which has a view pager and shows some introductory pages.
This app was taking time to load so I thought to display a progress dialog till the activity loads, but that progress dialog also appears few seconds later.
startup activity:
public class StartUpActivity extends AppCompatActivity {
boolean isUserFirstTime, login;
public static String PREF_USER_FIRST_TIME;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isUserFirstTime = Boolean.valueOf(Utils.readSharedSetting(StartUpActivity.this, PREF_USER_FIRST_TIME, "true"));
Intent introIntent = new Intent(StartUpActivity.this, SlidingActivity.class);
introIntent.putExtra(PREF_USER_FIRST_TIME, isUserFirstTime);
ProgressDialog dialog = new ProgressDialog(StartUpActivity.this);
dialog.setMessage("Welcome to Mea Vita, please wait till the app loads.");
dialog.setCancelable(false);
dialog.setInverseBackgroundForced(false);
dialog.show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//Here you can send the extras.
startActivity(new Intent(StartUpActivity.this,SlidingActivity.class));
// close this activity
finish();
}
}, 4000);
}
}
This doesn't happen every time,only sometimes. What can be the possible reason for this? how can I stop this?
Any solution? Thank you..
There is a strange issue with newly released Android Studio 2.0 (same issue in 2.1) first time of launching application take longer than usual (e.g. 2, 3 seconds or sometimes screen blinks or goes black) this issue happens only in debug mode and not effect your released APK.
A temporary solution to fix this is disabling instant run:
Settings → Build, Execution, Deployment → Instant Run and uncheck Enable Instant Run
First of all, make as rule to make all data loading in async tasks, you must check activity that you want to start where you load data.
The problem is in your second activity.
oncreate method should be used only to make findviews or start async tasks, don't load any in oncreate or in onstart or in onresume.
Probably you are loading high res images in sliding layout or you loading data in it.
There is another way, load all data in async task on first activity, then with ready data start second activity with already data loaded.
There are a few things that can load slowly.
Android need to read your code from storage and load the classes into ram.
I assume Utils.readSharedSetting(StartUpActivity.this, PREF_USER_FIRST_TIME, "true") reads from preferences. That's a file that you're reading from synchronously.
Actually launching the dialog takes a very small amount of time.
I'd suggest showing your loading inside the activity itself to minimize the work needed to render it.
Also, you can store PREF_USER_FIRST_TIME as a boolean instead of a String.
If I'm bringing Android activities from the stack to the front, how do I refresh them? So to run onCreate again etc.
My code below, in conjunction with setting activities in the Android manifest to android:launchMode="singleTask" allows me to initiate an activity if that activity is not already active within the stack, if it is active within the stack it is then brought to the front.
How do I then, if the activity is brought to the front refresh it so that onCreate is ran again etc.
Intent intent = new Intent(myActivity.this,
myActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
I think FLAG_ACTIVITY_CLEAR_TOP will resolved your problem:
Intent intent = new Intent(myActivity.this, myActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
I don't think there is an explicit way to refresh onCreate, perhaps you may want to add the code you want reloaded into onResume.
This workaround may work if you want to keep your code in onCreate.
finish();
startActivity(getIntent());
If all you want to do is refresh the content, you should override the onResume method, and add in the code to perform the refresh in this method. To do this, use the following code within the activity that you want to perform the refresh, (ie, not the same activity that you are calling startActivity() from):
#Override
protected void onResume(){
super.onResume();
//add your code to refresh the content
}
Tip: If you are using Android Studio, press Alt+Insert (while you have the Java file open), then click Override Methods, find onResume, and it should provide you with a basic template for the method.
The diagram I added shows the order that the methods are run (this is known as the Activity Lifecycle). onCreate() is run whenever an Activity is first created, followed by onStart(), followed by onResume(). As you can see, when a user returns to an Activity, onCreate() is not run again. Instead, onResume() is the first method that is called. Therefore, by putting your code into the onResume() method, it will be run when the user returns to the activity. (Unlike onCreate(), which will not be run again).
Extra info: Since you will be initially setting the data in onCreate() and then refreshing it within onResume(), you might want to consider moving all of your code used to initially set the data to onResume() as well. This will prevent redundancy.
Edit: Based on your following comment, I can give the following solution:
I'm wanting to properly refresh the page, e.g. if there is a variable count initialised at 0. And though running the activity it's has became equal to 300. When the activity is called (intent) then refreshed, count will once again be equal to it's initial value. Do you know how to do this?
Without your current activity's code, there is not much to work with, but here is some pseudo-code as to how I would accomplish your problem:
public class MyActivity extends Activity {
TextView numberTextView;
int numberToDisplay;
#Override
protected void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(myContent);
numberTextView = (TextView) findViewById(R.id.numberTextView);
numberTextView.setText(numberToDisplay+"")//converts the integer to a string
}
#Override
protected void onResume(){
super.onResume();
numberToDisplay = 0;
numberTextView.setText(numberToDisplay+"");
}
}
I have an activity for handling deeplink which is a browsable activity
suppose user clicks a link on another app and my browsable activity handles that intent
and start the app, , then user minimise the app by pressing back button
class code for handling intent data
Uri link = getIntent().getData();
if user reopen app from running tasks getIntent() still have data
onDestroy method of browsable activity
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
setIntent(null);
}
setIntent(null) not working
so my question is how can i remove data from intent permanently
I am a little late on the answer here but I was dealing with a similar issue and found a solution. The reason you are still seeing data in the intent is because your app was originally started with an intent that contained data. That original intent is stored somewhere in Androids' ActivityManager and is immutable, to my understanding. When user reopens the app from "recent tasks", Android uses that original intent to recreate the application.
There is a workaround to this, however. In your apps onCreate() method, you can check to see if the Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY is set, which would allow your app to distinguish if it is being started from "recent tasks" or not, and therefore, you can avoid using the data contained in the intent.
Putting the following snippet in your onCreate() method would return true if the app is being opened from "recent tasks"
(getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0)
you have to remove data one by one key. i think you can't remove all data with one line.
if you want to remove specific key than you should use ==> getIntent().removeExtra("key"); or
getIntent().setAction("");
it will remove your data.
for more ==> Clearing intent
To remove the content it works best for me with the following lines of code.
//Clear DATA intent
intent.setData(null);
intent.replaceExtras(new Bundle());
intent.setFlags(0);
After that they can verify that the intent does not contain data
I've read through several posts about using this but must be missing something as it's not working for me. My activity A has launchmode="singleTop" in the manifest. It starts activity B, with launchmode="singleInstance". Activity B opens a browser and receives an intent back, which is why it's singleInstance. I'm trying to override the back button so that the user is sent back to activity A, and can then press Back to leave the activity, rather than back to activity B again.
// activity B
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ECLAIR
&& keyCode == KeyEvent.KEYCODE_BACK
&& event.getRepeatCount() == 0) onBackPressed();
return super.onKeyDown(keyCode, event);
}
#Override
public void onBackPressed() {
startActivity(new Intent(this, UI.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK));
return;
}
After returning from the browser, the stack is...
A,B,Browser,B
I expect this code to change the stack to...
A
... so that pressing back once more takes the user back to the Home Screen.
Instead, it seems to change the stack to...
A,B,Browser,B,A
...as though those flags aren't there.
I tried calling finish() in activity B after startActivity, but then the back button takes me back to the browser again!
What am I missing?
I have started Activity A->B->C->D.
When the back button is pressed on Activity D I want to go to Activity A. Since A is my starting point and therefore already on the stack all the activities in top of A is cleared and you can't go back to any other Activity from A.
This actually works in my code:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Intent a = new Intent(this,A.class);
a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(a);
return true;
}
return super.onKeyDown(keyCode, event);
}
#bitestar has the correct solution, but there is one more step:
It was hidden away in the docs, however you must change the launchMode of the Activity to anything other than standard. Otherwise it will be destroyed and recreated instead of being reset to the top.
For this, I use FLAG_ACTIVITY_CLEAR_TOP flag for starting Intent(without FLAG_ACTIVITY_NEW_TASK)
and launchMode = "singleTask" in manifest for launched activity.
Seems like it works as I need - activity does not restart and all other activities are closed.
Though this question already has sufficient answers, I thought somebody would want to know why this flag works in this peculiar manner, This is what I found in Android documentation
The currently running instance of activity B in the above example will either receive the new intent you are starting here in its onNewIntent() method, or be itself finished and restarted with the new intent. If it has declared its launch mode to be "multiple" (the default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created; for all other launch modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to the current instance's onNewIntent().
So, Either,
1. Change the launchMode of the Activity A to something else from standard (ie. singleTask or something). Then your flag FLAG_ACTIVITY_CLEAR_TOP will not restart your Activity A.
or,
2. Use Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP as your flag. Then it will work the way you desire.
I use three flags to resolve the problem:
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_CLEAR_TASK |
Intent.FLAG_ACTIVITY_NEW_TASK);
Add android:noHistory="true" in manifest file .
<manifest >
<activity
android:name="UI"
android:noHistory="true"/>
</manifest>
i called activity_name.this.finish() after starting new intent and it worked for me.
I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"
But it won't work for me... I am not suggesting this solution for use but if setting flag won't work for you than you can try this..But still i recommend don't use it
I know that there's already an accepted answer, but I don't see how it works for the OP because I don't think FLAG_ACTIVITY_CLEAR_TOP is meaningful in his particular case. That flag is relevant only with activities in the same task. Based on his description, each activity is in its own task: A, B, and the browser.
Something that is maybe throwing him off is that A is singleTop, when it should be singleTask. If A is singleTop, and B starts A, then a new A will be created because A is not in B's task. From the documentation for singleTop:
"If an instance of the activity already exists at the top of the current task, the system routes the intent to that instance..."
Since B starts A, the current task is B's task, which is for a singleInstance and therefore cannot include A. Use singleTask to achieve the desired result there because then the system will find the task that has A and bring that task to the foreground.
Lastly, after B has started A, and the user presses back from A, the OP does not want to see either B or the browser. To achieve this, calling finish() in B is correct; again, FLAG_ACTIVITY_CLEAR_TOP won't remove the other activities in A's task because his other activities are all in different tasks. The piece that he was missing, though is that B should also use FLAG_ACTIVITY_NO_HISTORY when firing the intent for the browser. Note: if the browser is already running prior to even starting the OP's application, then of course you will see the browser when pressing back from A. So to really test this, be sure to back out of the browser before starting the application.
FLAG_ACTIVITY_NEW_TASK is the problem here which initiates a new task .Just remove it & you are done.
Well I recommend you to read what every Flag does before working with them
Read this & Intent Flags here
Initially, I also had a problem getting FLAG_ACTIVITY_CLEAR_TOP to work. Eventually, I got it to work by using the value of it (0x04000000). So looks like there's an Eclipse/compiler issue. But unfortunately, the surviving activity is restarted, which is not what I want. So looks like there's no easy solution.