I have designed a splash screen with a button. The Java code is as below. The layout of the splash contains some texts with animation and button named skipped splash screen. When the user presses the button, the splash screen has to stop immediately and open the next activity. But when I open the splash screen and press skip button, the next activity opens but after the duration for which splash screen has to run gets over, again the activity opens. How to stop the splash screen when a user presses the skip button?
public class Qz1 extends Activity {
TextView a;
TextView b;
TextView c;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qz1);
a =(TextView)findViewById(R.id.roundOnea22);
a.startAnimation(AnimationUtils.loadAnimation(Qz1.this, R.anim.anim_slide_in_left));
b =(TextView)findViewById(R.id.roundOneb);
b.startAnimation(AnimationUtils.loadAnimation(Qz1.this, R.anim.anim_slide_in_right));
c =(TextView)findViewById(R.id.roundme);
c.startAnimation(AnimationUtils.loadAnimation(Qz1.this, R.anim.anim_slide_in_left));
Thread thread = new Thread(){
#Override
public void run() {
// TODO Auto-generated method stub
try{
sleep(3200);
startActivity(new Intent(getApplicationContext(), Qone.class));
} catch (InterruptedException e){
e.printStackTrace();
}
}
};
thread.start();
}
public void round1(View v){
Intent i = new Intent(Qz1.this, Qone.class);
startActivity(i);
}
}
Let's suppose you want to keep your first activity in the background, but you do not want the thread to re-open the second activity as soon as it has finished sleeping.
In order to achieve that, you can make your "thread" a global variable of a custom Thread class. You can define this as an inner class of your activity:
MyThread thread;
and the class definition:
private class MyThread extends Thread
{
public boolean bRun = true;
#Override
public void run()
{
try
{
sleep(3200);
if (bRun)
{
startActivity(new Intent(getApplicationContext(), Activity2.class));
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
In onCreate(), you write
thread = new MyThread();
thread.start();
Then you can change your "onClick" method like this:
public void round1(View v){
if (thread != null && thread.isAlive())
{
thread.bRun = false;
}
Intent i = new Intent(Qz1.this, Qone.class);
startActivity(i);
}
This will keep the thread from starting the second activity, if it has been started by clicking the button.
Shouldn't be using sleep(2000)
use an animationlistener (http://developer.android.com/reference/android/view/animation/Animation.AnimationListener.html)
when onAnimationEnd is triggered call startActivity.
I think best practice here would be to use a Handler.
You can do it like this:
public class Test extends AppCompatActivity{
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Settign the splashscreen with the button i suppose
setContentView(R.id.splashcreen);
}
#Override
protected void onStart() {
super.onStart();
handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
startNextActivity();
}
}, 2000);
}
public void startNextActivity(){
startActivity(new Intent(getApplicationContext(), Qone.class));
}
public void skipSplashScreen(){
if (handler != null)
handler.removeCallbacksAndMessages(null);
startNextActivity();
}
#Override
protected void onStop() {
super.onStop();
// clear handler on stop
if (handler != null)
handler.removeCallbacksAndMessages(null);
}
}
CAll skipSplashScreen() when user press the button and the handler will stop so the timer stops and you go to next activity manually by calling method startNextActivity().
It's best practice to use Async Tasks for wait/sleep scenarios, such as for splash screens, but requirements can differ.
Anyway this is my way to call a splash screen:
Create the AsyncTask first.
private class SplashTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
finish();
Intent intent = new Intent(SplashActivity.this,
MainActivity.class);
startActivity(intent);
}
}
}
Then call this where ever you want: on button click, on start, or on create:
new SplashTask().execute();
try this in the splash activity
Button button = (Button)findViewById(R.id.buttonLayout);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(this,TargetActivity.class));
finish();
}
});
Related
I've seen some of the answers to similar questions on here but they aren't working for me.
What I want to do is start a Thread and run some code in it, but before I start the thread, I want to display a loading dialog, and as soon as the thread is finished running, close the loading dialog.
So something like this:
LoadingDialog dialog = new LoadingDialog(MainActivity.this);
class MyThread {
...
void send() {
dialog.displayDialog();
// DO THINGS HERE
new Thread((Runnable) () -> {
try{
...
} catch (...) {
}
}).start();
// Close the dialog with dialog.closeDialog();
}
}
(displayDialog() and closeDialog() are just methods I created in my LoadingDialog class to start and dismiss the dialogs)
I'm not sure exactly how to do this, I've seen some uses of handler on this site but they're all different and not working for me so I'm a little stuck.
Thanks
Solution
public class MainActivity extends AppCompatActivity {
LoadingDialog dialog;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dialog = new LoadingDialog(MainActivity.this);
MyThread myThread = new MyThread(MainActivity.this);
myThread.start();
}
static class MyThread extends Thread {
private WeakReference<MainActivity> activityRef;
public MyThread(MainActivity activity) {
activityRef = new WeakReference<>(activity);
}
#Override
public void run() {
send();
}
void send() {
// Display dialog
if (getActivity() != null) {
getActivity().dialog.displayDialog();
}
// DO THINGS HERE
// TODO: Write your code that execute in a background here
// Close dialog
if (getActivity() != null) {
getActivity().dialog.closeDialog();
}
}
private MainActivity getActivity() {
return activityRef.get();
}
}
}
I'm using a simple activity (from this library) with ZXing to scan a barcode.
Everything works fine, but the transition between the MainActivity and the ScannerActivity doesn't work well. Halfway through it gets interrupted. When going back from the ScannerActivity to the MainActivity the transition works like desired. Only while loading the barcodescanner it doesn't look really good.
Do you have any idea how to fix this?
MainActivity:
private void invokeScanner() {
try {
Intent intent = new Intent(this, ScannerActivity.class);
stealFocus(et_loadInput);
startActivityForResult(intent,0);
this.overridePendingTransition(R.anim.detail_anim_up, R.anim.detail_anim_down);
} catch (Exception e){
Log.e(TAG, "couldn't open scanner");
e.printStackTrace();
openAlertDialog(Const.MSG_PROCESSING_ERROR);
}
}
ScannerActivity:
public class ScannerActivity extends AbstractTitleBarActivity implements ZXingScannerView.ResultHandler{
private ZXingScannerView mScannerView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mScannerView = new ZXingScannerView(this);
setContentView(mScannerView);
this.tv_backTitle.setText(getString(R.string.TITLE_SEARCH_VIEW));
this.tv_heading.setText("");
TextView titleClose = (TextView) findViewById(R.id.btn_close);
titleClose.setVisibility(View.VISIBLE);
titleClose.setOnClickListener(titleCloseListener);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
#Override
public void onResume() {
super.onResume();
mScannerView.setResultHandler(this); // Register ourselves as a handler for scan results.
mScannerView.startCamera(); // Start camera on resume
}
#Override
public void onPause() {
super.onPause();
mScannerView.stopCamera(); // Stop camera on pause
}
#Override
protected boolean isBackBtnVisible() {
return false;
}
#Override
protected boolean isLogoVisible() {
return false;
}
#Override
public void handleResult(Result rawResult) {
Log.v(TAG, rawResult.getText()); // Prints scan results
Log.v(TAG, rawResult.getBarcodeFormat().toString()); // Prints the scan format (qrcode, pdf417 etc.)
MainActivity.scanVal = rawResult.toString();
MainActivity.loadVal = MainActivity.scanVal;
finish();
overridePendingTransition(R.anim.detail_anim_back_down,R.anim.detail_anim_back_up);
}
// listener for close button
protected TextView.OnClickListener titleCloseListener = new TextView.OnClickListener() {
public void onClick(View v) {
finish();
overridePendingTransition(
R.anim.detail_anim_back_down, R.anim.detail_anim_back_up);
}
};
}
I actually solved my own problem :D with this answer.
I just put the ZXingScannerView into a fragment and added a surface view with 0px height as a sibling. Now the animation works fine and the barcode scanner loads without refreshing the complete activity.
I was having some problem for Android activity transition. Basically what I am trying to do is share text to Twitter. However, when I open up the twitter content, it took quite a few seconds to load up the content and resulting in the white blank activity for a few seconds.
And here is my codes, when my button onClick, I am executing the loading dialog:
ivTwitterShare.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Thread newThread = new Thread() {
#Override
public void run() {
try {
super.run();
sleep(10000);
} catch (Exception e) {
} finally {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri
.parse(tweetUrl));
startActivity(intent);
progressDialog.dismiss();
}
}
};
newThread.start();
new LoadTwitterTask().execute();
}
});
private class LoadTwitterTask extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(context, "Loading Twitter...",
"Retrieving Twitter information, please wait...", false,
false);
EventDialogueBox.customizeDialogueBox(context, progressDialog);
}
#Override
protected Void doInBackground(Void... params) {
try {
synchronized (this) {
int counter = 0;
while (counter <= 4) {
this.wait(50);
counter++;
publishProgress(counter * 25);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressDialog.setProgress(values[0]);
}
#Override
protected void onPostExecute(Void result) {
}
}
However, my problem now is the white blank page before the content is loaded up still there. What I wanted is firstly, the loading dialog will show. Then, at the same time, the twitter intent is loading. Once finish loaded up the content, then dialog will be dismissed.
Any ideas?
Thanks in advance.
how to manage a countdown to begin right away with an activity start and to start new activity when time is up? Thanks in advance
Edits:
Activity contatins a button. User should press it until time is up, otherwise another activity starts
try this code
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
//start new activity
}
}.start();
You can achieve this in two ways
METHOD 1: Creation of a thread and setting time to sleep exactly after that redirection to main app screen.
METHOD 2: Set time to handler and call Handler().postDelayed , it will surly call run method of runnable after setting the time and redirection to main app screen.
we can implement in this given way wher we can write code for our MainScreen
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
public class MainScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainscreen);
// METHOD 1
/****** Create Thread that will sleep for 10 seconds *************/
Thread background = new Thread() {
public void run() {
try {
// Thread will sleep for 10 seconds
sleep(10*1000);
// After 10 seconds redirect to another intent
Intent i=new Intent(getBaseContext(),AnotherScreen .class);
startActivity(i);
//Remove activity
finish();
} catch (Exception e) {
}
}
};
// start thread
background.start();
//METHOD 2
/*
new Handler().postDelayed(new Runnable() {
// Using handler with postDelayed called runnable run method
#Override
public void run() {
Intent i = new Intent(MainScreen.this, AnotherScreen.class);
startActivity(i);
// close this activity
finish();
}
}, 10*1000); // wait for 10 seconds
*/
}
#Override
protected void onDestroy() {
super.onDestroy();
}}
the AnotherScreen code can be as follows
import android.app.Activity;
import android.os.Bundle;
public class AnotherScreen extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.anotherScreen);
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
for an another example visit http://www.androidhive.info/2013/07/how-to-implement-android-splash-screen-2/
https://codereview.stackexchange.com/questions/31295/review-request-android-countdowntimer-activity
This is the answer you are looking for a spalshActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
try {
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
Intent i = new Intent(SplashScreen.this,
MainActivity.class);
startActivity(i);
finish();
}
};
Timer timer = new Timer();
timer.schedule(timerTask, 300);// DElay of 300 mil sec
} catch (Exception e) {
Log.e("ERROR in Splash Screen", e.toString());
}
}
I get this error "Can't create handler inside thread that has not called Looper.prepare()"
Can you tell me how to fix it?
public class PaymentActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.payment);
final Button buttonBank = (Button) findViewById(R.id.buttonBank);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
progressDialog = ProgressDialog.show(PaymentActivity.this, "",
"Redirecting to payment gateway...", true, true);
new Thread() {
public void run() {
try {
startPayment("Bank");
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
}
}.start();
}
});
StartPayment Method:
private void startPayment(String id) {
Bundle b = getIntent().getExtras();
final Sail sail = b.getParcelable(Constant.SAIL);
final Intent bankIntent = new Intent(this, BankActivity.class);
try {
Reservation reservation = RestService.createReservation(
sail.getId(),
getSharedPreferences(Constant.PREF_NAME_CONTACT, 0));
bankIntent.putExtra(Constant.RESERVATION, reservation);
// <workingWithDB> Storing Reservation info in Database
DBAdapter db = new DBAdapter(this);
db.open();
#SuppressWarnings("unused")
long rowid;
rowid = db.insertRow(sail.getId(), sail.getFrom(),
sail.getTo(), sail.getShip(), sail.getDateFrom().getTime(),
sail.getPrice().toString(), reservation.getId().floatValue());
db.close();
// </workingWithDB>
String html = PaymentService.getRedirectHTML(id, reservation);
bankIntent.putExtra(Constant.BANK, html);
} catch (Exception e) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog alertDialog = builder.create();
alertDialog.setMessage(e.getMessage());
alertDialog.show();
}
startActivity(bankIntent);
}
You should know that when you try to modify your UI , the only thread who can do that is the UiThread.
So if you want to modify your UI in another thread, try to use the method: Activity.runOnUiThread(new Runnable);
Your code should be like this :
new Thread() {
public void run() {
YourActivity.this.runOnUiThread(new Runnable(){
#Override
public void run(){
try {
startPayment("Bank");//Edit,integrate this on the runOnUiThread
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
});
}
}
}.start();
I assume you create a Handler in startPayment() method. You can't do that, as handlers can be created on th UI thread only. Just create it in your activity class.
Instead of new Thread() line, try giving
this.runOnUiThread(new Runnable() {
you cant change any UI in thread you can use runOnUIThread or AsyncTask for more detail about this click here
I've found that most thread handling can be replaced by AsyncTasks like this:
public class TestStuff extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonBank = (Button) findViewById(R.id.button);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new StartPaymentAsyncTask(TestStuff.this).execute((Void []) null);
}
});
}
private class StartPaymentAsyncTask extends AsyncTask<Void, Void, String> {
private ProgressDialog dialog;
private final Context context;
public StartPaymentAsyncTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(context);
// setup your dialog here
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setMessage(context.getString(R.string.doing_db_work));
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(Void... ignored) {
String returnMessage = null;
try {
startPayment("Bank");
} catch (Exception e) {
returnMessage = e.getMessage();
}
return returnMessage;
}
#Override
protected void onPostExecute(String message) {
dialog.dismiss();
if (message != null) {
// process the error (show alert etc)
Log.e("StartPaymentAsyncTask", String.format("I received an error: %s", message));
} else {
Log.i("StartPaymentAsyncTask", "No problems");
}
}
}
public void startPayment(String string) throws Exception {
SystemClock.sleep(2000); // pause for 2 seconds for dialog
Log.i("PaymentStuff", "I am pretending to do some work");
throw new Exception("Oh dear, database error");
}
}
I pass in the Application Context to the Async so it can create dialogs from it.
The advantage of doing it this way is you know exactly which methods are run in your UI and which are in a separate background thread. Your main UI thread isn't delayed, and the separation into small async tasks is quite nice.
The code assumes your startPayment() method does nothing with the UI, and if it does, move it into the onPostExecute of the AsyncTask so it's done in the UI thread.
Try
final Handler handlerTimer = new Handler(Looper.getMainLooper());
handlerTimer.postDelayed(new Runnable() {
public void run() {
......
}
}, time_interval});