I am working on an app and while testing on my phone a noticed something weird: if I close the app while the splash screen is running, when the time of the before mention activity is over, the app opens again, even if I am in another app. Why does this happen?
package com.example.arlet.storemaps;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import java.util.Timer;
import java.util.TimerTask;
public class SplashScreenActivity extends AppCompatActivity {
//duration of splash screen in miliseconds
long delay = 6000;
private Timer timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash_screen);
Timer RunSplash = new Timer();
TimerTask ShowSplash = new TimerTask() {
#Override
public void run() {
//finishing splash screen
finish();
//starting main activity
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
startActivity(intent);
}
};
RunSplash.schedule(ShowSplash, delay);
}
#Override
protected void onDestroy(){
timer.cancel();
timer.purge();
super.onDestroy();
}
}
Here's the code updated #Badran
Override the onDestroy Method in SplashActivity:
#Override
protected void onDestroy() {
//remove the handler or thread or etc... that is opening the another activity
//call timer.cancel()
//call timer.purge ()
super.onDestroy();
}
So Your code will be now :
package com.example.arlet.storemaps;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import java.util.Timer;
import java.util.TimerTask;
public class SplashScreenActivity extends AppCompatActivity {
//duration of splash screen in miliseconds
long delay = 6000;
private Timer RunSplash;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash_screen);
RunSplash = new Timer();
TimerTask ShowSplash = new TimerTask() {
#Override
public void run() {
//finishing splash screen
finish();
//starting main activity
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
startActivity(intent);
}
};
RunSplash.schedule(ShowSplash, delay);
}
#Override
protected void onDestroy(){
if(RunSplash != null){
RunSplash.cancel();
RunSplash.purge();
}
super.onDestroy();
}
#Override
protected void onPause() {
if(RunSplash != null){
RunSplash.cancel();
RunSplash.purge();
}
super.onPause();
}
}
Here is my code for an activity. In this I am printing the time elapsed on a text view. I want to put onPause and onResume method in this. It should work such that the time is paused while app is in background . And when again brought to forefront, should timer start from where it paused. I tried it using this code but the time is not paused. It continues to run in background. Can anybody help to find workaround for this.
package com.example.test;
import android.support.v7.app.ActionBarActivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView tt1;
private Handler customHandler = new Handler();
long timeInMilliseconds = 0L,timeToGo=0L,startTime=0L;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tt1=(TextView) findViewById(R.id.textView1);
startTime=System.currentTimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
}
public Runnable updateTimerThread=new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
long timeNow = System.currentTimeMillis();
timeToGo = 30 - (timeNow - startTime) / 1000;
tt1=(TextView) findViewById(R.id.textView1);
tt1.setText(timeToGo+"");
if(timeToGo<0L){
Intent intent=new Intent(MainActivity.this,Game.class);
finish();
startActivity(intent);
}
else
customHandler.postDelayed(this, 0);
}
};
#Override
public void onPause() {
super.onPause();
customHandler.removeCallbacksAndMessages(null);
}
#Override
public void onResume() {
super.onResume(); // Always call the superclass method first
customHandler.postDelayed(updateTimerThread, 0);
}
}
You need to update your startTime in onResume cause it hasn't changed...
#Override
public void onResume() {
startTime = System.currenTimeMillis() - timeToGo * 1000;
...
}
Or just use a Chronometer class http://developer.android.com/reference/android/widget/Chronometer.html
#Override
protected void onPause() {
customHandler.removeCallbacks(updateTimerThread);
super.onPause(); }
I'm developing a simple game where 3 activities (menu, settings and ranking list) needs one background music that should play smoothly in the background even if for example user leaves menu and goes into settings and then back.
For that I created service which works perfectly. There is only one major problem: when app is closed (user press home button for example), music doesn't stop playing.
I have tried with onDestroy, onStop, onPause but the problem is not solved.
Service:
package com.android.migame;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.IBinder;
public class Meni_music extends Service implements OnCompletionListener {
private static final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.menu);
player.setLooping(true); // Set looping
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
public IBinder onUnBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
player.stop();
player.release();
stopSelf();
}
#Override
public void onLowMemory() {
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
}
}
Menu:
package com.android.migame;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class Meni extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.meni);
startService(new Intent(Meni.this,Meni_music.class));
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
}
I think this behavior is most logically addressed by creating your own application class. Register this class in your manifest using:
<application
android:name="MyApplication"
Let the MyApplication class look something like this:
public class MyApplication extends Application
implements ActivityLifecycleCallbacks, Runnable
{
private Handler h;
#Override public void onCreate()
{
h = new Handler();
registerActivityLifecycleCallbacks(this);
}
public void onActivityCreated(Activity activity, Bundle savedInstanceState) { }
public void onActivityStarted(Activity activity) { }
public void onActivityStopped(Activity activity) { }
public void onActivitySaveInstanceState(Activity activity, Bundle outState) { }
public void onActivityDestroyed(Activity activity) { }
public void onActivityResumed(Activity activity)
{
h.removeCallbacks(this);
startService(new Intent(this, Meni_music.class));
}
public void onActivityPaused(Activity activity);
{
h.postDelayed(this, 500);
}
public void run()
{
stopService(new Intent(this, Meni_music.class));
}
}
Try this it will work .Make a ActivityLifecycleCallback class that will check if your application is in background or running.On onActivityStopped call stop your service.
public class MyLifecycleHandler implements ActivityLifecycleCallbacks {
private int resumed;
private int paused;
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
public void onActivityDestroyed(Activity activity) {
}
public void onActivityResumed(Activity activity) {
++resumed;
}
public void onActivityPaused(Activity activity) {
++paused
if(resumed == paused)
stopService(new Intent(this, Meni_music.class));
}
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
public void onActivityStarted(Activity activity) {
}
public void onActivityStopped(Activity activity) {
}
}
register your callback class -
registerActivityLifecycleCallbacks(new MyLifecycleHandler());
I had a similar requirement, and here's how I solved it:
Create a class that implements Application.ActivityLifecycleCallbacks, and have your application register it with registerActivityLifecycleCallbacks in it's onCreate method. This class will be notified every time an activity is paused or resumed.
Have this class maintain a count of the number of active activities - start at 0, add one for each resumed activity, and subtract one for each paused activity. In practice, your counter will always be zero or one.
In your onActivityPaused method, after decrementing the counter, check to see if the count is zero. Note that there is a short period of time between an Activity being paused and the next one being resumed when you transition between activities, during which the count will be zero. If, after waiting some reasonable amount of time from the onActivityPaused, your count is still zero, then your application has been put completely into the background, and you should stop your service.
This is what you can do,
Create a static helper class, add a static variable msActivityCount in it and add following 2 methods in it.
increaseActivityCount() - increment the msActivityCount value. If msActivityCount == 1 start the service. Call this function from onStart() of each activity.
decreaseActivityCount() - decrement the msActivityCount value. If msActivityCount == 0 stop the service. Call this function from onStop() of each activity.
This should solve your issue without any problems.
Easy solutions:
Just use one activity! Use Fragments for each screen that you are displaying.
Use a static counter. Increment the counter when you call startActivity(). Decrement the counter onPause() of all activities. When an activity pauses, and your counter is 0, then stop the music.
Start your service when Menu activity resumes and stop it when the activity stops. So the Menu activity should look like something like this:
package com.android.migame;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class Meni extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.meni);
}
#Override
protected void onPause() {
super.onPause();
stopService(new Intent(Meni.this,Meni_music.class));
}
#Override
protected void onResume() {
super.onResume();
startService(new Intent(Meni.this,Meni_music.class));
}
}
You declare your Intent outside the function in activity class and stop the service inside this class, call stop or ondestroy
like this:
public class Meni extends Activity {
private Intent i=new Intent();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.meni);
i=new Intent(Meni.this,Meni_music.class);
startService(i);
}
#Override
protected void onDestroy() {
stopService(i);
super.onDestroy();
}
#Override
protected void onStop() {
stopService(i);
super.onStop();
}
}
Background Music without using Services:
http://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion
when "don't keep activities" is selected on Setting's Developer Options progress dialog is not dismissing.
Actually, I am displaying the Progerss bar,for initialize the Application, When I am going to Activity A to Activity B and then came to Activity A, the Progress bar is not dismissing after initialize completed.
Below is my Code,
First Activity
package com.example.donotkeepactivitiesalive;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
public static final int MESSAGE_PROGRESS_BAR_INITIALIZING = 1;
private Dialog m_cObjDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println(getClass().getName() + "before InitializeEnvironment >>>>>>");
new InitializeEnvironment().execute();
System.out.println(getClass().getName() + "after InitializeEnvironment >>>>>>");
Button lb = (Button) findViewById(R.id.button1);
lb.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent lIntent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(lIntent);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
protected Dialog onCreateDialog(int id) {
m_cObjDialog = new ProgressDialog(this);
m_cObjDialog.setTitle("Initializing");
((ProgressDialog) m_cObjDialog).setMessage("Initializing the Application");
m_cObjDialog.setCancelable(false);
return m_cObjDialog;
}
class InitializeEnvironment extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
System.out.println(getClass().getName() + "onPreExecute >>>>>>");
super.onPreExecute();
showDialog(MESSAGE_PROGRESS_BAR_INITIALIZING);
}
#Override
protected String doInBackground(String... aurl) {
System.out.println(getClass().getName() + " doInBackground >>>>>>");
return null;
}
#Override
protected void onPostExecute(String unused) {
dismissDialog(MESSAGE_PROGRESS_BAR_INITIALIZING);
System.out.println(getClass().getName() + " onPostExecute >>>>>>");
}
}
}
Second Activity
package com.example.donotkeepactivitiesalive;
import android.app.Activity;
import android.os.Bundle;
public class SecondActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Is there any way to track this problem and work even if "don't keep activities" is enabled
I solved this, by checking the Bundle object is null or not.If the Bundle object is null then call the AsynTask class, else don't call,
if(null == savedInstanceState) {
new InitializeEnvironment().execute();
}
But make sure that your previous Activity is not overriding onActivityResult()
My app seems to start up properly, with the splash screen and stuff. But when it sleeps for 6 secs and when it supposed to get into the main activity the app crashes any help please?
Here is me code (android.intent.action1.MAINACTIVIVTY, the "action" was purposely changed to "action1")
package com.hellhogone.multitools;
import com.hellhogone.multitools.R;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Window;
import android.view.WindowManager;
public class Splash extends Activity{
#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.splash);
MediaPlayer yo = MediaPlayer.create(Splash.this, R.raw.smusic);
yo.start();
Thread timer = new Thread(){
public void run(){
try{
sleep(6000);
}catch(InterruptedException e){
e.printStackTrace();
}finally{
Intent h1 = new Intent("android.intent.action1.MAINACTIVITY");
startActivity(h1);
}
}
};
timer.start();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
finish();
}
}
You cannot start an activity from another thread than the UI thread. To avoid this problem you can use runOnUiThread() :
}finally{
runOnUiThread(new Runnable() {
public void run() {
Intent h1 = new Intent("android.intent.action1.MAINACTIVITY");
startActivity(h1);
}
});
}