質問

I'm trying to create a Splash page that has a banner and cancel button, by the following rules:

  1. if nothing is pressed, go to main activity after 5 seconds.
  2. if cancel button is pressed, go to main activity immediately.
  3. if banner is pressed, go to other activity.

My code:

public class BannerSplashActivity extends Activity {
    private static final int TIMEOUT = 5000;

    private View mButtonCancel;
    private SplashHolderTask mSplashHolderTask;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.form_banner_splash);

        // Excecute task
        mSplashHolderTask = new SplashHolderTask();
        mSplashHolderTask.execute();

        // find references
        mButtonCancel = findViewById(R.id.buttonCancel);
        mButtonCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mSplashHolderTask.cancel(true);
                goToMainActivity();
            }
        });
    }

    private void goToMainActivity(){
        startActivity(new Intent(this, MainActivity.class));
        finish();
    }


    /**
     * This task holds the bannerSplash
     */
    private class SplashHolderTask extends AsyncTask<Void, Void, Void>{

        @Override
        protected Void doInBackground(Void... params) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    goToMainActivity();
                }
            }, TIMEOUT);

            return null;
        }
    }
}

When I run my code I'm getting:

Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

How can I implement that logic?

役に立ちましたか?

解決 2

The Exception because you creating a Handler inside another thread.. By changing your code like this you can get what you want exactly..

public class BannerSplashActivity extends Activity {
private static final int TIMEOUT = 5000;

private View mButtonCancel;

private Handler handler = new Handler();
private Runnable runnable;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.form_banner_splash);
    runnable = new Runnable() {

        @Override
        public void run() {
            goToMainActivity();
        }
    };
    handler.postDelayed(runnable, TIMEOUT);

    // find references
    mButtonCancel = findViewById(R.id.buttonCancel);
    mButtonCancel.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            handler.removeCallbacks(runnable);
            goToMainActivity();
        }
    });
}

private void goToMainActivity() {
    startActivity(new Intent(this, MainActivity.class));
    finish();
}
}

I am not using any Threads or AsynchTasks.

他のヒント

You can't create a Thread in an AsyncTask. You can simply use a simple delayed handler that you will cancel in case of a click on the banner, the cancel button or if the user leave the app :

public class BannerSplashActivity extends Activity {
    private static final int TIMEOUT = 5000;

    private Handler cancelHandler;

    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.form_banner_splash);

      cancelHandler = new Handler(){
        @Override
        public void dispatchMessage(Message msg) {
             goToMainActivity();
        }
      };
      cancelHandler.sendEmptyMessageDelayed(0, TIMEOUT);

      // find references
      View mButtonCancel = findViewById(R.id.buttonCancel);
      View mBannerView = findViewById(R.id.bannerView);

      mButtonCancel.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              cancelHandler.removeMessages(0);
              goToMainActivity();
          }
      });

      mBannerView.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              cancelHandler.removeMessages(0);
              //go to the activity you want
          }
      });
 }

  private void goToMainActivity(){
      startActivity(new Intent(this, MainActivity.class));
      finish();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    if(cancelHandler != null){
      cancelHandler.removeMessages(0);
    }
  }
}    

With Thread.sleep(x) (timer), running in another thread is enough:

public class SplashScreen extends Activity {
    private static final int splash_duration = 5000;
    private boolean mPaused = false;
    private boolean mActive = true;
    private Thread splashTimer = null;

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

            Button cancel = (Button)findViewById(R.id.cancel);
            View bannerWidget = (Banner)findViewById(R.id.someBanner);



            cancel.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                //cancel button is pressed, go to main activity                     immediately.
                Intent intent = new Intent("com.foo.MainActivity");
                startActivity(intent);

                }
            });

            bannerWidget.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                //banner is pressed, go to other activity.
                Intent intent = new Intent("com.foo.OtherActivity");
                startActivity(intent);

                }
            });

            splashTimer = new Thread(new Runnable() {
                public void run() {
                    long current_time = 0;
                    try {

                        while (mActive && current_time < splash_duration) {
                            Thread.sleep(200);
                            if (!mPaused)
                                current_time += 200;
                        }
                        //nothing is pressed, go to main activity after 5 seconds.
                        Intent intent = new Intent("com.foo.MainActivity");
                        startActivity(intent);
                    } catch (Exception ex) {
                        Log.e("Splash", ex.toString());
                    } finally {
                        finish();
                    }
                }
            });
            splashTimer.setDaemon(true);
            splashTimer.start();
        }

        @Override
        protected void onPause() {
            super.onPause();
            mPaused = true;
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (splashTimer != null) {
                Thread dummy = splashTimer;
                splashTimer = null;
                dummy.interrupt();
            }

        }

        @Override
        protected void onResume() {
            super.onResume();
            mPaused = false;
        }

        @Override
        public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
            super.onKeyDown(keyCode, keyEvent);
            mActive = false;
            return true;
        }
}

A Handler and a Runnable is enough for you.

Handler mHandler;
Runnable mRunnable;
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.form_banner_splash);

    mHandler = new Handler();
    mRunnable = new Runnable() {
        @Override
        public void run() {
            goToMainActivity();
        }
    };

    mHandler.postDelayed(mRunnable, TIMEOUT);

    mButtonCancel = findViewById(R.id.buttonCancel);
    mButtonCancel.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            handler.removeCallBacks(mRunnable);
            goToMainActivity();
        }
    });

    private void goToMainActivity(){
        startActivity(new Intent(this, MainActivity.class));
        finish();
    }
}

Already answered but some one looking for onBackPressed() then use simple full activity...

public class ActivityLaunch extends Activity {

    private static int SPLASH_TIME_OUT = 3000;
    Handler mHandler;
    Runnable runnable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activitylaunch);

        mHandler = new Handler();
        runnable = new Runnable() {

            @Override
            public void run() {
                Intent i = new Intent(ActivityLaunch.this, ActivityHome.class);
                startActivity(i);
                finish();
            }
        };
        mHandler.postDelayed(runnable, SPLASH_TIME_OUT);
    }

    @Override
    public void onBackPressed() {
        mHandler.removeCallbacks(runnable);
        finish();
    }
}

Vote Up .. if you get helped..

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top