So I'm working on this project, and its rather large in size. I've have put a kind of 'behind the scenes' security login system in.
Pretty much, all the activities extend the subActivity class, and the subActivity extents Activity. This has allowed me to make every form automatically .putExtra() when it starts a new activity, and on every onCreate() it will check the incoming data and determine whether it should force the user to login (push them to the LoginActivity).
So right now, the login activity, on successful login, it loads to the MainActivity. I want it to dynamically load the activity the user was last at...
This means, store the class of the activity that launched the LoginActivity in the extras, and then have the LoginActivity, on successful login, get the class from the extras and use it to start the Activity.
I'm looking for the simplest way possible, I was trying serializable, but was having a lot of issues and thought there must be another way to just pass a reference to the 'destination' class.
Hope this makes sense!
Cheers
You could use Java reflection API:
Call your login activity like this:
Intent intent = new Intent(this, LoginActivity.class);
intent.putExtra("activity", getClass().getName());
startActivity(intent);
Then parse the calling activity's name in login activity and go back to it after successful log in:
private String mActivity;
#Override public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
// ...
mActivity = "";
Bundle extras = getIntent().getExtras();
if (extras != null)
mActivity = extras.getString("activity");
}
}
#Override public void onClick(View view)
{
try {
Class<?> cls = Class.forName(mActivity);
startActivity(new Intent(this, cls));
}
catch (Exception e) {
e.printStackTrace();
}
}
In the LoginActivity, simply call finish() which will return to the next Activity on the Stack, in your case going back to the previous one.
You can start your login activity by startActivityForResult and then check result of login activity in your main activity. Look here http://developer.android.com/reference/android/app/Activity.html#StartingActivities
Related
I have an activity which can be accessed via different activities.
Like you have one activity containing a listview and the second containing a gridview and both shows the same data. When you click on an item a new activity with some details is shown. I need to somehow remember which activity was the initial one (with gridview or listview) so that I can set a button to redirect here. But it's not enough to just return to previous activity (like using finish() to close the current one), because there is a way to navigate among different objects from inside the details activity (I have a gridview on that screen). So I need to remember the initial view during moving through the details activity for various number of times.
Is there a way?
EDIT: omg why so many downvotes? At least tell me why it is so stupid, I'm learning coding for Android for 2 weeks how am I supposed to know everything??
This sounds like it would best be solved by using two Fragments within the same Activity
You can use a bundle object to pass data to the new activity (B) so you could know wich activity (listView or gridView) had started it.
In activity B:
private static final String ACTIVITY_TYPE = "activity_type";
public static Intent createIntent(Context context,String activityType)
{
Intent intent = new Intent(context, ActivityB.class);
Bundle b = new Bundle();
b.putString(ACTIVITY_TYPE,activityType);
intent.putExtras(b);
return intent;
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle b = getIntent().getExtras();
String activityType;
if (b != null)
{
activityType = b.getString(ACTIVITY_TYPE);
}
//the calling activity didn't use the createIntent method and didn't provide the activity type
else
{
activityType = "some_default_type";
}
//save activity type to use later
//rest of your code
}
In the calling activity:
Intent intent = ActivityB.createIntent(ActivityListView.this,"activity_list_view");
startActivity(intent);
I have an Android Best Practice question. I have to following code, which is working nicely, but I think it is not so elegant. So, my question is: at which point of activity life cycle is nice to start another activity ?
public class LoginActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ParentPreferences parentPreferences = new ParentPreferences(getApplicationContext());
if (parentPreferences.isPassExists()) {
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
} else {
setContentView(R.layout.login);
}
}
}
The task is about: if the parent has already made a password to protect the app, than we don't need to show the LoginActivity. I don't know, is it "healthy" for an Activity to give an intent to launch, when nor the onCreate nor the other lifecycle methods completed.
What are you thoughts guys ?
I think the better way is to create LauncherActivity, and start activitys from them:
For example:
public class LauncherActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ParentPreferences parentPreferences = new ParentPreferences(getApplicationContext());
Intent intent;
if (parentPreferences.isPassExists()) {
intent = new Intent(this, MainActivity.class);
} else {
intent = new Intent(this, LoginActivity.class);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
startActivity(i);
}
}
Updated:
Refering to Activity | Android Developer
onCreate is a first lifecycle method, сonsequently better to start activity B when A activity just started and does not inflate any layout
I would have the manifest start your MainActivity or whatever you call it. The MainActivity starts by checking if the user has logged in. If not, it starts your LoginActivity, which comes back in onActivityResult() with the result of the login.
It does depend on the requirement for the user to log in every time they start the app, or just once, or once in a while. If the use has to log in every time, than it's ok to start with LoginActivity. Otherwise, starting LoginActivity every time and passing to MainActivity (or whatever) seems just a waste. "Waste" not in the sense of performance, but of clarity of your app.
I think the best solution for you is to add a SplashScreen or like a "fake" screen.
Here you check if he's logged in already and based on it you start the correct activity.
Maybe the absolutely best way would be to do it with fragments, but you have to change a lot of your app.
About when to call it, the onCreate is perfect :)
i make app with two activities.
firs has:
2 ExitText(login and password);
button(confirm, save data with SharedPreferences, intent to second activity).
second one:
2 TextView(get login and password with SharedPreferences);
button(clear data on SharedPreferences, intent to firsActivity).
how to make next: while there are some data on SharedPreferences - app will be started from the 2nd screen.
for example, i made:
if (user!=null && pass!=null){ Intent enterIntent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(enterIntent);
}
but, technically it first run the firstActivity and than go to the secondOne. if there are some method to start app with the another activity (not mainOne)?
You won't be able to check to see if there are values in SharedPreferences before entering one Activity.
What you can do is check the value before displaying the UI (before calling setContentView(R.layout.my_layout)), and either continue along, or start the next Activity.
public class MyStartActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences preferences = getSharedPreferences("my_prefs", Context.MODE_PRIVATE);
if (preferences.contains("my_key")) {
// start next Activity
}
setContentView(R.layout.my_layout);
}
}
If you don't want the first one on the back stack, you can call finish() after starting the second one (or use appropriate flag(s) on intent).
Another approach would be to have only one activity with to fragments and decide dynamically which one set on start. With fragments you can also easily change layouts on button click or on back pressed.
I'm not sure if it will work, because app has to start at the first activity. First activity checks login and pass at share preferences and then you can go to the second activity
try this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences preference = getSharedPreferences("my_prefs", Context.MODE_PRIVATE);
if (preference.getSting("key",null)!= null) {
// start new Activity
//finish this activity so it not in back stack
} else {
setContentView(R.layout.my_layout);
}
}
There are some applications in which you can logout at any point within. e.g you login and then your browse around. you use the action bar or the menu button to logout. I can call finish() at that very point but then it will just pop the last activity. Even if i move the user forward to the Home Activity, still the stack remains in memory. Is there any way to destroy the remaining stack?
The easiest way to do this is to clear the stack back to your home or first activity, and pass an identifier saying to exit the app. For example:
public class ActivityOne extends Activity {
public static final String FINISH_THIS = "FINISH_THIS";
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(intent.hasExtra(FINISH_THIS)) {
finish();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(getIntent().hasExtra(FINISH_THIS)) {
finish();
}
}
}
public class ActivityTwo extends Activity {
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.logout) {
Intent intent = new Intent(this, ActivityOne.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(ActivityOne.FINISH_THIS, true);
startActivity(intent);
}
return true;
}
}
If ActivityOne is the root of your stack and ActivityTwo is where the user selected the option to logout, starting an intent that clears back to ActivityOne will get rid of the backstack. If you want the app to exit when logging out, you can pass an extra like I did with FINISH_THIS to signal the root/home activity to finish.
Another way to do this would be to call setResult(FINISH_THIS) where FINISH_THIS is an int identifier before calling finish(). Then in all other activities in the stack, you'd override onActivityResult and check the result to see if that activity needs to be finished. If it does, you set the result again and keep passing it down the line.
Using the intent method I outlined in the beginning is the preferred method for clearing the stack as it doesn't rely on daisy chaining results together but both options work well enough.
A quick and dirty way to do it would be onResume verify you are still logged in, if not then finish it. That way if they hit back, it will close each activity as it tries to open them. This would also prevent someone from using the app manager to re-enter your activity when you expect it to be closed.
Another idea would be read Android: Clear the back stack
my main.xml file is just dummy. I want to start different activites based on the condition. If the password is found in shared pref file, the login activity should be launched, and if password is not found, the configuration activity should be launched. it is working fine but when I press the back key from keypad, the main activity is shown (I mean the blank screen because there is nothing) How can I avoid this?
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefs = getSharedPreferences(preffilename, MODE_PRIVATE);
final String password = prefs.getString("password",null);
if(password == null)
{
Intent i = new Intent(getApplicationContext(), Configuration.class);
startActivity(i);
}
else
{
Intent i = new Intent(getApplicationContext(), Login.class);
startActivity(i);
}
}
Call finish() from your main activity after calling startActivity(), this will remove main activity from stack.
What is your expectation when you pressed the back button? You might want to put those code in onResume() so it always get called when the main activity is brought back from the stack.