2

I start studying this: Android SplashScreen and my app works perfectly with this method. Unfortunately, I've developed a custom splash screen (not a progress dialog like in the other post) and I'm not able to use the same approach. My splashscreen is a different activity that I starts calling it from the onCreate as a different thread.

Instead of this.pd = ProgressDialog.show(this, "Working..", "Downloading Data...", true, false); in the onCreate I do:

        Thread splashThread = new Thread() {
                @Override
                public void run() {
                     // start the splash screen activity
                }
        };
        splashThread.start();
 }

The splashscreeen activity correctly starts. So I call the AsyncTask as in the default method (doInBackground, onPostExecute) and I'm not able to end the activity that is running the splashscreen and come back to the main one, after all the variables are loaded in the doInBackground.

Any suggestion?

Community
  • 1
  • 1
Zappescu
  • 1,429
  • 2
  • 12
  • 25

2 Answers2

2

Well, I finally thank JPM for the suggestion to use handlers and I solved with that:

public class SplashScreen extends Activity {

        private static Handler mHandler ;
        private static Handler mainHandler ;

        protected static final int CLOSE_SPLASH = 0 ;

        /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash_screen);

        mHandler = new Handler(){
                @Override
                public void handleMessage(Message msg){
                        switch(msg.what){
                        case CLOSE_SPLASH:
                        finish();
                        break;
                        }

                }
        };
    }

    @Override
    public void onStart(){
        super.onStart();
        if(mainHandler != null){
                mainHandler.sendEmptyMessage(MainActivity.START_LOAD);
        }
    }

    @Override
    public boolean onKeyDown (int keyCode, KeyEvent event){
        if(keyCode == KeyEvent.KEYCODE_BACK){
                mainHandler.sendEmptyMessage(MainActivity.ABORT_LOAD);
        }
        return super.onKeyDown(keyCode, event) ;
    }
    public static void setMainHandler(Handler h){
        mainHandler = h ;
    }
    public static void sendMessage(Message msg){
        mHandler.sendMessage(msg);
    }
    public static void sendMessage(int w){
        mHandler.sendEmptyMessage(w);
    }
}

In the MainActivity I manage handlers back and forth:

public class MainActivity extends Activity {

        private MainActivity _this;
        private Handler mHandler;

        protected static final int FINISH_LOAD = 0 ;
        protected static final int START_LOAD = 1 ;
        protected static final int ABORT_LOAD = 2 ;

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);

                _this = this;

                mHandler = new Handler() {
                        @Override
                        public void handleMessage(Message msg) {
                                switch (msg.what) {
                                case FINISH_LOAD:
                                   SplashScreen.sendMessage(SplashScreen.CLOSE_SPLASH);
                                        break;
                                case START_LOAD:
                                        initializing();
                                        break;
                                case ABORT_LOAD:
                                        finish();
                                }

                        }
                };
                startSplash();
        }

        private void startSplash() {
                Intent intent = new Intent(this, SplashScreen.class);
                SplashScreen.setMainHandler(mHandler);
                startActivity(intent);
        }

        private void initializing() {
                new Thread() {
                        @Override
                        public void run() {    
                                long start_time = android.os.SystemClock.uptimeMillis();
                                doTheHeavyJob();
                                long duration = android.os.SystemClock.uptimeMillis() - start_time;
                                if (duration <=3000) {
                                   try {
                                       wait(3000-duration);
                       } catch (InterruptedException e) {
                          e.printStackTrace();
                    }
                        }
                        mHandler.sendEmptyMessage(FINISH_LOAD);
                  }
            }.start();
        }    
}

In this manner I can manage the doTheHeavyJob() function and finish the SplashScreen in both cases: after the job finish and at least after 3000 millis, the minimum duration of my splashscreen to be shown. I also want to tank Teskio on the anddev italian website for the most of the job done here.

Zappescu
  • 1,429
  • 2
  • 12
  • 25
1

I don't know if that is the way I would have done it since Android has some nice Handler methods that can do some of what you are looking for then you can block on the thread until your items download. Here is how I make a standard Splash screen. This Splash activity is the main activity in the Manifest, and when its done calls the next activities.

import java.io.File;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;

/**
 * Splash screen to start the app and maybe check if some things enabled
 * If not enabled popup and if user enables then continue else close app.
 */
public class Splash extends Activity {
    private static final String TAG = "Splash";

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.splash);

        // load some stuff 
        (new Handler()).postDelayed(new splashHandler(), 2000);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.d(TAG, "OnActivity result code = " + resultCode);
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == -1) {
           // class of the next activity you want to display after the Splash screen
           Class<?> className = MainApp.class;
       startActivity(new Intent(getApplication(), className ));
       Splash.this.finish();

    } else {
          Toast.makeText(Splash.this, getResources().getText(R.string.stringSplashonActivity), Toast.LENGTH_LONG).show();
          finish();
          // the program...
          return;
        }
    }

    /**
     * Runnable class to check if user is logged in already
     * and then start the correct activity.
     *
     */
    class splashHandler implements Runnable{

        @Override
        public void run() {

            .....Do something.....
        }
    }
}

Then don't forget to define the activity between the applicaton tags in the Android Manifest.xml (for those new to Android)

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

Hope this helps....

JPM
  • 9,077
  • 13
  • 78
  • 137
  • 1
    The idea of handlers is interesting and maybe I should go deep on it. Would you tell me more? – Zappescu Sep 06 '11 at 15:58
  • as per android's manual : A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue. – JPM Sep 06 '11 at 16:18
  • There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own. http://developer.android.com/reference/android/os/Handler.html – JPM Sep 06 '11 at 16:19