The first activity of my android app, the "launcher activity", finishes pretty quickly. It's goal is to redirect to the MainActivity or to the UserLoginActivity, depending on the value of a shared-preferences variable.
If this variable does not exist, it automatically perform a StartActivity to the MainActivity.
If this variable is set, then it will perform an HTTP request to my API, in order to Authenticate the user. Then it will start the MainActivity. The HTTP request usually takes less than one second.
The thing is that I would like to display a progress bar, in the center of the LauncherActivity, so the user can understand that something is loading.
The problem is that nothing is displayed on the screen. But if I comment the line that starts the activity, then it will be displayed... It seems that the activity duration is too fast to display anything !
I thought calling the setContentView() method will instantly load Views on the screen. Is my case a normal behavior ? How could I display a progress bar on the screen, knowing that the activity will last around one second ?
Here you can see my Launcher Activity
public class Launcher extends Activity {
private void goToUserLogin(){
Intent intent;
intent = new Intent(this, UserLoginActivity.class);
startActivity(intent);
finish();
}
private void goToMain(){
YokiAPI API = new YokiAPI(this);
Intent intent;
try {
if (API.authenticateSmart(YokiGlobals.preferences.getSavedUserId(this))) {
intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
} else {
this.goToUserLogin();
}
} catch (Exception e){}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launcher);
// Launch Demo if First Run
if (YokiGlobals.preferences.getFirstLaunch(this)){
YokiGlobals.preferences.updateFirstLaunch(false, this);
this.launchDemo();
}
/*
** If userId saved, smart Auth and go to Main
** Else go to User Login for Full Auth or register
*/
if (YokiGlobals.preferences.getSavedUserId(this) == null){
this.goToUserLogin();
}
else {
this.goToMain();
}
}
}
And the .xml ressource file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="THIS TEXT WONT APPEAR"
android:layout_marginTop="208dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Thanks,
Oscar
I thought calling the setContentView() method will instantly load Views on the screen
No it won't because you are still in onCreate(). If you want to see any UI you need to let the activity cycle to go further, so rework your code or move your authentication to separate activity, meybe?
PS: you use this. without any real reason.
Thank you for your help. I used AsyncTask in order to fetch data from the API.
The main UI thread can now load the view.
Here is some very simplified code that maybe could help others.
public class UserSmartAuthActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_smart_auth);
new SmartAuth().execute();
}
private class SmartAuth extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
Context context = getApplicationContext();
YokiAPI API = new YokiAPI(context);
Intent intent = null;
try {
if (API.authenticateSmart(YokiGlobals.preferences.getSavedUserId(context)))
intent = new Intent(context, MainActivity.class);
else
intent = new Intent(context, UserLoginActivity.class);
} catch (Exception e){}
startActivity(intent);
finish();
return null;
}
}
}
Related
Every time my app enters pAUSE stage and enters onresumestage, i am killing my current activity and start new Acitivy. And at the same time in onresume stage, i try to make some button visible. Some how the visibility function never gets updated. Always stays at defualt invisible stage... any help highly appreciated. ..
// code in onresume stage that makes button ready visible and at the same time call refresh function
public void onResume() {
super.onResume();
refresh();
runOnUiThread(new Runnable() {
#Override
public void run() {
ImageButton ready = (ImageButton) findViewById(R.id.ready);
ready.setVisibility(View.VISIBLE);
}
});
}
// thats where i am killing current activity and starting new activity
public void refresh() {
Intent intent = getIntent();
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
// MediaPresentationActivity.this.finish();
finish();
recreate();
overridePendingTransition(0, 0);
startActivity(intent);
}
// xml image button set default visibility to invisible
<ImageButton
android:id="#+id/ready"
android:layout_width="90dp"
android:layout_height="90dp"
android:visibility="invisible"
/>
From the best of my knowledge , refreshing activity kill the current activity. Only issue could be onResume function. You should try java Synchronous function. Currently setvisbility for image button is executed before finishing the refresh function . Actually it does set image button to visible, but refresh function will delete it as both run at the same time. so you should try Synchronous function : which allow second function to call ,only after first function is executed completely.
what simply you can do is calling the same activity again like
Intent intent=new Intent(MainActivity.this,MainActivity.class);
startActivity(intent);
finish();
Note: Replace MainActivity with your own class name.
This question already has answers here:
How to start new activity on button click
(28 answers)
Closed 5 years ago.
My app runs well and shows no errors, but my button is not working ( is unClickable in device)
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button11=(Button)findViewById(R.id.button11);
button11.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
new Intent(MainActivity.this, Main2Activity.class);
}
});
}
}
and XML file :
<Button
android:id="#+id/button11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50px"
android:layout_marginTop="200dp"
android:background="#color/colorPrimary"
android:text="صفحه اصلی"
android:onClick="onClick"/>/>
On the real device when I click on this button nothing happens !
try this way
Intent i = new Intent(MainActivity.this, Main2Activity.class);
startActivity(i);
EDIT: I wanted to add a bit of an explanation to help
Hi MRAK,
First things first, you do NOT need to create an onClick listener. Remove all of that completely. Android studio is a beast and automatically does that for you using the XML file. When you set "onClick" in the XML file, it automatically calls the name of whatever method you put in there. You should change it so it is not also called "onClick." I would prefer to call it "startAcitivty2" or so on so you are not confused later. I stuck with your method name for now.
See below for corrected code:
public void onClick(View v){
// note in the below line i'm just using "this"
Intent myIntent = new Intent(this, Main2Activity.class)
// Secondly, you need to end the current activity
finish();
// Third, you need to start your new activity...
// Creating an Intent does not the activity alone
startActivity(myIntent);
}
Also, this has so many downvotes because this has been asked 1000+ times. Please use google or the search bar above before asking. Google will reroute you to stackoverflow anyway :)
I have two android activities with one single button on both.
The activity DetailsActivity is my MAIN activity.
public class DetailsActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.details_activity_layout);
}
#Override
public void onResume() {
super.onResume();
}
public void gotoSubDetails(View view) {
Intent intent = new Intent(this, SubDetailsActivity.class);
startActivity(intent);
finish();
}
}
And my SubDetailsActivity is as follows:
public class SubDetailsActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.sub_details_activity_layout);
}
#Override
public void onResume() {
super.onResume();
}
public void gotoDetails(View view) {
Intent intent = new Intent(this, DetailsActivity.class);
startActivity(intent); // Restarting the finish()ed activity here.
finish();
}
}
And this is how I mentioned my button in details_activity_layout.xml for DetailsActivity.java:
<Button android:id="#+id/details_submit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/to_sub_details"
android:onClick="gotoSubDetails" />
And this is how I have mentioned my button in sub_details_activity_layout.xml for SubDetailsActivity.java:
<Button android:id="#+id/sub_details_submit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/back_to_details"
android:onClick="gotoDetails" />
These are my both activities in AndroidManifest.xml:
<activity android:name="DetailsActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="SubDetailsActivity">
</activity>
When I click the button in DetailsActivity, the activity finish()es properly and SubDetailsActivity starts up.
But when I click the button in SubDetailsActivity to get back to the finish()ed DetailsActivity, the app straight away crashes on my LG L90 phone.
Where am I going wrong? Any help? Please.
PS:
I cannot post the log cat report as I did not test it on my mac but directly on my phone. I don't have an emulator. I am compiling the code on my terminal and transferring the .apk file on my phone via bluetooth.
EDIT:
Ok guys. Now this is really funny!
I removed the
android:onClick="gotoSubDetails"
and
android:onClick="gotoDetails"
from my details_activity_layout.xml and sub_details_activity_layout.xml respectively. And I loaded the android.widget.Button's in my DetailsActivity.java and SubDetailsActivity.java and added an android.view.View.OnClickListener on both of them and overrode the onClick(View) method.
This is what I did in my DetailsActivity.java:
public class DetailsActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.details_activity_layout);
Button button = (Button)findViewById(R.id.details_submit);
button.setOnClickListener(new DetailsSubmitListener());
}
#Override
public void onResume() {
super.onResume();
}
public class DetailsSubmitListener implements OnClickListener {
#Override
public void onClick(View view) {
Intent intent = new Intent(this, SubDetailsActivity.class);
startActivity(intent);
finish();
}
}
}
And this is what I did in my SubDetailsActivity.java class:
public class SubDetailsActivity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.details_activity_layout);
Button button = (Button)findViewById(R.id.sub_details_submit);
button.setOnClickListener(new SubDetailsSubmitListener());
}
#Override
public void onResume() {
super.onResume();
}
public class SubDetailsSubmitListener implements OnClickListener {
#Override
public void onClick(View view) {
Intent intent = new Intent(this, DetailsActivity.class);
startActivity(intent);
finish();
}
}
}
And this miraculously worked fine.
So what was the problem with the .xml attributes in my layout files? And how different is it from the hardcoded listener in my .java file? This thing has confused me. finish()ed activities can be re-started. Thats what I discovered with my change in the program. Please shed some light of knowledge on this.
Aditya,
If you want to traverse between 2 activities like in your case, you should never finish Details activity. Instead without finishing Details activity, start SubDetails activity. If you want to come back, no coding required. If user presses BACK button, SubDetails Activity will be finished and DetailsActivity will come to foreground.
Finishing one activity and starting it again, is unnecessary overhead. Avoid it. Finish activity if it is absolutely necessary.
Also, there is no any way to restart finished activity.
Just like Harry answered,
I want to add something for you. If you are programming for higher API Levels (e.g. Android API 13+) you can define a parent activity.
This way you don't need to make such complex implementations.
For reference
Google Developers Guide to UP navigation
Stackoverflow ANSWER on the topic
I think you should read this!:
http://developer.android.com/guide/components/tasks-and-back-stack.html
I think it's very important how you declared the launchMode in your andriodManifest for your activities ! There should be the problem. Read carefully what is a task and how a back stack in android works.
Maybe you are finishing the task but at same time you are viewing the next activity which is in the same task ! After reopen it crashed because of this I think. Hope it helps.
In an activity, I have created a AsyncTask after hiding the activity:
this.moveTaskToBack(true);
(new MyTask(this)).execute();
To show a dialog in the task (in onPostExcecute), I want to bring the activity to front:
alertDialog.show();
Intent intent = new Intent(mainActivity, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mainActivity.getBaseContext().startActivity(intent);
But a new instance of the main activity is created and shown on top of the dialog, although the application was still running (the activity has also a dialog style Theme.Dialog). How should I fix this?
Edit: According to javadoc, this code always recreates the activity and doesn't bring its previous instance to front, since startActivity is called from outside of an Activity Context.
How about adding a new piece of information to that intent, and catching it in onCreate()?
What I mean is something like this:
public class MainActivity extends Activity {
public static final String WANT_DIALOG_EXTRA = "WANT_DIALOG_EXTRA";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getIntent().hasExtra(WANT_DIALOG_EXTRA)) {
// create and show dialog
}
}
}
Then when you create your intent, add one more line like this:
intent.putExtra(MainActivity.WANT_DIALOG_EXTRA, true);
I have three activities: First, Second and Third. I used this method in Second activity:
public void onBackPressed() {
super.onBackPressed();
finish();
}
and this on Third activity:
public void onBackPressed() {
super.onBackPressed();
Intent i = new Intent(Third.this, Second.class);
startActivity(i);
finish();
}
The problem is when I press back button after coming from the Third activity, I am going into First activity instead of finish(). I am successfully exiting the application when I click back button right after coming from first activity but not after coming from Third activity.
How to solve this problem?
EDIT: Thanks for the answers guys,the answer of "Ved Prakash" solved the problem for me.But i have a weird problem now.When i press back button the app is successfully exiting but the app which i minimized to Recent Apps button is coming on to the screen and exiting.For example,if i have opened Setting app before opening my app,when i press back button,my app is exiting and immediately Settings app is also opening and exiting itself.What might be the problem?
Your problem is that you don't seem to understand how Activities work. The finish() function ends the current Activity, and then you receive the previous Activity from the backstack.
My recommendation is that you should use a single Activity, and hold Fragments inside it. If you want it so that pressing the Back button ends the application at any screen that is displayed, you could do the following:
Activity XML:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/initial_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Activity that holds the Fragments:
public class InitialActivity extends FragmentActivity implements ReplaceWith
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_initial);
getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener()
{
public void onBackStackChanged()
{
int backCount = getSupportFragmentManager().getBackStackEntryCount();
if (backCount == 0)
{
finish();
}
}
});
if (savedInstanceState == null)
{
getSupportFragmentManager().beginTransaction().add(R.id.initial_container, new FirstFragment()).commit();
}
}
#Override
public void replaceWith(Fragment fragment)
{
getSupportFragmentManager().beginTransaction().replace(R.id.initial_container, fragment).commit();
}
}
Example for a Fragment:
public class FirstFragment extends Fragment implements View.OnClickListener
{
private ReplaceWith activity_replaceWith;
private ImageView exampleImage;
public FirstFragment()
{
super();
}
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
try
{
activity_replaceWith = (ReplaceWith) activity;
}
catch (ClassCastException e)
{
Log.e(getClass().getSimpleName(), "Activity of " + getClass().getSimpleName() + "must implement ReplaceWith interface!", e);
throw e;
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
exampleImage = (ImageView) rootView.findViewById(R.id.fragment_first_example_image);
exampleImage.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View v)
{
if(v == exampleImage)
{
activity_replaceWith.replaceWith(new SecondFragment());
//please note that this should be done only if you are planning
//only on single-screen applications
//with no other layouts based on orientation or size
//otherwise, the Activity needs to be responsible for this, not the Fragment
}
}
}
This way, when you press the Back button, your application would end from any displayed screen.
Ok your code is wrong.
If you will look at activity source, you see that activity.onBackPressed() is calling finish(). So if call super.onBackPressed() you don't need to call finish.
Finish() is not stopping your application, it's stopping current activity.
Your code on third activity very strange. You are trying to stop activity and start another same activity.
What exactly you want to achieve?
If you want to exit application from your third activity, you need to clear your backstack. But I think you have problem with structure of your app.
Ok. then you should finish your first activity when you go to second activity like this(If you are using intent for that):
Intent it=new Intent(FirstActivity.this,SecondActivity.class);
finish();
startactivity(it);
and same for Second Activity:
Intent it=new Intent(SecondActivity.this,ThirdActivity.class);
finish();
startactivity(it);
this done your work...when you are in third activity the above activities are finished..
and when you press backButton you will be exit from application..
Good luck.
You can use -
public static final int FLAG_ACTIVITY_CLEAR_TOP
If set, and the activity being launched is already running in the
current task, then instead of launching a new instance of that
activity, all of the other activities on top of it will be closed and
this Intent will be delivered to the (now on top) old activity as a
new Intent.
And here is how -
When the user wishes to exit all open activities, they should press a button which loads the first Activity that runs when your app starts, in my case "MainActivity".
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
The above code clears all the activities except for LoginActivity. LoginActivity is the first activity that is brought up when the user runs the program. Then put this code inside the LoginActivity's onCreate, to signal when it should self destruct when the 'Exit' message is passed.
if (getIntent().getBooleanExtra("EXIT", false)) {
finish();
}
This explanation part is also introduced at exit-an-android-app.