Android: Logout system and the android lifecycle
on the weekend I started to build my first android app. As I need to ask
the user of my app for user credentials [which are used for further
webservice usage] I want to simulate a "login system". On the start of my
app the user should be told to enter his credentials. When the user is
inactive for too long I want to dismiss the entered credentials and to
"log out" the user. While coding and afterwards while testing I realized
that the way I thought I could go doesn't work. After reading the docu and
several SO-questions again and again I question myself more and more if I
have understand the app / activity life cycle and its possibilites fully.
So I wanted to ask for help in understand the life cycle and its linked
influences on my app. So yes this might be several questions in one :/
For the moment my app consists of the following activities:
a search activity (which is opened once the app is started)
a settings acitivy (which can be accessed from the search dialog and has a
link back to the search dialog)
After the user has entered an ID in the search dialog I want to open an
activity regarding to the search result (NYI).
When starting to implement the user auth, my idea was the following:
Everytime onResume() of an activity is called I need to check a) if user
credentials are already stored and b) if the last action of the user is
less then X minutes ago. If one these fails I want to show a "log in
panel" where the user can enter his credentials, which are then stored in
the SharedPreferences. For that I did the following:
I first build an parent activity which has the check and a reference for
the SharedPreferences in it
public class AppFragmentActivity extends FragmentActivity {
protected SharedPreferences sharedPref;
protected SharedPreferences.Editor editor;
protected String WebServiceUsername;
protected String WebServicePassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_appfragmentactivity);
}
@Override
protected void onResume () {
super.onResume();
// Check if user is "logged in".
// Meaning: Are there given user credentials and are they valid of was
the user inactive for too long?
// We only do this "onResume" because this callback is the only one,
which is called everytime an user
// starts/restarts/resumes an application
checkForUserCredentials();
// Set new "last action" now "now"
setLastAction(new Date().getTime());
}
@Override
protected void onStart () {
// Fill content
super.onStart();
// Set global sharedPreferences
sharedPref =
this.getSharedPreferences(getString(R.string.FILE_settings_file),
Context.MODE_PRIVATE);
}
/*
* Checks if user credentials are valid meaning if they are set and not
too old
*/
private void checkForUserCredentials() {
long TimeLastAction =
sharedPref.getLong(getString(R.string.SETTINGS_USER_LAST_ACTION), 0);
long TimeNow = new Date().getTime();
// Ask for User credentials when last action is too long ago
if(TimeLastAction < (TimeNow - 1800)) {
// Inactive for too long
// Set back credentials
setUsernameAndPassword("", "");
}
else
{
WebServiceUsername =
sharedPref.getString(getString(R.string.SETTINGS_USER_USERNAME),
"");
WebServicePassword =
sharedPref.getString(getString(R.string.SETTINGS_USER_PASSWORD),
"");
}
}
/*
* Saves the given last action in the sharedPreferences
* @param long LastAction - Time of the last action
*/
private void setLastAction(long LastAction) {
editor = sharedPref.edit();
editor.putLong(getString(R.string.SETTINGS_USER_LAST_ACTION),
LastAction);
editor.commit();
}
/*
* Saves the given username and userpassword sharedPreferences
* @param String username
* @param String password
*/
private void setUsernameAndPassword(String username, String password) {
editor = sharedPref.edit();
editor.putString(getString(R.string.SETTINGS_USER_USERNAME), username);
editor.putString(getString(R.string.SETTINGS_USER_PASSWORD), password);
editor.commit();
WebServiceUsername = username;
WebServicePassword = password;
}
/*
* Method called when pressing the OK-Button
*/
public void ClickBtnOK(View view) {
// Save User-Creentials
EditText dfsUsername = (EditText) findViewById(R.id.dfsUsername);
String lvsUsername = dfsUsername.getText().toString();
EditText dfsPassword = (EditText) findViewById(R.id.dfsPassword);
String lvsPassword = dfsPassword.getText().toString();
if(lvsUsername.equals("") || lvsPassword.equals("")) {
TextView txtError = (TextView) findViewById(R.id.txtError);
txtError.setText(getString(R.string.ERR_Name_or_Password_empty));
}
else
{
// Save credentials
setUsernameAndPassword(lvsUsername, lvsPassword);
setLastAction(new Date().getTime());
// open Searchactivity
Intent intent = new Intent(this, SearchActivity.class);
startActivity(intent);
}
}
The "log in mask" is setContentView(R.layout.activity_appfragmentactivity);.
The two other activites I created are then extending this parent class.
This is one of it:
public class SearchActivity extends AppFragmentActivity {
SearchFragment searchfragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
}
@Override
protected void onResume() {
super.onResume();
if(WebServiceUsername.equals("") && WebServicePassword.equals("")) {
// Username not set. Re"login".
Intent intent = new Intent(this, AppFragmentActivity.class);
startActivity(intent);
}
}
@Override
protected void onStart() {
super.onStart();
}
// ...
}
As far as I understand the lifecycle now this should work as the
following: When my app starts (the SearchActivity is set for LAUNCH) the
app should step into the onResume() of my parent class. There it sees that
the credentials are not yet stored and opens the layout of the
AppFragmentActivity which is the login. When entered, the user is
redirected to the SearchActivity which now sees "ok credentials are there,
lets move forward". But this doesnt't happen as the login is not shown up.
So I think my onResume() might be wrong. Perhaps my full idea is bad? Up
to here I thought I also understand the life cycle, but obviosly I don't?
I then had a look around on SO for similar problems. One thing I saw here
was a comment to an user which wanted to build a similar "logout"
mechanism as mine, that he has to implement this in every activity. I
thought about that and ask myself "Why do I have to override the
onResume() in every of my activites, when they are all from the same
parent? When theres no onResume() in the child, the one of the parent
should be called". The user in the SO-question was advised to use services
as background threads to count down a timer in there for the logout. I
then read the services article in the docu and then fully got disoriented:
There are two types of services: Started and bounded ones. A started
service is once started by an activity and then runs in the background
until hell freezes when it doesn't get stoped. So it's fully independed of
any app, but the programmer has to / should stop it when it's not longer
needed. A bounded services is bounded to one or many app components and
stops when all bounded components end. I thought this might be a good
alternative for me, but when I thought further I ask myself how: If one of
my starts it (let's say the login dialog) and then is closed the service
is stoped and the other activites always start there own ones which can't
be the sense of it. So this service must be bounded not to any component
but to my app. But whats the life cycle of an android app? How can I keep
information "global" inside my app. I know I can switch data between
actitivites using 'Intents'.
This more and more "foggy cloud" lead to ask myself: "Shall I use only one
activity and try to switch in/out everything using fragments?"
So my questions are (I think that's all of them, but I'm not sure anymore):
Does my idea of writing an parent class which does the checks for all
extended childs ok or bad AND does it work as I understood it?
Do I have to override every onResume() in the childs just to call the
parent one for the checks?
Can you give me a tip why my "login systems" doesn't work?
What's the life cycle of an android app and how can I interact with it?
Shall I only use one activity and switch in/out everything using fragments
or is it a good way to have several activities and some of them use
fragments (to reuse often used parts)?
Thanks in advise
Monday, August 12, 2013
Android: Logout system and the android lifecycle
Posted on 7:06 AM by Unknown
Subscribe to:
Post Comments (Atom)
0 comments:
Post a Comment