I have two activities: MainActivity and EventActivity.
Whenever I open my app (in MainActivity by default) and it has a certain flag in SharedPreferences, it intents to EventActivity and finishes itself. Otherwise, it only intents.
In EventActivity I have a button that, when clicked, calls finish() and goes back to EventActivity.
The problem is, when I re-open my application, it will finish the MainActivity and, when I press my custom back button, it will close the app (because the intent handle has finished).
How do I check if MainActivity didn't used finish()?
If I can do that, checking if it is finished I can intent to it.
Thanks.
Override the onDestroy method of MainActivity in that set a public static Boolean field of MainActivity. In that method set that public static field as true. Check for its value in EventActivity before you finish it i.e. when you are coming back from EventActivity to MainActivity. And fire an intent to start MainActivity from EventActivity if it's value is true. And set it's value as false in onCreate of MainActivity.
As follows:
In MainActivity.java
public class MainActivity extends Activity {
public static boolean isMainActivityDestroyed = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isMainActivityDestroyed = false;
.
.
.//Do something here
}
#Override
protected void onDestroy() {
super.onDestroy();
isMainActivityDestroyed = true;
.
.
.//Do something here
}
}
In EventActivity.java
public class EventActivity extends Activity {
.
.
.//Some methods
//Method which finishes EventActivity & starts MainActivity if destroyed
public void buttonOnClick()
{
if(MainActivity.isMainActivityDestroyed)
{
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
finish();
}
}
}
If isMainActivityDestroyed becomes true then it is an indication that MainActivity used finish().
You could create your own Application class extending Application and launch the needed activity from your Application's onCreate. In manifest you would then remove the default intent filter for your MainActivity.
Related
I am trying to finish one activity from another.
For that purpose I am having only the component name of that activity.
How can i finish that ?
1.Make your activity A in manifest file: launchMode = "singleInstance"
2.When the user clicks new, do FirstActivity.fa.finish(); and call the new Intent.
3.When the user clicks modify, call the new Intent or simply finish activity B.
FIRST WAY
In your first activity, declare one Activity object like this,
public static Activity fa;
onCreate()
{
fa = this;
}
now use that object in another Activity to finish first-activity like this,
onCreate()
{
FirstActivity.fa.finish();
}
SECOND WAY
While calling your activity FirstActivity which you want to finish as soon as you move on, You can add flag while calling FirstActivity
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
But using this flag the activity will get finished evenif you want it not to. and sometime onBack if you want to show the FirstActivity you will have to call it using intent.
You can do it in very simple way.
First create a static instance of your activity e.g. MainActivity, whom you want to finish like,
public static MainActivity act=MainActivity.this;
and now in another actvity e.g. MainActivity2 just call this line,
MainActivity.act.finish();
Try extending that activity and override the finish method
public class ma extends MainActivity{
#Override
public void finish()
{
super.finish();
}
}
You want to exit application after log out.
that time to user this
i.addCategory(Intent.CATEGORY_HOME);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
or try to another way like
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
moveTaskToBack(true);
finish();
}
I have three activities ActivityA, ActivityB, ActivityC.
Suppose in ActivityA, there is some code like...
if(someCondition()){
gotoActivityB();
}
else{
gotoActivityC();
}
Now, If user goes to ActivityB, ActivityA should not be finished.
If he goes to ActivityC, it should be finished.
Adding noHistory in manifest file doesn't work.
Also, finish()in if condition doesn't work, As there are many activities after ActivityC in which ActivityA should be in background.
I don't want to call startActivity(context,ActivityA.class)in those activities onBackPressed() because, it will again execute code of onCreate() in ActivityA.
So, is there a way, where i can remove ActivityA from the stack when user presses back button in ActivityB?
may be something like this:?
ActivityB.this.finish();
ActivityA.finish(); //some code to finish ActivityA
Okay, here is one way you can accomplish your goal. You will need to pass around the Activity context to wherever you need it in order to call finish() on it. I used the Application class to do this. I only used two classes to do it for the sake of time, but it should work just fine for your purposes. Here is how I did it:
This is the first class. It is the Activity that we want to close from another Activity.
public class MainActivity extends Activity implements OnClickListener {
private Button button;
// application instance
private MainApplication mainApplication;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainApplication = (MainApplication) getApplicationContext();
// set the Activity's context for later usage. Doing this determines which
// Activity can be closed from another Activity.
mainApplication.setActivityContext(this);
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
Intent i = new Intent(this, SecondActivity.class);
startActivity(i);
break;
}
}
}
This is the Second Activity. Exiting out of it will also cause finish() to be called on the first class:
public class SecondActivity extends Activity {
private Activity activityContext;
private MainApplication mainApplication;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_activity_layout);
mainApplication = (MainApplication) getApplicationContext();
// get the Activity context you stored in the MainApplication class
// so you can call finish on it.
activityContext = mainApplication.getActivityContext();
}
#Override
protected void onPause() {
super.onPause();
// closes your defined Activity. If you press the back button you will find
// that you exit right out of the app as the other Activity gets popped off
// the stack.
activityContext.finish();
}
}
And the Application class:
public class MainApplication extends Application {
private Activity activityContext;
public Activity getActivityContext() {
return activityContext;
}
public void setActivityContext(Activity activityContext) {
this.activityContext = activityContext;
}
}
And of course make sure to declare your MainApplication class in the AndroidManifest:
<application
android:name=".MainApplication"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
This is a sort of hacky way to do this. There may be better ways. But regardless, you have to pass around the context of the Activity that you want to call finish() on. Then you can close it from anywhere.
Hi you can finish your activity in current activity itself based on the condition. or use StartActivityforResult based on the result you can finish your activity.
hope this will help you.
You can try this in another way, like i do.
Create a static instance variable of the activity in the beginning.
private static Activity1 thisAct = null; // Activity1 is name of class
Now initialize this variable in onCreate() method
thisAct = this;
Create a static method which will finish this activity
public static void finishActivity()
{
thisAct.finish();
}
While going to Activity C, clear the FLAG :
Intent cIntent = new Intent(view.getContext(), cActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(cIntent);
This looks very similar to my previous question because it's some sort of follow up. I was not very happy with the only solution given; also, the solution was for a problem slightly different from this one. So let me try to explain the problem again...
A notification is created at boot (with a BroadcastReceiver).
My app main activity is opened and the home button is pressed (the activity will be sent to the back stack).
I pull down the status bar and press on the notification previously created at boot.
That will start some activity, different from the main one.
I press the back button and the main activity is displayed.
This is not very different from my previous question... The thing is, "main activity" was just an example. I could have opened the app main activity and then opened the about activity through a menu option and pressed the home button. The back stack would now be MainActivity ยป AboutActivity. Which means that when the back button is pressed while in "some activity" (started by pressing the notification), we would be brought to the top of the back stack, that is, the about activity.
What basically want is to prevent any other activity to be opened when I press the back button while in "some activity" (again, started by pressing the notification). I want to be brought exactly where I was, that could be the desktop or some other app's activity, but not my app's MainActivity nor AboutAcitivity cause that's not where I was, those were in the back stack, "sleeping" in the background.
I have come up with a solution, but I don't think it's very elegant and I was looking for something more, well, elegant... If you have any other suggestion, please, let me know.
Anyway, this is my proposed solution:
// I use this class for public static (or public static final) members and
// methods
public final class AppHelper {
public static final String KEY_RESUME_FROM_NOTIFICATION = "resumeFromNotification";
private static boolean sResumeFromNotification = false;
public static boolean getResumeFromNotification() {
return sResumeFromNotification;
}
public static void setResumeFromNotification(boolean resumeFromNotification) {
sResumeFromNotification = resumeFromNotification;
}
}
public class MainActivity extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
(...)
}
#Override
protected void onResume() {
super.onResume();
if(AppHelper.getResumeFromNotification()) {
AppHelper.setResumeFromNotification(false);
moveTaskToBack(true);
}
}
}
public class AboutActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
(...)
}
#Override
protected void onResume() {
super.onResume();
if(AppHelper.getResumeFromNotification()) {
AppHelper.setResumeFromNotification(false);
moveTaskToBack(true);
}
}
}
public class SomeActivity extends Activity {
// This will be called when the notification is pressed and the activity is
// not opened yet
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
(...)
extractIntentExtras(intent);
}
// This will be called if the activity is already opened and the
// notification is pressed
#Override
protected void onNewIntent(Intent intent) {
extractIntentExtras(intent);
super.onNewIntent(intent);
}
private void extractIntentExtras(Intent intent) {
Bundle bundleExtras = intent.getExtras();
if(bundleExtras != null) {
// These intent extras are set on the Intent that starts this activity
// when the notification is pressed
AppHelper.setResumeFromNotification(bundleExtras.getBoolean(
AppHelper.KEY_RESUME_FROM_NOTIFICATION));
mRowId = bundleExtras.getLong(AgendaNotesAdapter.KEY_ROW_ID);
populateNoteUpdateFields();
}
}
}
I don't know, but this solution doesn't look very elegant to me (but it works as I expect it) and I'm looking for alternatives or for strong opinions on my proposed solution as an acceptable and good solution. Thoughts?
After doing some more reading perhaps this is the combination of flags you need:
Intent intent = new Intent(mContext, SomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);
I think that should force your SomeActivity class to be launched in a completely new task.
When launching the Activity from the notification, you can control how the Activity you are about to open is put on the back stack, and what task it's associated with with Intent flags. You can try something like:
Intent intent = new Intent(mContext, SomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
If that doesn't work, try setting a few of the other flags until you get the desired behavior.
Do you ever want your MainActivity to stay in history? If not then my simple, crude solution is to finish the MainActivity when it is paused.
(Call this in your MainActivity)
#Override
public void onPause() {
finish();
}
This will ensure that your MainActivity is removed from history when you navigate away from it, and will never appear when the back button is pressed.
This could be used for AboutActivity as well.
I'm writing a test for an activity that have a few buttons,
each one of than starts a new Activity,
How can I know if the button is starting the correct activity?
This is what I have so far:
public class MainActivityTest extends ActivityUnitTestCase<MainActivity> {
private Intent mMainIntent;
public MainActivityTest() {
super(MainActivity.class);
}
#Override
protected void setUp() throws Exception {
super.setUp();
mMainIntent = new Intent(Intent.ACTION_MAIN);
}
#MediumTest
public void testButtonActivityA () {
MainActivity activity = startActivity(mMainIntent, null, null);
Button buttonActivityA = (Button) activity.findViewById(com.project.R.id.button_activity_a);
buttonVoice.performClick();
Intent i = getStartedActivityIntent();
assertNotNull(i);
assertTrue(isFinishCalled());
}
}
PS: the 'isFinishedCalled()' is failing, how can this be if I raise a new fullscreen Activity?
Thanks,
It's failing because finish() isn't called.
you have to finish an activity yourself, otherwise when you open a new one it comes up over the top on the 'stack' and the original activity has onPause called but is still 'alive'. finish() is an implicit call that you can code into your app to destroy an activity.
Please go read about the Android Activity Lifecycle
Then learn to call when you should call finish()
In my application I have an activity class A that has a listview with a cursor adapter.
From A I can go to the activity B, by pressing a button. From B I can go back to A by pressing a button (not by pressing the BACK button). This means that a new instance of the A activity is created.
From this point, if I press the BACK key, the current A activity is destroyed and B is popped. And if I press BACk again the initial A activity is popped. I hope it is clear.
My problem is that when the second A activity is destroyed, the database connection is reseted, in a static manner. So in the end, when the initial A activity is displayed, the listview will be empty.
My question is: should I try to have a single instance for the A activities, or shoud I change the database connection (to link it with the activity instance)?
Thanks a lot
Gratzi
First Of All In class A which is carrying your ListView . on clicking any Listview call the startActivity method for the Class B Activity without calling any finish().
I hope which is you are already doing.
Now in the Second Activity The button (Not the Back Button) you are using for calling Activity A . in its clickListener for calling Activity A dont call the startActivity(intentForA) instead call the finish(); for ending the Activity B. this will resume the A activity which is paused..
I hope this will help
You will need to create 3 Activities rather than 2.
Have a MAIN activity that does not really display anything.
So You have Activity A that is your main activity that can handle the connection to the DB etc.
Then Activity B and C can be the A and B that you have used.
Activity A (Main activity) can have a static instance of itself so you can refernce it's
Variables etc -OR- you can pass data from one activity to the other using Intent.put, etc.
I prefer the global static instance way as I'm a little old school on Java.
Edit:
Forgot to mention, to handle the 'closing' of the app, either Activity B or C must also close Activity.
public class ActivityA extends Activity {
ActivityA act_a_instance;
public int some_integer = 22;
#Override
public void onCreate(Bundle savedInstanceState) {
act_a_instance = this;//Now you can reference this Activity outside
//Your creation stuff etc
}
}
public class ActivityB extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
//Your creation stuff etc
//Reference stuff from ActivityA like so :
int temp_integer = ActivityA.act_a_instance.some_integer;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.options_back:
startActivity(new Intent(this, ActivityC.class));
break;
}
}
#Override
protected void onStop() {
finish();
super.onStop();
}
}
public class ActivityB extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
//Your creation stuff etc
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.options_back:
startActivity(new Intent(this, ActivityB.class));
break;
}
}
#Override
protected void onStop() {
finish();
super.onStop();
}
}
Use below code hope this will solve your problem
Intent i = new Intent(B.this, A.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);