I implemented night mode in my app.User can change the night mode settings in profile activity.The order of activities are as follows.
TabbedActivity>>DisplayActivity,ProfileActivity
The changed settings are applied only in current activity.(i.e profile activity).If the user presses back button,changes are not applied to that activities.Anyone help me to apply changes to all the activites.When we close the app and open again.changes are applied.But back press doesn't work.
This is the code I am using.
#Override
protected void onCreate(Bundle savedInstanceState) {
final SharedPreferences sharedPreferences =
getSharedPreferences("NIGHT_MODE", MODE_PRIVATE);
int result=sharedPreferences.getInt("NIGHT_MODE_OPTION",0);
if (result==2){
setTheme(R.style.darkTheme);
}else setTheme(R.style.AppTheme);
loadLocale();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
final SharedPreferences.Editor editor = getSharedPreferences("NIGHT_MODE", MODE_PRIVATE).edit();
if (result==2){
night.setChecked(true);
}
night.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
editor.putInt("NIGHT_MODE_OPTION",AppCompatDelegate.MODE_NIGHT_YES);
editor.apply();
startActivity(getIntent());
}else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
editor.putInt("NIGHT_MODE_OPTION",AppCompatDelegate.MODE_NIGHT_NO);
editor.apply();
startActivity(getIntent());
}
}
});
}
Since you are not considering Android lifecycle. You configure everything inside onCreate. However, while switching between activities current activity's lifecycle change accordingly. Here is lifecycle is explained very well
Solution:
When you come back to the previous activity, onResume is called. You should apply all changes inside this method
override fun onResume() {
super.onResume()
//Read your settings from SharedPrefs then apply, here
}
'i think the better practice would to restart/reset app everytime the theme is changed'
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
finish();
Related
Below is my code to the MainActivity.java of my project, this is the welcome like screen for my app and should only appear first time user opens the app. Otherwise the user should get to see the Medicine_Activity.java which is also triggered when the user presses "Get Started" button on MainActivity. In order to implement this i came across something known as SharedPreferences and tried to implement it. But it isnt working quite as expected, the MainActivity flashes for a second before Medicine_Activity is launched. I am new so please help me out
Here is a video clip to view this bug in action - https://www.dropbox.com/s/fqbo9urb6xnh3pd/WhatsApp%20Video%202019-06-20%20at%202.12.50%20PM.mp4?dl=0
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button btnGetStarted;
#Override
protected void onCreate(Bundle savedInstanceState) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
boolean previouslyStarted = prefs.getBoolean(getString(R.string.pref_previously_started), false);
if(!previouslyStarted) {
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(getString(R.string.pref_previously_started), Boolean.TRUE);
edit.apply();
} else{
Intent intent = new Intent(this, Medicine_Activity.class);
startActivity(intent);
}
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //will hide the title
getSupportActionBar().hide(); // hide the title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); //enable full screen
setContentView(R.layout.activity_main);
Button btnGetStarted = findViewById(R.id.btnGetStarted);
btnGetStarted.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Intent intent = new Intent(this, Medicine_Activity.class);
startActivity(intent);
}
}
Use commit() while storing the true and finish() the MainActivity.
if(!previouslyStarted) {
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(getString(R.string.pref_previously_started), true);
edit.commit();
} else{
Intent intent = new Intent(this, Medicine_Activity.class);
startActivity(intent);
finish();
}
A short explanation: commit() writes the data synchronously (blocking the thread its called from). It then informs you about the success of the operation. However, apply() schedules the data to be written asynchronously. It does not inform you about the success of the operation.
Quoting from Documentation:
Unlike commit(), which writes its preferences out to persistent storage synchronously, apply() commits its changes to the in-memory SharedPreferences immediately but starts an asynchronous commit to disk and you won't be notified of any failures
MyApp testing is multi language change. http://www.androhub.com/android-building-multi-language-supported-app/ After I choose radio button, it changes language in current activity. But when I go back previous activity, it doesn't change language. So, I want to recall onCreate when I click back button. Or How to refresh current activity?
onCreate ()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
txt = (TextView) findViewById(R.id.txt);
radioGroup = (RadioGroup) findViewById(R.id.radioGroup);
radioEng = (RadioButton) findViewById(R.id.eng);
radiohi = (RadioButton) findViewById(R.id.hi);
// Initialization
pref = getSharedPreferences("MyPref", Activity.MODE_PRIVATE);
editor = pref.edit();
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, #IdRes int i) {
String lang = "en"; // Default Language
switch (i) {
case R.id.eng:
lang = "en";
break;
case R.id.hi:
lang = "hi";
break;
default:
break;
}
changeLocale(lang); // Change Locale on selection basis
}
});
loadLocale();
}
changeLocale
private void changeLocale(String lang) {
if (lang.equalsIgnoreCase(""))
return;
Locale myLocale = new Locale(lang); // Set Selected Locale
saveLocale(lang); // Save the selected locale
Locale.setDefault(myLocale); // set new locale as default
Configuration config = new Configuration(); // get Configuration
config.locale = myLocale; // set config locale as selected locale
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); // Update the config
}
saveLocale & loadLocale
private void saveLocale(String lang) {
editor.putString("save", lang);
editor.commit();
if (lang.equals("en")) {
radioEng.setChecked(true);
} else {
radiohi.setChecked(true);
}
}
private void loadLocale() {
String lang = pref.getString("save", "");
if (lang.equals("")) {
radioEng.setChecked(true);
} else {
changeLocale(lang);
}
}
give resultCode when back from current activity, or save configuration, then check configuration on activity resume for language change
I think you should finish the previous activity and recreate it, you can use LocalBroadcast.
You can call onCreate method on back press by handling back press event.
#Override
public void onBackPressed() {
onCreate(new Bundle());
}
If you are using API 11 then use below code and also if above code doesn't work.
Intent intent = getIntent();
finish();
startActivity(intent);
While using the recreate method works by doing
this.recreate()
It was only added in API level 11. If you want to include more devices you can check the API level and implement both the recreate method as well as
Intent intent = getIntent();
finish();
startActivity(intent);
You can use both by making an if statement like...
if (android.os.Build.VERSION.SDK_INT >= 11){
//Code for recreate
recreate();
}else{
//Code for Intent
Intent intent = getIntent();
finish();
startActivity(intent);
}
Intent intent=new Intent(Current_Activity.this,Current_Activity.class);
startActivity(intent);
finish();
instantiate a new intent in your onBackPressed()
Since you are using two activities when you create intent from first activity to second activity the first activity onStop() is called and activity is put to back stack.When you press back button the first activity onCreate() is not called again but onResume() is called and activity is resumed.
So the logic that your are trying to should be done in onResume() such that it will be called every time when you press back button.For more reference check this.
https://developer.android.com/guide/components/activities/activity-lifecycle.html
MainActivity in my app has launchMode set to singleTask. If I start ActivityB from MainActivity, then put app to background and start my app from applications screen it does not resume correctly. ActivityB automatically finishes and MainActivity resumes. I expect ActivityB to resume instead. Why is this happening and what could I do to make it work normally? It works OK without singleTask flag but I need that flag for other purposes.
By the way, my app resumes correctly from recent apps screen.
Use the following code in the LAUNCHER Activities.
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isTaskRoot()) {
finish();
return;
}
// Rest of your onCreate code goes here
}
Activity B is closed because it launched from Activity A, this is normal behavior for android because Activity A needs to be restarted (singleTask) and all related instance will be kill/finish.
So, what you can do is implement shared-preference.
your activity A should be like this :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//// read share preference
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger("MYSHARE_PRFERENCE");
int isOpened = sharedPref.getInt("IS_ACTIVITY_B_ALREADY_OPENED", defaultValue);
if (isOpened == 1)
{
//resume activity B
startActivity(new Intent(MainActivity.this, ActivityB.class));
}
////
findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this, ActivityB.class));
//// write on share preference
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("IS_ACTIVITY_B_ALREADY_OPENED", 1);
editor.commit();
////
}
});
}
}
P.S : I didn't compile it yet, the code might be error on compile. But share preference can be solution for your problem.
My question is "Is there any way to save state of activity, that can be used when application has been restart.".
In my application, I had been override onSaveInstanceState and onRestoreInstanceState to save and restore my instance state.
I also used SharedPreferences to save the state. But I found that SharedPreference has been clear when I pressed Back Buttaon and restart my application.
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
SharedPreferences pref = getSharedPreferences(MY_APP, MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString(USER_NAME, name.getText().toString());
editor.putInt(COUNT_STATE, count);
editor.commit();
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
SharedPreferences pref = getSharedPreferences(MY_APP, MODE_PRIVATE);
name.setText(pref.getString(USER_NAME, ""));
count = pref.getInt(COUNT_STATE, 0);
}
I also know that this problem has been solved if I used external or local storage.
I want to know that can I persist application state without using file or database.
at onBackPressed() you need to store your state
and when activity created onCreate() you need to restore it
private void saveMyState(){
SharedPreferences pref = getSharedPreferences(MY_APP, MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString(USER_NAME, name.getText().toString());
editor.putInt(COUNT_STATE, count);
editor.commit();
}
private restoreMyState(){
SharedPreferences pref = getSharedPreferences(MY_APP, MODE_PRIVATE);
name.setText(pref.getString(USER_NAME, ""));
count = pref.getInt(COUNT_STATE, 0);
}
#Override
public void onBackPressed() {
saveMyState();
super.onBackPressed();
}
#Override
public void onCreate(Bundle savedInstanceState){
//init views, buttons, textViews (findViewById)...
//do other works ...
//:
//:
//then try to restore state (if saved)
restoreMyState();
}
if you want you can do the same call saveMyState() and restoreMyState() at
onSaveInstanceState() and onRestoreInstanceState() in case of orientation changed
i think this will cover all the cases you want.
PS: using SharedPreferences will write/read to a file, under the hood so you are already using file if you are using SharedPreferences
For my question, I try to change behavior of Pressed Back Button by overring onBackPressed.
In this method I write moveToBackTask(true).
#Override
public void onBackPressed() {
moveTaskToBack(true);
}
My application state has been restored when I pressed back button and restart application.
But I think that this state can't be restored when I restart my device.
Do I need to store my state in a file?
I want my app to start a activity only the first time the app launches.
Any one got any idea?
I found this but it only shows a black screen.
public class WhatsNew extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";
protected void onCreate(Bundle state){
super.onCreate(state);
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean dialogShown = settings.getBoolean("dialogShown", false);
if (!dialogShown) {
// AlertDialog code here
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("dialogShown", true);
editor.commit();
}
}
}
When the app launches, set a flag in the activity preferences that the activity has already run. Default your setting to false, and then only start that activity if the flag isn't set. Note that if the user cleans your application data, or uninstalls it and later installs it again the activity would show again.
I think that you talk about activities like "log" page that you would launch only once in your application's whole life.
For this, you can use sharedPreferences:
SharedPreferences prefs;
SharedPreferences.Editor editor;
and below your startActivity(intent), you add:
prefs = getSharedPreferences("nbRepet",Context.MODE_PRIVATE);
editor = prefs.edit();
editor.putInt("nbRepet", 1);
editor.commit();
Now your variable nbRepet have 1 as value.
After that, you can add these lines ABOVE your startActivity(intent) to verify that your activity was never launched before:
//here you recover nbRepet's value..
preferences = MainActivity.this.getSharedPreferences("nbRepet", MODE_PRIVATE);
int value = preferences.getInt("nbRepet", 0);
//.. and you verify if your activity is launched before.
if(value<1)
{
startActivity(intent);
}
You will need an Activity which checks a persisted boolean. ie,
onCreate(Bundle bundle)
{
boolean firstRun = // persistance method here
Intent toForward;
if(firstRun)
// Create an intent to start you "only once" activity
// persist "firstRun" as false;
else
// Create an intent for your usual startup
startActivity(toForward);
finish();
}
this will do the job for you
package com.example.startup;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main); //we don't need this line
SharedPreferences settings=getSharedPreferences("prefs",0);
boolean firstRun=settings.getBoolean("firstRun",false);
if(firstRun==false)//if running for first time
{
SharedPreferences.Editor editor=settings.edit();
editor.putBoolean("firstRun",true);
editor.commit();
Intent i=new Intent(MainActivity.this,Second.class);//Activity to be launched For the First time
startActivity(i);
finish();
}
else
{
Intent a=new Intent(MainActivity.this,Main.class);//Default Activity
startActivity(a);
finish();
}
}
}
Depends on what "first time" means. Easiest way is to put some flag into the SharedPreferences... but that can stay around for a while. ^^
If you mean that onCreate should be invoked only once when "start only once when app is launched", you could set the launchMode of the acitivty to singleInstance or singleTask in the manifest.
See my answer in this post, regarding this same issue.
I recommend checking the SharedPreference value for whether the app has previously been ran, inside of the onResume().