Search code examples
javaandroidandroid-intentsplash-screen

Display splash screen only when the app is launched and not every time when the activity containing splash screen code, is called


Before I get into describing by problem I'd like to point out I am aware of the other threads asking this question, however none for me have been able to solve my issue.

The difference between previously asked questions and my question is that I've splash screen code in the main activity and NOT in another activity, so i have no layout XML file for this.

So, the problem is, I want to display splash screen only when the app is started, and this is done perfectly by the following code but when the main activity (which contains splash screen code) is called by another activity using Intent, the splash screen is displayed again.

So, first I tried to use flag variable, initiating 0 when activity is created and incrementing it by one when splash screen is displayed once. but I figured out that it will not work because it will always 0 when activity is created.

So, now i'm trying to pass a string from the other activity and trying to prevent splash screen again as shown in following code:

public class Registration extends ActionBarActivity {

public final static String EXTRA_MESSAGE = "com.kaushal.myapplication.MESSAGE";

DatabaseHelper myDb;
EditText username,password;
private ImageView splashImageView;
boolean splashloading = false;
int flag=0;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_registration);


    String message = null;
    Intent intent0 = getIntent();
    message = intent0.getStringExtra(Registration.EXTRA_MESSAGE);//string from another activity.

    if(!message.equals("signup has called me")) { //splash screen code in `if`
        splashImageView = new ImageView(this);
        //splashImageView.setBackgroundColor();
        splashImageView.setImageResource(R.drawable.sexy);
        setContentView(splashImageView);
        splashloading = false;
        Handler h = new Handler();

        h.postDelayed(new Runnable() {
            public void run() {
                splashloading = false;
                setContentView(R.layout.activity_registration);
                username = (EditText) findViewById(R.id.username);
                password = (EditText) findViewById(R.id.password);
            }
        }, 3000);
        flag++;
    }

    if(flag==0){
        username = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
    }

    myDb = new DatabaseHelper(this);




}
}

Here Registration is name of my main activity which is launched when the app will be started.

Code of method of another activity named sign Up which passes a string:

 public void backToRegistration(View view){
    Intent intent0 = new Intent(this,Registration.class);
    intent0.putExtra(EXTRA_MESSAGE, "signup has called me");
    startActivity(intent0);
}

What is the problem with this method? App is crashes immediately after launching.


Solution

  • So there are a number of issues with using a String in an Intent as a flag like this. Strings aren't really setup for it. The overhead is a good bit more than that of a simple primitive boolean flag.

    To do this the way you are currently trying

    Change your onCreate code to this

    super.onCreate(savedInstanceState);
    
    Intent intent0 = getIntent();
    boolean showSplash = getIntent().getBooleanExtra(Registration.FLAG_KEY), true);
    
    handleSplashScreen(showSplash);
    

    And add this method, which we will use in a somewhat recursive way to handle showing the splash screen.

    private void handleSplashScreen(boolean showSplash){
        if(showSplash) { //splash screen code in `if`
            splashImageView = new ImageView(this);
            //splashImageView.setBackgroundColor();
            splashImageView.setImageResource(R.drawable.sexy);
            setContentView(splashImageView);
            splashloading = false;
            Handler h = new Handler();
    
            h.postDelayed(new Runnable() {
               public void run() {
                   handleSplashScreen(false);
               }
            }, 3000);
        }
        else{
            splashloading = false;
            setContentView(R.layout.activity_registration);
            username = (EditText) findViewById(R.id.username);
            password = (EditText) findViewById(R.id.password);
        }
    }
    

    Then, when you are opening this activity from another activity do

    public void backToRegistration(View view){
        Intent intent0 = new Intent(this,Registration.class);
        intent0.putExtra(FLAG_KEY, false);
        startActivity(intent0);
    }
    

    Where FLAG_KEY is private static FLAG_KEY = com.kaushal.myapplication.FLAG; and replaces the EXTRA_MESSAGE string.

    How I would recommend doing it

    Now, in saying that, this isn't at all how I would recommend doing this. You should simply have a SplashScreenActivity that is called on launch and redirects to your Registration MainActivity. This get's rid of the convolution of having an Activity with two different layouts, flags, etc.

    public class SplashScreenActivity extends Activity{
    
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_splash);
    
            new Handler().postDelayed(new Runnable(){
                @Override
                public void run(){
                    startActivity(new Intent(SplashScreenActivity.this, MainActivity.class);
                    SplashScreenActivity.this.finish();
                }
            }, 3000);
    
        }
    }
    

    Where R.layout.activity_splash looks like this

    <?xml version="1.0" encoding="utf-8"?>
    <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="R.drawable.sexy"
        android:scaleType="centerInside" />
    

    Then you could have MainActivity like this

    public class MainActivity extends ActionBarActivity{
    
        // Variables here
        ...
    
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_registration);
    
            username = (EditText) findViewById(R.id.username);
            password = (EditText) findViewById(R.id.password);
        }
    
        // Other methods
        ...
    }
    

    Lastly, simply go in the manifest and update it so that the newly created SplashScreenActivity is shown on launch and make sure that the MainActivity is still declared appropriately.

    <activity
        android:name=".SplashScreenActivity"
        android:label="@string/app_name">
    
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    
    <activity
        android:name=".MainActivity"/>
    

    No more flags, no more logic, no more issues. It loads the splash screen on launch and that is it. The Activity finishes after it passes the intent so it is no longer on the stack. All is well. The reason that the other questions handle things like this is it is the recommended way of going about having a splash screen.