I have two Activities in one application.
First one updates its TextViews every 3 seconds. It works fine.
When the keyguard (lock screen) is activated the first activity launches the second activity which appears over the lock screen (in order to show data even if the screen is locked). It also works fine.
I would like the TextViews of the second activity to be updated periodically by the first activity. I have played hours with this and tried a lot of suggestions I found with Google but none of them worked for me. The second activity always crashes with NullPointerException at the moment when the TextView.setText() is called.
What is the best practice for doing this?
Thanks in advance for any help.
I don't think there is a good way to do this, as your first activity could get collected by the system, and you generally don't want to do work after onPause has been called.
I would move that logic that updates the views into a service that runs in the background. Since it sounds like you only need this service while the application is running I would create a bound one.
http://developer.android.com/guide/components/services.html
You can pass the data on calling another activity as :
Intent intent =new Intent(FirstActivity.this, SecondActivity.class);
intent.putStringExtra("TextName","Value");
startActivity(intent);
As Ashish said you could use EventBus.
Add the library to your app and in your Second Activity register your activity in the EventBus in onCreate method:
EventBus.getDefault().register(this);
Create a new class in your project to define an event type:
public class TestEvent {
public TestEvent() {}
}
So in your second activity create a method to receive the event:
public void onEvent(TestEvent event) {
//stuff to do
}
Now, in your first activity you just have to "fire" the event in the method executed each 2 seconds:
EventBus.getDefault().post(new TestEvent());
Each time you execute post method, the onEvent of your second activity will be run.
A way to do it is by defining a Singleton object that holds the value to be displayed on the TextView, for instance, a Integer or a String.
Both activities have access to read/write into this object. So when you come back to the second activity, maybe on the onResume() method..you can the following:
public void onResume() {
super.onResume();
textview.setText(""+ MySingleton.getInstance().getValue());
}
On the other activity:
public void updateMethod() {
int newValue = .....;
MySingleton.getInstance().setValue(newValue);
}
This will make sure that whenever you come back to this activity (as onResume() is called), the value will be updated into the TextView. Of course, assuming that you are updating the value from the other activity accordingly.
Note this is the simplest solution you can do, professionally, I would do an event driven solution, where the observer gets notified when the value is changed. For that you can play with http://square.github.io/otto/ library.
Related
I've searched through dozens of Stackoverflow posts and the android doc but just couldn't find the answer.
According to the accepted answer of this SF-post the onCreate method runs when the activity is first created. It also notes that in here views are supposed to be created and list data is being binded.
Then the onStart Method runs but here's the issue. Where's the difference? If you do everything inside of onCreate, switch activities, your app will still display the same data, regardless whether you put the app in the background or switched activities.
So if you declare views in onCreate, what do you do in onStart? initiliaze the views to their R.id.view ? Fetch data?
onResume I suppose is then used for listeners since it's the gas and brake according to this SF-posts accepted answer.
onCreate() is called when the activity is first created. onStart() is called whenever the activity becomes visible, which includes when it is first created (after onCreate()) and after it is coming back to the screen from being stopped (e.g., another activity took over the screen).
So:
Put code in onCreate() that needs to happen when the activity is created (and use onDestroy() to clean it up)
Put code in onStart() that needs to happen either when the activity is created or when the activity returns to the foreground (and use onStop() to clean it up)
Frequently, we do not do anything special when the activity returns to the foreground, in which case you do not need to worry about onStart() or onStop().
I have four activity for my application, Main Activity -> second Activity-> Third Activity -> Fourth Activity. Each Activity contains the onBackPressed method implemented. Every time when the onBackPressed method called, it sends an intent to the previous activity. For Example, in Fourth Activity onBackPressed method, it contains an intent to go to the previous Activity, which is the Third Activity. This works fine upto the MainActivity. When I press on the back button on the MainActivity it must exit the application. However, it just starts the next activity, which is the second Activity. What causes this bug???
Here is some relevant code.
From the fourth activity:
#Override
public void onBackPressed() {
Intent intent = new Intent(this,third.class);
intent.putExtra("id",FinalID);
intent.putExtra("Image Item", categoryItem);
startActivity(intent);
}
From the third activity:
#Override
public void onBackPressed() {
Intent intent2 = new Intent(this, second.class);
intent2.putExtra("Image Item", categoryItem);
Toast.makeText(this, "theFinalActivity=" + categoryItem.getId(), Toast.LENGTH_SHORT).show();
startActivity(intent2);
}
The second activity looks like the following.
#Override
public void onBackPressed() {
next = false;
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
And finally the code in the MainActivity:
#Override
public void onBackPressed() {
System.exit(0);
}
Android System internally handles the backstack for the activities. You don't need to explicitly handle going back if you're not supposed to override the default behavior. In your case, On pressing back, you're not popping the current activity, instead you're pushing a new one into the backstack. This will result in ambiguous behavior of your back button.
First, the onBackPressed function is not required to be implemented only if you are caring about taking care of the activity stack (i.e. finishing up your third activity will bring back the second and finishing the second activity will bring up the first one and so on). The activity stack is already taking care of it.
Secondly, if you want to pass the data to a caller activity from the activity that you have opened from the caller, this is not the ideal way to do so. I would like to recommend you to read this documentation where it explains how to pass such intents in a graceful manner using the life-cycle functions provided by Android.
Just to give you a heads up, here are three steps for you to pass the data between activities in a backward direction.
You need to start the second activity from the first activity using startActivityForResult instead of startActivity with a request code passed along with it (so that you can differentiate between different request codes from other activity if there is any).
Then in your second activity, if you need to pass something to your caller activity (i.e. the first activity), you need to use setResult to pass the desired data back to the caller and finish() the second activity.
In the first activity, you need to implement onActivityResult function to get the data back from the second activity.
Here is a nice example of the overall implementation where you can take a look too.
I know that you are expecting that the system.exit(0) should kill the application whatever the situation is. However, in Android, it does not work in the way that you have expected I think. I am quoting from this answer on StackOverflow to explain how the system.exit(0) works.
System.exit(0) - Restarts the app with one fewer activity on the
stack. So, if you called ActivityB from ActivityA, and System.exit(0)
is called in ActivityB, then the application will be killed and
started immediately with only one activity ActivityA.
I hope that helps!
I am trying to write code for my android application for things to happen when the activity is Resumed. Although I only want this stuff to happen when the activity is re-visited for the second time and not the first time.
So I want the user to do what they need in the onCreate method in their first visit to the activity and then when they go back to the activity then the onResume code happens.
Should I be using a different method or how can I achieve what I am looking to do?
public void onResume(){
super.onResume();
RunningStatus = sharedPreferences.getBoolean("RunningStatus", false);
if (isS1Pressed) {
if (isPressed) {
if (RunningStatus = false) {
pause.setBackgroundResource(R.drawable.start);
}
}
}
EDIT:
I don't mean second time I mean every time after. Basically I have a production line and my app determines whether it is ahead or behind. So when the user enters this activity then the can perform the calculation. We have a pause button where the user can pause the line if the production line has been stopped in real life. Although I would like that the user can then go out of that specific production line and do calculations on other lines too. Although at the minute once I leave the activity I lose all its state.
Thanks
You could use a boolean flag. in onResume e.g.
if (secondVisit) {
...
} else secondVisit = true;
If you want to do some stuff for very specific time (only 2nd, not 1st or 3rd, 4th,...), I suggest you should use some counter variable and use activity method onSaveInstanceState() and onRestoreInstanceState() to store and retrieve. If you don't want to reset the counter when app got killed, use data persist like SharePreference to store counter.
i assume that you have gone through the activity life cycle if not then visit
https://developer.android.com/guide/components/activities/activity-lifecycle
boolean secondUse=false;//this should be a field in the activity class
onRestart() method is called only when we visited the activity and and came back and then we visit(i.e. when the activity already in the activity stack).
if you have other use case, then using sharedPreference would be better.
override the onRestart()
inside it write the following
if(!seconduse){
//do your stuff
secondUse=true;
}
as you said in the edit you need the stuff to work on every visit after first visit then simply put your code in onRestart() method
public void onRestart(){
super.onRestart();
RunningStatus = sharedPreferences.getBoolean("RunningStatus", false);
if (isS1Pressed) {
if (isPressed) {
if (RunningStatus = false) {
pause.setBackgroundResource(R.drawable.start);
}
}
}
}
I'm new to Android programming, so I'm probably missing something trivial here.
The goal is to create a prototype of a digital signage app. Right now I've created three activities; MainActivity has a method which switches to the second activity after a certain period of time. The same method is then called from the second activity to third, and from third back to main.
There are two problems though: first, is it ok to create new Intent every time the app switches between the activities? As I mentioned, I started learning Android recently, so please don't be mad if this is a super dumb question.
Second: the app launches itself after I've hit home button in my emulator even though I'm calling finish(); after the startActivity(intent);
Here is the method in the MainActivity:
public void switchActivities(final Class<?> classObject) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(getApplicationContext(), classObject);
startActivity(intent);
finish();
}
}, 1000);
}
The activities Second and Third extend MainActivity and call the switchActivities method:
switchActivities(Third.class); (from Second to Third).
Thanks in advance!
UPDATED:
I added public boolean isRunning = true; to my MainActivity and
if(isRunning) startActivity(intent); to the switchActivities method;
I also added a method
#Override
protected void onPause(){
super.onPause();
isRunning = false;
}
as advised here.
Although finish(); should have cleared the method stack, the app didn't close after pressing Home button but went to previous activity instead, so I added this line to every activity in the AndroidManifest file:
android:noHistory="true"
as advised here.
Sorry for not upvoting helpful answers, I don't have enough reputation yet.
Yeah, it is the proper way of switching activities by creating new intents. I am little confused about your second questions. if you are saying that as you are using postDelayed method which gets triggered after some interval, is being called even you have finished your activity or pressed home button, you can handle this by creating a boolean variable isRunning in your activity which gets false when onPause or onDestroy gets called. Then you in your postdelayed method, you can check the flag and then proceed as required.
The Intent used in navigation between the Activities , so it's cool to using it , no problem
The second problem because the Activity object still in your memory after you hit Home button , then the Handler will continue its work and start the activity after the certain period you determined in your code
For your first question: it's not a problem that you're creating a new Intent every time
The second one is a bit trickier. When you press the home button the current activity stays in memory, so it can start the new one even though you think it's not running. The easiest way to handle this to check weather the activity is finishing, and if so, you don't show the next one.
if (!isFinishing()) startActivity(intent);
This if statement prevents your activity to start a new one when it's in the background.
I want to update textview in my main activity view.
I have main.xml file that contains the main application ascreen,
in that screen, I have textview that I need to update from time to time from another activity (class).
If I try to update those values from the main activity it work perfect, but when I'm trying to do it from deferent activity the application crashes.
Here is the method of the main activity, I need to know how to call it from the other activity.
Main Activity method:
public void update_counters(){
TextView sms_textview = (TextView) findViewById(R.id.sms_textview);
sms_textview.setText(String.valueOf(sms_missed));
}
Please Help
Indeed it's a bad practice to have any static references to activities (or other contexts). Activity are designed to be rather independed from each other.
You can receive a result from an activity that was started with startActivityForResult() method and than react appropriately.
Like #Roman said, it's a bad practice to touch the UI stuff from other activities, and activities should be independent. What you can do, is a little bit redesign your message passing method. One might be good is to use the broadcast receiver, it also guarantees a better extensibility of your program.
So, whenever your 'other' activity need to call the update_counters, it turns to broadcast such an intent. Your previous MainActivity should register to listen to that broadcast, and update the UI as necessary. What would be the best is you can have several more instance of that activity, or other activity that can register to that broadcast as well.
Is there only one instance of your main activity? If so, store a static reference to it in the main activity class, initialize it in onCreate. Then have a static method that uses that reference to get to the instance:
static MainActivity TheMainActivity;
static public void update_counters()
{
TextView sms_textview = (TextView) TheMainActivity.findViewById(R.id.sms_textview); sms_textview.setText(String.valueOf(sms_missed));
}
The in the other activity:
MainActivity.update_counters();
This is called a singleton. Or, sometimes, a global.