I have a method in onResume() which fetches user's data and should get called when user launch the app. This is working fine.
The problem is that for example after opening 'Settings' when I tap/click on the back arrow, the method in onResume() gets called again and user data starts getting fetched again.
What I want is, I want that method to get called only when user launches the app and not every time the user transition back from settings to main activity.
Here's the onResume() in MainActivity.java:
#Override
protected void onResume() {
super.onResume();
fetchUserData();
}
Here's how I transition to Settings.java:
Intent settingsIntent = new Intent(MainActivity.this, SettingsActivity.class);
startActivity(settingsIntent);
Please let me how can I restrict the fetchUserData() to get called only when user launches the app and not again when user transition back to main activity from any other activity by tapping/clicking on back arrow.
Sorry, if question seems to be badly formatted. I'm still a beginner here.
if you want the method to be called only once when the activity opens move it inside OnCreate() method.OnResume() can be called several times.You can see the documentation of acttivity lifecycle here
You could adapt the following code, by setting a flag/indicator so that only wanted returns are processed (eg set resume_state to RESUMESTATE_NOTHING except when starting an intent after which you want to fetchUserData:-
public class AisleListByCursorActivity extends AppCompatActivity {
public final static int RESUMESTATE_NOTHING = 0;
public final static int RESUMESTATE_AISLEADD = 1;
public final static int RESUMESTATE_AISLESTOCK = 2;
public final static int RESUMESTATE_AISLEDELETE =3;
public final static int RESUMESTATE_AISLEUPDATE = 4;
public int resume_state = RESUMESTATE_NOTHING;
public ShopsCursorAdapter currentsca;
public AislesCursorAdapter currentaca;
public ShopListSpinnerAdapter currentslspa;
public long currentshopid;
private final static String THIS_ACTIVITY = "AisleListByCursorActivity";
private final ShopperDBHelper shopperdb = new ShopperDBHelper(this,null, null, 1);
private ListView aisleslistview;
private Cursor csr;
private int shopid = 0;
protected void onResume() {
super.onResume();
switch (resume_state) {
case RESUMESTATE_AISLEADD:case RESUMESTATE_AISLEUPDATE: {
Cursor csr = shopperdb.getAislesPerShopAsCursor(currentshopid);
currentaca.swapCursor(csr);
resume_state = RESUMESTATE_NOTHING;
break;
}
default: {
resume_state = RESUMESTATE_NOTHING;
}
}
}
........
public void aalbcadd(View view) {
resume_state = RESUMESTATE_AISLEADD;
Intent intent = new Intent(this,AisleAddActivity.class);
intent.putExtra("Caller",THIS_ACTIVITY);
intent.putExtra("SHOPID", currentshopid);
startActivity(intent);
}
Create method in OnStart() or onCreate() rather than onResume(). for reference - please see this link for better understanding of Android LifeCycle http://developer.android.com/reference/android/app/Activity.html
If you want your method to be called only once you must put that method in onCreate method of Activity. Because onResume is always called you come back to the activity as per Android lifecycle. So just replace you method fetchUserData(); into onCreate like below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app_list);
fetchUserData();
}
#Override
protected void onResume() {
super.onResume();
}
Related
Short:
I have Three classes: A (MainActivity), B (Secondary), C(Third).
A is parent of B is parent of C.
In A I make an Intend with Extra int idForUsage on B. B stores idForUsage in a variable int chosenId(works fine).
B does Stuff and makes an Intent with Extra int chosenId and int secondIdForUsage(works also fine).
C does Stuff and it works all fine.
When I´m now clicking the litte "back button" in the upper left corner to get to the parent activity the app crashes because I´m trying to access the Variable chosenId which seems to being set to default -1 (even if I´m trying to read the Extra again.)
public class MainActivity extends AppCompatActivity {
//references to Buttons etc
...
public static final String ChosenID = "com.example.Abzeichenschwimmer.ChosenSwimmerID";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//set up button stuff
...
//ListView which has clickable Items which trigger the Activity
lv_swimmerList = findViewById(R.id.lv_schwimmerListe);
//Listeners
lv_swimmerList.setOnItemClickListener(this::onListViewItemClick);
}
#Override
protected void onResume(){
super.onResume();
updateSchwimmerliste(dataBaseHelper);
}
public void onListViewItemClick(AdapterView<?> parent, View view, int position, long id) {
SchwimmerModel clickedSchwimmer = (SchwimmerModel) parent.getItemAtPosition(position);
Intent intent = new Intent(MainActivity.this, DisplaySchwimmer.class);
//Toast.makeText(MainActivity.this, String.valueOf(clickedSchwimmer.getId()), Toast.LENGTH_SHORT).show();
intent.putExtra(ChosenSwimmerID, clickedSchwimmer.getId());
startActivity(intent);
}
}
public class DisplaySchwimmer extends AppCompatActivity {
int chosenSwimmerID;
public static final String SchwimmerID = "com.example.Abzeichenschwimmer.schwimmerID";
public static final String AufgabenID = "com.example.Abzeichenschwimmer.aufgabenID";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_schwimmer);
lv_exc = findViewById(R.id.lv_aufgaben);
refreshValues();
showAufgabenOnListView(dataBaseHelper);
lv_exc.setOnItemClickListener(this::onListViewItemClick);
}
public void getIntentExtra(){
Intent intent = getIntent();
chosenSwimmerID = intent.getIntExtra(MainActivity.ChosenSwimmerID,-1);
}
public void onDeleteClick(View view){
SchwimmerModel toDeleteSwimmer = (SchwimmerModel) dataBaseHelper.getSchwimmerByID(chosenSwimmerID);
dataBaseHelper.deleteSchwimmer(toDeleteSwimmer);
Toast.makeText(this, "deleted", Toast.LENGTH_SHORT).show();
DisplaySchwimmer.this.finish();
}
public void refreshValues(){
getIntentExtra();
SchwimmerModel schwimmer = dataBaseHelper.getSchwimmerByID(chosenSwimmerID); <--- Main Error
}
private void showAufgabenOnListView(DataBaseHelper dataBaseHelper) {
getIntentExtra();
ArrayAdapter<ExcerciseModel> schwimmerArrayAdapter = new ArrayAdapter<ExcerciseModel>(DisplaySchwimmer.this, android.R.layout.simple_list_item_1, dataBaseHelper.getExcersisesForSwimmerByID(chosenSwimmerID));
lv_exc.setAdapter(schwimmerArrayAdapter);
}
public void onListViewItemClick(AdapterView<?> parent, View view, int position, long id) {
ExcerciseModel clickedExcerciseModel = (ExcerciseModel) parent.getItemAtPosition(position);
Intent intent2 = new Intent(DisplaySchwimmer.this, DisplayAufgabe.class);
intent2.putExtra(SchwimmerID, chosenSwimmerID);
intent2.putExtra(AufgabenID, clickedExcerciseModel.getId());
Log.e("aaa", String.valueOf(chosenSwimmerID));
startActivity(intent2); <-- Intentstart
}
#Override
protected void onResume(){
super.onResume();
showAufgabenOnListView(dataBaseHelper);
}
}
I hope the code (deleted many lines) is ok for an overview. Maybe someone knows the solution for this.
Thanks Maximus
When you press back from DisplayAufgabe to DisplaySchwimmer (the intent always is null)
Because you call getIntent di DisplaySchwimmer, you will get default value which is -1 (null intent extra)
When you try to call dataBaseHelper.getSchwimmerByID(chosenSwimmerID); is mean you try to get index -1 on database. You will always get error because accessing index -1.
My Suggestion
Add validation before call dbHelper i.e
if (chosenSwimmerID > -1){
SchwimmerModel schwimmer = dataBaseHelper.getSchwimmerByID(chosenSwimmerID);
}
Only getExtra when value available
if (intent.hasExtra(MainActivity.ChosenSwimmerID)){
chosenSwimmerID = intent.getIntExtra(MainActivity.ChosenSwimmerID,-1);
}
It all boiled down on using sharedPreferences. This helped a lot. A Second post from me explanined this problem more simplified and I found a solution.
I am working on android application in which i need to start the location service. All i need to make it sure that the service should work, whether it will be on any activity, if i press the back button/home button or even if i sweep the application by pressing home button. My location service stops working after sometime like i put the timing of 1 minute but it will call it after 2-3 minutes.
private static final LocationRequest REQUEST = LocationRequest.create()
.setInterval(1000 * 60 * 1) // 30 minutes seconds
.setFastestInterval(1000 * 60 * 1) // 16ms = 60fps
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
My code is given below for calling location service class and main class where i am running calling that service. Please help me out in the above described scenario where i want to run that service in background: When press the back button, home button, removing application by pressing home button.
public class GPSLoggerService extends Service {
private LocationManager lm;
private static long minTimeMillis = 2000;
private static long minDistanceMeters = 0;
private static float minAccuracyMeters = 35;
private static boolean showingDebugToast = false;
MyLocationTracker locationTracker;
private static final String tag = "MUrgency GPS Logger";
/** Called when the activity is first created. */
private void startLoggerService() {
if (locationTracker != null)
return;
locationTracker = new MyLocationTracker(this) {
#Override
public void onLocationFound(Location location) {
Constants.sMY_LOCATION = location;
float a = (float) location.getLatitude();
float b = (float) location.getLongitude();
SharedPreferences prefs = getSharedPreferences("locationPref", 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putFloat("latitudeFloat", a);
editor.putFloat("longitudeFloat", b);
editor.commit();
if (minutes > 5){
shouldSync = true;
}
}
};
}
private void shutdownLoggerService() {
}
}
#Override
public void onCreate() {
super.onCreate();
startLoggerService();
}
#Override
public void onDestroy() {
super.onDestroy();
shutdownLoggerService();
}
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Class for clients to access. Because we know this service always runs in
* the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
GPSLoggerService getService() {
return GPSLoggerService.this;
}
}
}
Main class where i am calling service at onCreate()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mainlanding);
startService(new Intent(this, GPSLoggerService.class));
}
#Override
protected void onDestroy() {
sActivityMain = null;
super.onDestroy();
stopLocationService();
}
From my view I can see this is a normal process, when the app enters OnPause method, this starts to works in background then you need a background process to execute your class and functions that you want.
If this is your first time using parallel programming I think you need to dedicate a little bit of your time to search information about this. It's amazing form to work with background processes. Really it's the difference between a normal android programmer and professional android programmer (among other things) because with the background processes can use all potency of your device.
Tell me if I helped you, good programming!
I have two activities. I want to pas an integer to the other. this is how i do it
public void gotoSecondActivity(View v) {
Intent intent = new Intent(this, SecondActivity.class);
intent.putIntegerArrayListExtra("myInt", myVariable);
startActivity(intent);
}
and then i retrieve it in the onCreate function as follows
var = getIntent().getIntExtra("myInt", 0);
This works. But it only gets the value AT THE moment when i press the button to go to next activity
However, myVariable is an integer that keeps updating and changing. EVEN when I am on my secondActivity, the integer should be running in background and changing.
Is there a way to constantly pass this integer?
I have even tried to make it static and read it like var = MainActivity.myVariable;
You need to implement some sort of observer pattern. Use BroadcastReceiver, or event bus like otto or GreenRobot.
update (more details):
build.gradle
dependencies {
compile 'de.greenrobot:eventbus:2.2.1'
}
Event.java
public class Event {
public int value;
public Event() {}
}
MainActivity.java
public class MainActivity extends Activity {
private Event event = new Event();
// inside a loop
event.value = newValue;
EventBus.getDefault().post(event);
}
SecondActivity.java
public class SecondActivity extends Activity {
#Override
public void onResume() {
super.onResume();
EventBus.getDefault().register(this);
}
#Override
public void onPause() {
EventBus.getDefault().unregister(this);
super.onPause();
}
public void onEvent(Event event) {
// do something
}
}
But more importantly, what type of value are you sending over, and how do you plan on updating it?
You should be better off using an IntentService or some background process.
Why don't you define the variable at Application level and you access to it at any moment?
Your solution of making it static should do the trick, just be sure to not store the variable locally but always fetch it from the static field, this will be the simplest way to do this.
I am newbie in android, in my android app, a main Activity class, which contains a TextView for displaying various status message from other classes. I want to update TextView of main Activity with status values from other classes. There is no direct connection between main activity class and other class. Is it possible in android ? if yes i am not aware to do it. Kindly provide solution to do it
code snippets
//main activity
public class MainMenu extends Activity {
static String status = "Hello Friends";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView)findViewById(R.id.mytext);
tv.setText(status);
MyOtherClass myclass = new MyOtherClass();
myclass.connect();
}
Other class is not an activity class
// Other class
public class MyOtherClass {
public MyOtherClass(){
}
public void connect(){
String strIP = Mtx.confRead("IPAddress");
String strPort = Mtx.confRead("Port");
String msg = "Connecting...";
// i want to show value of msg varible in Textview of main activity from here
}
thanking you
Make a status instance field in your main activity
public static status = "initial status";
set it to the TextView
TextView tv = (TextView) findViewById(R.id.youtTextViewId);
tv.setText(status);
and update it using values in other activities when they are called.
Yes it is possible you need to pass those status values from other classes and then use
textView.setText(your_status);
values can be passed via intents through putExtra() and getExtra()
in first class send status like this
s=new Intent(this, nextClassName.class);
d=new Bundle();
d.putString("status", status);
s.putExtras(d);
startActivity(s);
then in the newClassName u can get it by this code
Intent t=getIntent();
k=t.getExtras();
status=k.getString("status");
the u can set Text of textview to status
textview.setText(status);
try this
u can do this by making these changes in your code
public String connect(){
String strIP = Mtx.confRead("IPAddress");
String strPort = Mtx.confRead("Port");
String msg = "Connecting...";
return msg;
// i want to show value of msg varible in Textview of main activity from here
}
and in main class
String status=myclass.connect();
textview.setText(status);
try this
if the other classes are activities that are started by ur activity, then use something like this
Main Activity
private void some_function() {
startActivityForResult(intent_to_pass, SOME_REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if((requestCode == SOME_REQUEST_CODE) && (resultCode == RESULT_OK)) {
// extract status from data and use setText() to set the new status
}
}
Other Activity
// Prepare an intent, say result, with the status to be sent to main activity and use this to send back the new status
setResult(RESULT_OK, result);
If the other classes are services and/or activities that are independent, then in Main Activity, use
#Override
protected void onNewIntent(Intent intent) {
// Extract new status from intent now and use it
}
In the other classes, simply start the main activity with an intent containing the new status. This ensures that if the main activity is already running, simply use the data in new intent received
EDIT (saw ur updates after posting):
if the other class is neither an activity nor a service, then u can do this:
when u create this class, pass the context of parent class (which can either be a service or an activity) to it and use this context to create an intent which is used with startActivity(). Or, simply communicate using BroadcastListeners. But i m not sure if this is the best way to do it
May be this could work.......
//main activity
public class MainMenu extends Activity {
static String status = "Hello Friends";
static TextView tv;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView)findViewById(R.id.mytext);
tv.setText(status);
MyOtherClass myclass = new MyOtherClass();
myclass.connect();
}
In other class:
// Other class
public class MyOtherClass {
public MyOtherClass(){
}
public void connect(){
String strIP = Mtx.confRead("IPAddress");
String strPort = Mtx.confRead("Port");
String msg = "Connecting...";
MainMenu.tv.setText(msg);
}
My application has a few activities, and a background service. My question is, if I have the context variable in the service, how can I tell which activity is currently open? I need to do this to direct the next action my service takes. For example,
if (context is activity_1) {
//take this action
} else if (context is activity_2) {
//do this instead...
}
That's the basic gist of what I'm trying to do.
Help much appreciated.
You could set a SharedPreferences entry in each onResume() method of your activities and read that value from the service. To keep it clean you could write an Activity that does that and then extend all your activities from it:
public class MyActivity extends Activity {
private static final String PREFS_NAME = "MyPrefsFile";
#Override
protected void onResume() {
getContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
.edit()
.putInt("activtiyIdRunning", getActivityId() )
.commit();
super.onResume();
}
abstract protected int getActivityId();
}
public class MyConcreteActivity1 extends MyActivity {
#Override
protected int getActivityId() {
return 1;
}
// your normal code
}
in your service than just call:
int currentActivity = getContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
.getInt("activityIdRunning",-1);