I'm having a strange problem to do with stopping my android app. On my phone I have a home button and a back button, now when I go into my app after pressing the home button, the program loads data from the internet as expected, but when I go into my app after pressing the back button, the data doesn't load. I've debugged it to an extent, and have found out that the only difference is that the back button calls the onCreate() method. I'm quite confused to why this is is happening.
Here's some of my code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("DAP", "Created");
setContentView(R.layout.activity_ltc);
getActionBar().setTitle("LTC Charts");
getActionBar().setLogo(
getResources().getDrawable(R.drawable.new_litecoin_logo_large));
TextView textView = (TextView) findViewById(R.id.ltcdata);
textView.setText("Loading data...");
TimerTask timer = new TimerTask() {
#Override
public void run() {
parseJSON();
}
};
Timer time = new Timer();
time.schedule(timer, 500, 85);
}
"when I go into my app after pressing the back button, the data doesn't load."
If you have already launched your app, the Activity will be paused (and onPause is called) when you navigate away from it. When you navigate back to the app, the same activity instance is resumed (and onResume is called).
See http://developer.android.com/training/basics/activity-lifecycle/index.html
This is because your activity hasnt been destroyed. What you should do is put something into the onresume of your activity to get the data again when you come back to the activity. If you want the data to be destroyed for sure and the user never leaves the activity you can destroy everything in onpause.
As others said, override onResume().
A common pattern would be to extract common initialisation code into a method, and call it from where needed:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
#Override
protected void onResume(){
super.onResume();
init();
}
private void init(){
setContentView(R.layout.activity_ltc);
getActionBar().setTitle("LTC Charts");
// ....
}
This could be because your activity is not set correctly at AndroidManifest.xml .
Make sure the activity name is the right one. If you inserted your activity into some package include that name as well . for example I have my activitu which is called "SettingsActivity" (usually the default is MainActivity) set in a package called Activities :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<activity android:name=".Activities.SettingsActivity">
...
Use the on resume function below.
#Override
public void onResume(){
//will be executed onResume
}
Related
I have a, what I thought was a, simple task. I have a list of achievements in a recyclerView in my MainActivity. Clicking on one of the achievements launches the AchievementDetailActivity. You do an action in the AchievementDetailActivity and it completes the achievement. When that happens, I need the thumbnail on the MainActivity to be the achievement icon and not the locked icon. What I thought was I could just use the LocalBroadcastManager to send and receive messages from one activity to another, but that isn't working. From everything I have read you are supposed to unregister the listener in your activity onPause and onStop lifecycle methods, however, if you unregister the listener in the onPause of MainActivity, it gets unregistered when the AchievementDetailActivity starts and nothing gets delivered to the MainActivity. I don't understand how you can use LocalBroadCastManager with receivers to send information between activities when they get unregistered as soon as you start a new activity. The following example shows it unregisters as soon as the second activity is started, so the first activity will never get the broadcast...
public class MainActivity extends AppCompatActivity {
public static final String ACTION = "update";
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("MAIN ACTIVITY", "RECEIVED EVENT");
}
}
public void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver), new IntentFilter(ACTION));
}
public void onPause() {
Log.d("MAIN ACTIVITY", "REMOVING LISTENER");
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
//.. The rest of MainActivity
}
public class SecondActivity extends AppCompatActivity {
#Override
public void onStart() {
super.onStart();
//initialize view and such
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
Intent intent = new Intent(MainActivity.ACTION);
intent.putExtra("Something", "somewhere");
manager.sendBroadcast(intent);
}
)};
}
If you run the above, obviously with the buttons and such, you will get a message that shows it unregisters the listener as soon as SecondActivity starts and the MainActivity will never get the message it is supposed to get when you click a button on the second activity.
Is there a way to send information from activity to activity, or because of the lifecycle events is that not possible? Everything I read said LocalBroadcastManager was the right way to do it, but it gets unregistered so, how can it? Please help, this is driving me nuts. Thank you.
If you want to use your LocalBroadcastManager to fetch results, do not unregister in onPause, in which case must to unregister in onDestroy().
If you startAvtivity only to fetch some results, it is a good way to startActivityForResult.
Its not a great idea to use LocalBroadcastReceiver for this purpose. Use startActivityForResult instead. Follow this Official doc for implementation details.
The reason its not wokring is:
You are registering the receiver in onStart and unregistering it in onPause(). When your second activity is shown, onPause () will be called as a result the BroadcastReceiver is unregistered.
Its not a great idea to keep it registered since it would lead to memory leaks.
What should I do to prevent activity from being destroyed when home button is pressed. My activity is destroyed by pressing home Randomly.
Thanks in advance
This is the activity lifecycle-
When any application's activity goes to the background after the Home button was pressed, it isn't destroyed arbitrarily - the OS destroys activities in the background when it runs short of available RAM, so when the Home button is pressed the activity goes to onPause() -> onStop() and then it's up to the OS's mercy.
This can happen to any device running Android OS which runs into a low memory scenario at any given time, not only Galaxy S3.
The way to handle this is to use onSaveInstanceState in your activity:
#Override
protected void onSaveInstanceState(Bundle outState) {
// Put all important data you have into the outState before calling
// super.
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
// Here you will receive the bundle you put in onSaveInstanceState
// and you can take it from the state bundle and put it in place.
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Here you need to check if you have data, if
// onSaveInstanceState was called and you put data in that
// function, data should be available here, and put it back into
// place.
}
Have some problem with android finish() methods.
I have one parent-class activity. Lets call it ParentActivity. All other activities in my project extends ParentActivity. Each time on ParentActivity.onCreate there are some statement, and I want to stop activity from executing if it fails. But when I call finish() in parent, I cant stop executing onCreate method on its child. Something like that:
public class ParentActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!someStatement) finish();
}
public class Test extends ParentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("TAG", "I dont want this code!");
}
}
Surely, I can just verify in parent activity its status each time, but I dont think its a good idea.
public class Test extends RexActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (isFinishing()) return; /// It works - but it bad :(((
Log.d("TAG", "I dont want this code!");
}
}
Can I somehow stop executing onCreate method on child activity from its parent? Many thanks for any help!
I'm not sure if I got your question right. As you have some grammatical issues.
The onCreate statements are always executed. You can either have a Boolean in ParentActivity to stop the code from executing in ChildActivity#onCreate().
You can try making your onCreate() code more modular by dividing it into functions so that it's not called.
Let me know what works for you.
Best option is to Use finish() in your splash screen just before you create your second activity,
I'm starting a project and I want to reproduce a video in the main activity when the app is executed, when the user presses the video it goes to another activity. If the user press the back button, he is going to the main screen again and reproduces the video from the beginning. The video is located in the raw directory.
The problem is that the videoview is reproducing the video when the activity is first created but not when the user goes back to it from the other activity (In my case the MenuSection activity). The code is really simple but i will paste it anyway:
public class MainActivity extends Activity {
private VideoView mVideoView;
LinearLayout menuSection;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
mVideoView = (VideoView) findViewById(R.id.surface_view);
mVideoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() +"/"+R.raw.documentariesandyou));
mVideoView.requestFocus();
mVideoView.setMediaController(null); //i dont want the controls of the videoview.
mVideoView.start();
menuSection = (LinearLayout) findViewById(R.id.menuSection);
menuSection.setOnClickListener(new menuSectionListener());
}
class menuSectionListener implements OnClickListener {
public void onClick(View v) {
Intent staticActivityIntent = new Intent(MainActivity.this, MenuSection.class);
startActivity(staticActivityIntent);
}
}
}
The MenuSection is just an activity that shows a textview like "Hello world", so I'm not pasting it.
Move mVideoView.start(); to onResume() instead of onCreate() as:
#Override
protected void onResume() {
super.onResume();
mVideoView.start();
}
see Managing the Activity Lifecycle onResume() is called from your Activity when Activity is Already Running
call video.pause() on onPause() overrided method of your activity and call video.resume() on onResume() method of your activity.
Move mVideoView.start(); to onStart(), instead of onCreate().
See Activity Lifecycle in the developer docs for more info on how the lifecycle of Activities work.
I am not certain, but you may also need to move the setVideoURI(); to onStart() as well.
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()"?