Run App Twice To Work - java

I'm making an android app that test if certain security features on your phone are enabled. For example, if you have password log in enabled or if your data is encrypted on your phone.
For some reason, the app has to be run twice to test and see if these security features are enabled on the phone or not, and this is the problem I'm trying to solve. I'd like it to test and see if the security features are enabled when the app is created and the first time the app is run, not the second time it is run.
I test if these features are enabled in the onStart() function in my MainActivity file. I included the functions code below:
#Override
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#SuppressLint("NewApi")
public void onStart()
{
super.onStart();
//determine if phone uses lock pattern
//It returns 1 if pattern lock enabled and 0 if pin/password password enabled
ContentResolver cr = getBaseContext().getContentResolver();
lockPatternEnable = Settings.Secure.getInt(cr, Settings.Secure.LOCK_PATTERN_ENABLED, 0);//Settings.System
//returns 1 if pin/password protected. 0 if not
KeyguardManager keyguardManager = (KeyguardManager) getBaseContext().getSystemService(Context.KEYGUARD_SERVICE);
if( keyguardManager.isKeyguardSecure())
{
//it is pin or password protected
pinPasswordEnable=1;
}
else
{
//it is not pin or password protected
pinPasswordEnable=0;
}//http://stackoverflow.com/questions/6588969/device-password-in-android-is-existing-or-not/18716253#18716253
//determine if adb is enabled. works
adb=Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0);
//determine if bluetooth is enabled.works
bluetooth=Settings.Global.getInt(cr, Settings.Global.BLUETOOTH_ON, 0);
//Settings.System BLUETOOTH_DISCOVERABILITY
//determine if wifi is enabled. works
WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled())
{
//wifi is enabled
wifiInt=1;
}
else
wifiInt=0;
//determine if data is encrypted
getDeviceEncryptionencryption();
//determine if gps enabled
}//end of onStart() function
If any more code needs to be posted to answer this question, just let me know, and thanks for your help. Maybe the issue has something to do with the super.onStart();
Does anyone think that a splash loading screen might help solve the issue?

Here is good explanation how app lifecycle flows.
onStart() can be executed many times. You can keep counter how many times you had entered this method and act differently on each time:
static int counter=0;
public void onStart()
{
counter++;
Log.i("MyApp", "onStart() run "+counter);
switch (counter){
case 1: break; // first run
case 2: break; // second run
default: break;// other runs
}
}
To be more clear about life cycle and why your onStart() method is called twice I suggest to have counter and Log.i() in each important state of the cycle - at least in onCreate() and onRestart().
Keep in mind that app stays in memory when you click Home button. When you click app icon again it restarts already running app (calls onRestart() and then onStart() methods and no onCreate() ). When you really kill you app for real then sequence would be onCreate and onStart without onRestart. Having logcat records really helps you to understand app lifecycle flow and why your onStart() is called twice or more times.

Using a static variable to check how many times onStart has been called isn't a good idea, because an app can be killed if Android needs more memory for other apps while still allowing the user to navigate back to the app. That would be the path through the red box in the picture below (http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle):
A static variable would be 0 again after that and your app would run the security check again.
What you need to do is use an instance variable that you persist in onSaveInstanceState and restore in onCreate. In case the app is killed, onSaveInstanceState is called and you save your Activity's state. If the user goes back to the app, onCreate is called and the state would be restored. This works for all other cases too when the app isn't killed but the user just navigates away from the app and later re-opens it. Here's a simple example of an app saving and restoring:
public class MainActivity extends Activity {
private boolean mSecurityCheckDone;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mSecurityCheckDone = savedInstanceState.getBoolean("mSecurityCheckDone");
}
}
#Override
protected void onStart() {
super.onStart();
if (! mSecurityCheckDone) {
// run the security check
mSecurityCheckDone = true;
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("mSecurityCheckDone", mSecurityCheckDone);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
mSecurityCheckDone = savedInstanceState.getBoolean("mSecurityCheckDone");
}
}
}

how about using flag ?
singleTop
If an instance of the activity already exists at the top of the target
task, the system routes the intent to that instance through a call to
its onNewIntent() method, rather than creating a new instance of the
activity.
singleTask
The system creates the activity at the root of a new task and routes
the intent to it. However, if an instance of the activity already
exists, the system routes the intent to existing instance through a
call to its onNewIntent() method, rather than creating a new one.
singleInstance
Same as "singleTask", except that the system doesn't launch any other
activities into the task holding the instance. The activity is always
the single and only member of its task.
http://developer.android.com/guide/topics/manifest/activity-element.html

I'm not sure why you are using onStart(), if you want it to be run the first time the activity is created I would probably use onCreate() instead.
There is no API in Android that will tell you if the app has been run at least once so you will need to use some type of persistent storage for that, e.g. SharedPreferences could be used to persist a flag that would be set the first time your app is run and thereafter you can check it as shown here.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences settings = getSharedPreferences("Prefs", 0);
if (settings.getBoolean("first_time", true)) {
//the app is being launched for first time, do something
Log.d("Comments", "First time");
// first time task
// record the fact that the app has been started at least once
settings.edit().putBoolean("first_time", false).commit();
}
}

Related

onCreate in an Activity ignores all the call stack sequence

MainActivity has an attribute android:launchMode="singleInstance" in AndroidManifest.xml
Here's the onCreate method from MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "onCreate() from MainActivity");
session = new TempSession(this);
// check if logged in. If not, take the user back to login activity.
session.checkLogin(); // <---- HERE
Toast.makeText(this, "logged in as " + session.getUsername(), Toast.LENGTH_SHORT).show();
// Prevents screen from turning off when in this Activity.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
....
and the TempSession, it checks if user is logged in, and if not, it will take the user to the LoginActivity.
This is the checkLogin() method
public void checkLogin(){
// Check login status
if(!this.isLoggedIn() || getUsername() == null) {
// user is not logged in redirect him to Login Activity
Intent i = new Intent(context, LoginActivity.class);
// Closing all the Activities
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
// Add new Flag to start new Activity
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
// Staring Login Activity
context.startActivity(i);
}
}
From my understanding, where I marked <---- HERE from MainActivity, when it calls checkLogin(), shouldn't it finish all task before it proceeds?
Currently, my app would open up LoginActivity, but still proceeds to the next instructions (e.g. makes a Toast saying "logged in as null", and keeps going on in background) and calls onPause() -> onStop() .
Is there any way to stop the MainActivity from keep going at that point?
This situation causes pressing back from LoginActivity bypasses to MainActivity.
Let me know if you need more information.
Thank you in advance.
Is there any way to stop the MainActivity from keep going at that point?
Yes. Have checkLogin() return some value that indicates MainActivity#onCreate(...) should return instead of proceeding.
Calling startActivity(...) does not start an activity. Think of it as asking the Android framework to start an activity. It places this job at the end of the UI thread's work queue. That means that before it starts the new activity, it will finish any other jobs that are already in the work queue, including the rest of the current method and possibly other lifecycle methods of the current activity.
The reason that your toast still shows up is because merely starting a new activity does not destroy your old activity. It's merely pushed to the backstack. Of course you can change this using the android:launchMode attribute in your manifest. A simple strategy in your cause might be to simply return true from your checkLogin() method when the user is logged in and change your onCreate as follows:
if( session.checkLogin() ) {
Toast.makeText(this, "logged in as " + session.getUsername(), Toast.LENGTH_SHORT).show();
// Prevents screen from turning off when in this Activity.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
....
}

Android working in background

this is my first question I got stucked in an app development..
I have developed an app. This app has a registration activity in the first stage, here the user's name, password and mobile number is collected and saved in the server. after that, the user's registration process is completed.
once this is done, the app will work to give daily horoscope predictions. This means the app will have to notify, or predict, daily. So after once the registrtion process is over the app should continue to run in the background. Also, when the user re-opens the app, it should not display the registration page, but the prediction page. I would also like a button that closes the app, but keeps it running in background.
How would I go about doing this?
Here is the code to my mainActivity,
public class MainActivity extends Activity
{
Button btn1,btn2;
LoginDataBaseAdapter loginDataBaseAdapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loginDataBaseAdapter=new LoginDataBaseAdapter(this);
loginDataBaseAdapter=loginDataBaseAdapter.open();
btn2 = (Button) findViewById (R.id.button2);
btn1 = (Button) findViewById (R.id.button1);
if(loginDataBaseAdapter.getUsercount() >= 50)
{
btn2.setVisibility(View.INVISIBLE);
}
else
{
btn2.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
Intent i = new Intent(MainActivity.this,SignUpActivity.class);
startActivity(i);
}
});
}
btn1.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
Intent inte = new Intent(MainActivity.this,SignInActivity.class);
startActivity(inte);
}
});
}
#Override
protected void onDestroy()
{
super.onDestroy();
// Close The Database
loginDataBaseAdapter.close();
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
finish();
}
}
1.Use Shared preference to set a flag once user has done a successful login. NEVER STORE USERNAME OR PASSWORD.
2.Create a Service which will run in Background for getting horoscope details.
3.Next time when user opens app, check the flag value from the Shared Preferences and display appropriate activity
Create a Service class which runs in the background. Access the horoscope details in the service class in a daily manner, which is up to your requirements. Don't forget to register your service in your Activity.
Also once the registration is successful save username and password in Sharedpreferences and each time application starts you can check if the data is available or not and skip the login page. If it's online you can further validate the username and password with the server.
Since you are writing a Service class you can close the application by clicking a button or something. But once you login makesure you finish() the login activity and start the prediction activity.
You will have to inherit from Thread Object. This will allow You to overwrite the run method where You can, for example, run an infinite loop depending on some passed arguments to the inherited thread class.
NOT UI threads ( and this is going to become one, as i understood) must not create and/or modify any ui elements. Therefore You must also create an interface, which will be implemented by the inherited thread class. You also will have to pass the thread's callback object as listener to Your thread class in order to invoke a method call in it, where itself You then can marshall thread execution back to ui thread. Basically this means, the thread runs in background and if some conditions occurr, it announces the main thread like an event, where You for Yourself can Do whatever You like.
But read You must, first: ( especially, how variable access among n threads should be ensured ):
Here for example:
Threading Example in Android

How to recover data after closing another application

I'm developing an Android application and I need to open pdf files and return to same activity when back button is pressed.
Problem
I correctly open pdf file (from ActivityOne) using an intent and starting activity, but when I press back button, all data that I had in the ActivityOne (and previous activities) have been lost.
Here is my code of starting activity for showing pdf:
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+"/"+ myApplication.getUsuarioActual().getFacturaActual().getPdf());
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(file));
intent.setType("application/pdf");
startActivity(intent);
What do I have to do to solve that? Same occurs when I open another application and close it: when return to my app, it shows an error saying that all data is null.
EDIT
After reading that question, as #TheCharliemops recommended me, I know it is what I need, but I have another question related to that.
I have a class myApplicationthat extends Application to maintain global application state where I save all data that I read/write in different Activities.
My question is if I have to save all data I have in myApplication in every activity using onSaveInstanceState or there is some easiest manner to do it.
Firts of all, welcome to SO!!
Here, #reto-meier explains how to save the activity state in Android. I think that could fix your problem. I put his code here for future people with similar problem.
He says that you must override onSaveInstanceState(Bundle savedInstanceState) and onRestoreInstanceState(Bundle savedInstanceState) as following code shows:
Reto Meier said:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("MyBoolean", true);
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "Welcome back to Android");
// etc.
}
The Bundle is essentially a way of storing a NVP ("Name-Value Pair") map, and it will get passed in to onCreate and also onRestoreInstanceState where you'd extract the values like this:
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}
I hope this helps you.
Regards!

Android Trying to display a welcome fragment when app starts, but not after

I've been looking for a way to have the blank detail side of my fragment layout host a welcome screen (or something - login perhaps) on start up. Afterwards, when a user presses one of the left side menu items, I'd like to eliminate the fragment for the remainder of the program run. I don't want to add it to the backstack, as that messes up my configuration changes. I've considered using shared prefs to host a boolean about whether the fragment has been displayed. The only concern with this method is where to safely reset the boolean value for the next run of the app. I'm of the impression that there's no gaurantee that the onStop, onDetach etc. will definitely get called upon closing of the app, so if the app got closed in the wrong state, it would be rendered useless ( the first fragment wouldn't display - crash )
Anyone have any ideas on how I could implement a filler for the right side of the app upon startup?
I've been trying to add something to the onCreate of my main activity thus far with no success.
Thanks in advance.
Ken
If your fragment can be part of its own Activity, you can use the android:noHistory="true" attribute to keep the Activity off of the backstack. If your user tries to navigate backwards, it'll hit the bottom of the backstack twice before exiting your application.
If you can't split your fragment into its own activity, noHistory may not work -- I can't say as I haven't tried it myself.
I was able to come up with a solution to creating a welcome or login screen which will display both fragments and activities from the main activity. Seems to be working fine as tested.
private boolean welcomeShown;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_list);
if (findViewById(R.id.item_detail_container) != null) {
mTwoPane = true;
((MainFragment) getSupportFragmentManager().findFragmentById(
R.id.item_list)).setActivateOnItemClick(true);
}
if (savedInstanceState != null){
welcomeShown = savedInstanceState.getBoolean("displayed");
}
if(!welcomeShown){
if (mTwoPane){
WelcomeFragment welcomeFragment = new WelcomeFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.item_detail_container, welcomeFragment)
.commit();
}
else{
Intent welcomeIntent = new Intent(this, WelcomeActivity.class);
startActivity(welcomeIntent);
welcomeShown = true;
}
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("displayed", true);
}

too little fps in android emulator / wrong error message at start

I have an app that, for now, runs a loop where it updates the game state ~25 times/s and tries so draw it 40 times/s. the update works fine, it shows just a bit more than 25. but on the emulator, the game draws under 20 fps, no matter how much there is to draw. even if I only paint the background green it has low fps.
I sent the app to someone who tested it on his phone, there it runs correctly with 40fps drawing speed and 25fps updating speed.
I tested it on the emulator with different API levels, the drawing fps is always way too slow. I use eclipse. do I have to make any special setting for the emulator or so?
There was another problem too, the guy who tested it on his phone got an error message when starting the app, it said the app wouldn't react and the option for wait and shutdown. after waiting 5-10 seconds the content view would be displayed. I create the content view and assign the variable in the onCreate method, without starting the loop. In the onStart method I set the contentView and start the loop, but it runs an empty while loop until I set a boolean in the onResume method. any ideas?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view= new MainMenu(this); }
protected void onStart() {
super.onStart();
this.setContentView(view);
view.startGameView();
}
public void startGameView() {
loop=new GameLoop(this);
loop.start();
}
protected void onResume() {
super.onResume();
view.resumeGameView();
}
public void resumeGameView() {
loop.b_pause=false;//loop starts to execute code for drawing/updating
}
the code for the activity change:
public void changeActivity(Class c, String str)
{
Intent i=new Intent(this, c);
startActivity(i);
}

Categories