This is my first question so sorry if I don't provide all the needed info. Just comment and I'll add it.
Onto the problem itself. I'm trying to make a splash screeen of sorts which consists of a short video. I want the app to start the following activity after the video ends, but after I start the app it just starts the second activity right away (Menu.class in the code). Once I'm in the Menu activity I can go back but all i see is a black VideoView. Also, the VideoView worked before I added the Handler. Not sure if it even could have been the problem (new to android studio) but doesn't work even after removing #Override (probably a stupidity, right?). Or can it be caused by the Menu.java activity? (It's just the standard pre-generated preset, I didn't make any changes to it)
public class splash_screen extends AppCompatActivity {
static long duration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.activity_splash_screen);
VideoView videoView = this.findViewById(R.id.videoView);
String path = "android.resource://" + getPackageName() + "/" + R.raw.splash;
videoView.setVideoURI(Uri.parse(path));
videoView.start();
duration = videoView.getDuration();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(splash_screen.this, Menu.class));
}
}, duration);
}
}
Thanks for any and every advice, and like I said let me know if you need more info on the problem.
VideoView need some time to warm up, so here:
videoView.start();
duration = videoView.getDuration();
duration could be 0, that is why handler fires immediately. To switch to the second activity you should remove handler part and use:
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
startActivity(new Intent(splash_screen.this, Menu.class));
finish();//close activity
}
});
You Can Also Use Thread.sleep(millisecond); If you are adding animation to your splash screen
The Full C O D E:
Thread t=new Thread(){
#Override
public void run() {
try{
sleep(3000);
}
catch (InterruptedException e){
}
finally {
startActivity(i);
}
}
};
t.start();
It Gives a delay of 3 seconds,you can do animation part within it
Related
I am working on an application for research purposes. We want to track some user activity on the phone: if some actions are easily detactable with broadcast receivers, we want also to check current running applications.
This application works only on Android devices that runs android 5.0 or lower.
My problem is that I post a Runnable Obj in a handler, Runnable posts again itself in handler after HALF_SECOND (see code for details). In runnable I get information and send them to IntentService to perform work.
Everything works fine: app starts at boot, handler and runnable do their job in background UNLESS I open the main Activity.
The app is able to keep going for days, but if I open the main Activity and then close it from "recent open activities" with a swipe, or from the memory task manager, handler and runnable stop, even if they are not called/accessed by the activity (they are in a Separate Service).
Moreover, not always a call to onDestroy (of the activity or Service) is made.
Reading online I understand that swipe or task manager remove the app from memory abrouptly thus not always calling onDestory.
What I want to achive is to make the handler start again soon after the main activity is closed.
What I have tried is to put some check in onPause method of the activity, making sure to remove this check if onStart is called again (like in case the the app switches from vertical to horizontal layout, or if home button is pressed and then app is opend again). Also implemented a way to make the handler send "ImAlive" intent to a broadcast receiver, which should restart the service that starts the handler, if intents do not arrive before a count down is finished. Unfortunately, as soon the main activty stops existing, even the broadcast is automatically unregistered and destroyed.
My question is, is there a way to create something that is able to make my handler restart if the activity is closed? Or is there some other pattern that can help me as workaround for what I want to achieve? Because I am polling data every half second I read is better to use handler, because Timer augments small interval to a greater interval, and AlarmManager is not precise enough for very small interval.
What I want to achieve is something similar to Facebook, Instagram, Whatsapp, Telegram app, that are always in memory, and even if you force to terminate them, after a few seconds are back again there... how?
We are not interested in battery issues because of continuous polling to data. As for research purposes we don't mind if the phone on which we are testing last 2 days straight, 1 day or 12 hours or less.
Here the code: OnBootService is started from broadcast receiver, declared in manifest when onBootCompleted and ShutDown actions are received, in order to start and stop handler.
public class OnBootService extends Service{
private static final Handler handler = new Handler();
private final long HALF_SEC = 500;
private RunnableTest r = null;
private Context myContext = this;
private final String TAG = "BootService";
// Extras
public static final String START = "start";
public static final String STOP = "stop";
#Override
public IBinder onBind(Intent intent){
return null;
}
#Override
public int onStartCommand(Intent intent, int flag, int startId){
String action = intent.getAction();
switch(action){
case START: startHandler();
break;
case STOP: stopHandler();
break;
}
return START_NOT_STICKY;
}
private void startHandler(){
if(r == null){
r = new RunnableTest();
handler.post(r);
Log.i(TAG, "----Handler started!");
}
}
private void stopHandler(){
if(r != null){
Log.i(TAG, "----calling STOP");
handler.removeCallbacks(r);
r = null;
}
}
private class RunnableTest implements Runnable {
private String TAG = "RunnableTest";
public RunnableTest(){}
#Override
public void run(){
handler.removeCallbacks(this);
// Do stuff
Intent i = new Intent(myContext, MyIntentService.class);
i.putExtra("addStuff", myStuff);
myContext.startService(i);
handler.postDelayed(this, HALF_SEC);
}
}
Activity is empty: all method overridden just to understand proper Activity lifecycle, but else is empty for now.
public class MainActivity extends AppCompatActivity {
private final String TAG = "Activity";
private Context myContext = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// access a file and get stored information to show
setContentView(R.layout.activity_main);
Toast.makeText(getBaseContext(), "Application open successfully", Toast.LENGTH_LONG).show();
}
#Override
protected void onRestart(){
super.onRestart();
Log.e(TAG, "----onRestart Called");
}
#Override
protected void onStart(){
super.onStart();
Log.e(TAG, "----onSTART Called");
}
#Override
protected void onResume(){
super.onResume();
Log.e(TAG, "----onRESUME Called");
}
#Override
protected void onPause(){
super.onPause();
Log.e(TAG, "----onPAUSE Called");
}
#Override
protected void onStop(){
super.onStop();
Log.e(TAG, "----onSTOP Called");
}
#Override
protected void onDestroy(){
super.onDestroy();
Log.e(TAG, "----onDestroy Called");
}
}
Any help is really appreciated, if you need some more information on the code, I will update the post.
Thank you!
Android system can restart the service if u return START_STICKY inside onStartCommand().
It works perfectly on all lower version than Lollipop in Android.
No need of CountDownTimer.
The onStop method and onPause method is called whenever the home button is pressed and when calling setContentView. I want to be able to differentiate between the two to when the home button is pressed, the sound stops and when a new view is set, the sound continues. I'm a noob to java, but I have searched for a long time and can't find a solution.
#Override
protected void onResume() {
super.onResume();
if (btnSound.isChecked()){
snd.start();
}
}
#Override
protected void onStop() {
super.onStop();
snd.pause();
}
Well, to answer your question, the time between both the calls between onResume() and onStop() calls, might be so narrow that, you are not able to differentiate. You can try this if you may:
#Override
protected void onPause() {
super.onPause();
snd.start(); // Sound start
// SLEEP 2 SECONDS HERE ...
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
snd.pause();
}
}, 2000);
}
I am developing a board game that user plays with android. Since android is quite fast, I want to fake that android is performing some tough calculations and thus needs time for its next move.
What I want to do:-
User turn - he moves.
Android turn - android shows text "I am thinking" for 2 seconds
Android hides that text and and only after that moves his turn.
I tried doing:-
onAndroidTurn(){
textView1.setVisibility(View.VISIBLE);
Thread.sleep(2000);
textView2.setVisibility(View.GONE);
}
But what happens is that thread sleeps but text is not shown (okay I know why).
Then searching on stackoverflow, I learnt a way:-
onAndroidTurn(){
textView1.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable(){
void run() {
textView1.setVisibility(View.GONE);
}
}, 2000);
}
Now what this does is that it runs that text in another thread and android's turn is updated on screen and after moving it's turn android showing "Thinking" is total stupidity.
What can I do for this?
Try the following:
Show "I'm thinking"
Calculate your move but don't actually do the move, just store it for a while
Schedule timer
When timer runs out remove the text and do the move
Something like this:
onAndroidTurn(){
textView1.setVisibility(View.VISIBLE);
saveMove(calculateNextMove());
new Handler().postDelayed(new Runnable(){
void run() {
textView1.setVisibility(View.GONE);
doNextMove(restoreMove());
}
}, 2000);
}
Maybe you could just use an AsyncTask (like this pseudo-code):
private class ShowTextTask extends AsyncTask<Void, Void, Void> {
protected void onPreExecute(Void... result) {
textView.setText("Initital");
}
protected Long doInBackground(Void... urls) {
Thread.sleep(2000);
}
protected void onPostExecute(Void... result) {
textView.setText("After 2 seconds");;
}
}
Okay i did it like this:-
public void androidThinking(){
textView1.setVisibility(View.VISIBLE);
androidThinking = true; //explained below
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
droidThink.setVisibility(View.GONE);
//CODE for android's turn
androidThinking = false; //explained below
}
}, 2000);
androidThinking when set to true prevents the user from moving his turn by forcing the listener for user's button to return prematurely
btn.setOnClickListener(new View.onClickListener(){
#Override
public void onClick(View v) {
if(androidThinking)
return;
Thanx everyone for your reply.
i want the spash screen to only show when the app has been compltely destroyed not when it is running in the background and resumed
Android's Live-Circle
When your Acrivity is created:
onCreate
onStart
onResume
when your Activity becomes inactive:
onPause
onStop
when it becomes active again:
onRestart
onStart
onResume
and when it's destroyed:
onPause
onStop
onDestroy
Edit: what i would do is, i would define a global boolean for your Main-Activity, 'showSpash' for example, and initialize it as "true". Then, when your 'onCreate'-method is first called, you set it to "false".
Then, anytime the 'onCreate'-method is called, you check if the boolean is "false". If it is, don't show the splash, if not show it.
I created global variable in my application class:
public class MyApplicationClass extends Application {
public static boolean welcomeScreenIsShown = false;
}
Then in my splash activity I did something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
//Put this before anything else in OnCreate
if (MyApplicationClass.welcomeScreenIsShown) {
// Open your Main Activity
}
}
Then, in my Main Activity, I did:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyApplicationClass.welcomeScreenIsShown = true;
}
Good Luck!
A very simple method:
Main Activity is only a splash screen. This Activity is shown while a timer starts that elapses for say 4 seconds.
When 4 seconds hits, the splash screen activity is destroyed and the Main Application Activity is started.
Voila, you now have a splash screen that will never be shown, except when you first start the application.
public class SplashScreen extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
Thread t = new Thread() {
public void run() {
try {
int time = 0;
while (time < 4000) {
sleep(100);
time += 100;
}
}
catch (InterruptedException e) {
// do nothing
}
finally {
finish();
Intent i = new Intent(SplashScreen.this, MainApplication.class);
startActivity(i);
}
}
};
t.start();
}
}
A better approach would be to set the android:noHistory="true" attribute for SplashScreenActivity in the AndroidManifest.
Isn't this the purpose of "onResume()" vs. "onCreate()"?
I have a problem and that is my SplashScreen I have. It is built as an intro and after 3 seconds it shows the main menu of the program.
Anyway, if I press down Back or Home button during the time the SplashScreen shows, it closes, but the activity I have chosen to follow after the SplashScreen will still run after the three seconds.
My code: *****UPDATED CODE*****
Handler ur = new Handler();
myRun = new Runnable() {
public void run() {
mainIntent = new Intent(SplashScreen.this,MyApp.class);
SplashScreen.this.startActivity(mainIntent);
SplashScreen.this.finish();
overridePendingTransition(R.anim.fadein,
R.anim.fadeout);
}
};
ur.postDelayed(myRun, SPLASH_DISPLAY_TIME);
}
protected void onStop() {
super.onStop();
ur.removeCallbacks(myRun);
}
Even if I have an onStop() in this SplashScreen, the next activity will still run after the SPLASH_DISPLAY_TIME.
Since I changed the code I got Force Close after I pressed the Home button and the SplashScreen disappeared, also, I cannot launch my second activity.
Try to do it this way:
private static final int SPLASH_DISPLAY_TIME = 3000;
Handler ur = new Handler();
Runnable yourRunnable = new Runnable() {
public void run() {
mainIntent = new Intent(SplashScreen.this,MyApp.class);
SplashScreen.this.startActivity(mainIntent);
SplashScreen.this.finish();
overridePendingTransition(R.anim.fadein,
R.anim.fadeout);
}
};
ur.postDelayed(yourRunnable, SPLASH_DISPLAY_TIME);
Then, somewhere on onDestroy or whatever method you use to detect when your splashscreen activity get closed:
// somewhere
ur.removeCallbacks(yourRunnable);