this is my Splash Screen, If I press home or multitasking/appswitch button when Intent is started app crash, in logcat is FATAL EXEPTION: Thread-1277. Can I kill/delete this Intent when player press home button?
public class SplashScreen extends Activity {
private static int loadingTime = 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
setContentView(R.layout.loading_screen);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(SplashScreen.this, MainActivity.class);
startActivity(i);
finish();
}
}, loadingTime);
}
}
The following code tracks whether the SplashActivity is at least partially showing. If yes, it will continue to MainActivity. If not (activity is finished by pressing Back button, activity is stopped by pressing Home button) nothing happens.
This solution uses Fragments so the timing is preserved across e.g. screen orientation changes (it will always take specified time no matter how many times you rotate your device - the timer will not reset).
public class SplashActivity extends Activity {
// tracks when the activity is at least partially visible (e.g. under a dialog)
private boolean mStarted = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// your current code
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
setContentView(R.layout.activity_startup);
if (savedInstanceState == null) {
// first time onCreate, create fragment which starts countdown
getFragmentManager()
.beginTransaction()
.add(SplashFinishFragment.newInstance(), SplashFinishFragment.TAG)
.commit();
} else {
// fragment already set up from first onCreate after screen rotation
}
}
#Override
protected void onStart() {
// the activity becomes at least partially visible
mStarted = true;
super.onStart();
}
#Override
protected void onStop() {
// the activity is no longer visible
mStarted = false;
super.onStop();
}
public boolean isStarted2() {
// there is already hidden method isStarted() in the framework
// you can't use it and are not allowed to override it
return mStarted;
}
public static class SplashFinishFragment extends Fragment {
private static final String TAG = SplashFinishFragment.class.getSimpleName();
private static final int DELAY = 1000; // one second delay
private static final Handler mHandler = new Handler(); // one main thread anyway
private final Runnable mRunnable = new Runnable() {
#Override
public void run() {
if (getActivity() == null) {
// this should never happen, there is no activity, so no fragment
Log.e(TAG, "No activity!");
return;
}
SplashActivity a = (SplashActivity) getActivity();
if (a.isStarted2() || a.isChangingConfigurations()) {
// if activity is even partially visible or is rotating screen right now, continue
Intent i = new Intent(a, SettingsActivity.class);
a.startActivity(i);
}
// in any case close splash
a.finish();
}
};
public static SplashFinishFragment newInstance() {
return new SplashFinishFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// the countdown will continue (not reset) across screen rotations
setRetainInstance(true);
// try running the main activity after specified time
mHandler.postDelayed(mRunnable, DELAY);
}
#Override
public void onDestroy() {
// if the fragment gets destroyed (e.g. activity closes) do not launch main activity
mHandler.removeCallbacks(mRunnable);
super.onDestroy();
}
}
}
This was tested on a virtual Galaxy S2. It works when Home or Back button is pressed. It doesn't work when Recent Apps button is pressed. I don't know your use case but personally I would expect the app to continue launching while I browse recent apps.
Related
I am developing an app in which I have activity called "A" and another activity called "B". I used intent to navigate between "A" to "B", but when my app goes in background Intent still works.
What I want when app goes in pause state stop navigating from"A" to "B".How can I do that?
Here is code:
public class CSplashScreen extends AppCompatActivity {
// Splash screen timer
private static final int m_n_SplashTimeOut = 4000;
private ImageView splash_image;
private boolean isConnected;
private static CLoginSessionManagement s_oCloginSession;// refernce of loginsession management
public void onAttachedToWindow() {
super.onAttachedToWindow();
Window window = getWindow();
window.setFormat(PixelFormat.RGBA_8888);
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
if (NetworkUtil.isConnected(getApplicationContext())){
}else {
CSnackBar.getInstance().showSnackBarError(findViewById(R.id.mainLayout), "No internet connection available", getApplicationContext());
}
init();//initialize controls
}
private void init() {// initialize controls
Animation animation = null;
splash_image = (ImageView) findViewById(R.id.splash_image);
animation = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.zoom_out);
animation.setDuration(1500);
splash_image.startAnimation(animation);
new Handler().postDelayed(new Runnable() {
// This method will be executed once the timer is over
#Override
public void run() {
Intent i = new Intent(CSplashScreen.this, CMainActivity.class);
startActivity(i);
}
}, m_n_SplashTimeOut);// spalsh screen timing
}
}
#Override
public void run() {
if (!isFinishing()) {
startActivity(new Intent(CSplashScreen.this, CMainActivity.class));
}
}
You can have a flag like 'isPauch'.. make it true in in onPause() and make it false in onResume(). And check if flag is false then move to other activity.
Activity.onPause() and onStop() are called in (at least) two situations:
The another Activity was launched on top of the current one.
The app was minimized.
Is there an easy way to tell the difference?
You could do it this way. Make all of your activities extend from a base activity. The base activity needs to keep a visibility counter that is incremented/decremented during onResume/onPause:
public abstract class MyBaseActivity extends ActionBarActivity {
private static int visibility = 0;
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new Handler();
}
#Override
protected void onResume() {
super.onResume();
visibility++;
handler.removeCallBacks(pauseAppRunnable);
}
#Override
protected void onPause() {
super.onPause();
visibility--;
handler.removeCallBacks(pauseAppRunnable);
// give a short delay here to account for the overhead of starting
// a new activity. Might have to tune this a bit (not tested).
handler.postDelayed(pauseAppRunnable, 100L);
}
#Override
protected void onDestroy() {
super.onDestroy();
// uncomment this if you want the app to NOT respond to invisibility
// if the user backed out of all open activities.
//handler.removeCallBacks(pauseAppRunnable);
}
private Runnable pauseAppRunnable = new Runnable() {
#Override
public void run() {
if (visibility == 0) {
// do something about it
}
}
};
}
My app has the following Activities:
DashboardActivity
SplashActivity
MainActivity
This how the flow is required:
The dash board has a button that starts up the MainActivity. The onCreate() method of the main activity checks if a user-profile was previously created, if yes, then it starts normally (this is fast, no GUI delay).
If no user-profile is found, then it's required to display a splash screen having instructions/how-to for the mainActivity, meanwhile the onCreate() of the main activity creates a new user-profile file(slow and GUI blocking).
What I'm currently see is the splash/instructions showing delayed after the slow user-profile creation ends.
Here is a code snippet from MainActivity.
private void showUsage(){
Thread splashTread = new Thread() {
public void run() {
try {
Intent instructionIntent = new Intent(MainActivity.this,
InstructionsActivity.class);
startActivity(instructionIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
};
splashTread.start();
}
#Override //MainActivity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
if (!IsProfileExists()){
showUsage();
try{
createUserProfile(); //slow!
} catch (Exception e) { }
}
/*Continue with MainActivity*/
}
The Splash dismisses itself by a click:
public class InstructionsActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.instructions_layout);
ImageView instructions = (ImageView) findViewById(R.id.ivInstructions);
instructions.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
}
}
The problem:
The Instructions Activity (splash) shows after the GUI gets block from the MainActivity onCreate().
Any clues?
Do the condition check (IsProfileExists()) from dashBoardActivity and call the Splash activity if profile doesn't exist.
I have a simple activity that starts and stops a background service that logs GPS data. I then place the process in the background by clicking on the home button.
When I return to the App by clicking on it's icon it creates a new process rather than reverting to the original activity. If I then close this process (by clicking the back button) it calls onDestroy() and then reverts back to my original activity screen showing the service is still recording. This is very inconvenient for the intended use of the App.
It is my understanding the original activity should of been popped from the activity stack rather than a new process being created.
Included below is my activity code. I would appreciate anybody's explanation of this.
public class MainActivity extends Activity {
GPSTracker gps;
private static final String TAG = "MEDIA";
private String tv;
private boolean record = false;
private TextView status = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
record = savedInstanceState.getBoolean("Status");
Toast.makeText(getApplicationContext(),"onCreate",Toast.LENGTH_LONG).show();
setContentView(R.layout.activity_main);
}
public void StartRecord(View v) {
Button btn = (Button) findViewById(R.id.record);
status = (TextView) findViewById(R.id.status);
if (record == false) {
btn.setText("Stop Record");
status.setText("... Recording ...");
record = true;
ComponentName comp = new ComponentName(getPackageName(), LogService.class.getName());
ComponentName service = startService(new Intent().setComponent(comp));
}
else {
record = false;
status.setText("... Standing By ...");
stopService(new Intent(MainActivity.this,LogService.class));
btn.setText("Start Record");
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Toast.makeText(getApplicationContext(), "onSaveInstanceState",Toast.LENGTH_LONG).show();
savedInstanceState.putBoolean("Status", record);
// etc.
}
#Override
public void onResume() {
super.onResume(); // Always call the superclass method first
Button btn = (Button) findViewById(R.id.record);
Toast.makeText(getApplicationContext(), "onResume",Toast.LENGTH_LONG).show();
if (record == true)
btn.setText("Stop Record");
else
btn.setText("Start Record");
}
#Override
public void onStart() {
super.onStart(); // Always call the superclass method first
Toast.makeText(getApplicationContext(), "onStart",Toast.LENGTH_LONG).show();
}
#Override
public void onRestart() {
super.onRestart(); // Always call the superclass method first
Toast.makeText(getApplicationContext(), "onRestart",Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
super.onDestroy(); // Always call the superclass method first
Toast.makeText(getApplicationContext(), "onDestroy",Toast.LENGTH_LONG).show();
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
Toast.makeText(getApplicationContext(), "onRestoreInstanceState",Toast.LENGTH_LONG).show();
record = savedInstanceState.getBoolean("Status");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Try this and override below to functions, It should work fine in your case.
onResume() -> set record=true
onPause() -> set record=false
I have two activities in my project- Splash and AActivity. Splash is the main activity and is working fine. But if i change the orientation while Splash activity is running, the UI of splash activity goes off but it opens the AActivity after 10 sec.
code for splash activity is -
public class Splash extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
Thread timer = new Thread(){
public void run() {
try{
sleep(10000);
}catch(InterruptedException e){
e.printStackTrace();
}finally{
Intent AActivityIntent = new Intent("com.example.ex.AACTIVITY");
startActivity(AActivityIntent);
}
}};
timer.start();
}
#Override
protected void onPause() {
super.onPause();
finish();
}
}
I want to retain the UI of splash activity for 10 seconds even if orientation is changed. After 10 sec splash activity should be finished. How to do it ???
I suggest you doing the following:
public class Splash extends Activity {
private Thread timer;
private volatile long timeLeft;
private long timeStarted;
private long timeStopped;
private static final long TIME_TO_SHOW = 100000
private static final String KEY_TIME_LEFT = "timeLeftToRun";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
if (savedInstanceState != null) {
timeLeft = savedInstanceState.getLong(KEY_TIME_LEFT, 0);
} else {
timeleft = TIME_TO_SHOW;
}
timer = new Thread() {
public void run() {
try {
sleep(timeLeft);
Intent AActivityIntent = new Intent("com.example.ex.LISTSCREEN");
startActivity(AActivityIntent);
} catch(InterruptedException e) {}
}
}};
timeStarted = SystemClock.elapsedRealtime();
timer.start();
}
#Override
protected void onPause() {
super.onPause();
timer.interrupt();
timeStopped = SystemClock.elapsedRealtime();
finish();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
timeLeft -= timeStopped - timeStarted;
if (timeLeft > 0) outState.putLong(timeLeft);
}
}
The main idea here is that you kill the thread if the activity is killed, but you take a note for how long it has run and how much time it has left. When the activity is restored, you do the same actions, except you have to wait for a smaller amount of time.
The code above is, of course, untested, but it should illustrate the idea.
Insert into your manifest these below block.
It means orientation change situation controlled by your "activity".
http://developer.android.com/guide/topics/manifest/activity-element.html#config
android:configChanges="orientation"
And more.
Override "onConfigurationChanged" method.
Try this. You can do everything you want.
Instead of using a Thread for delayed launch of activity use Alarmmanager, even if you are quitting the app you could always cancel the pending Alarm