I am making a simple Android game that displaying a sequence of visual stimuli. I have two activities (Main & Settings). In the setting you will be able to edit the number of stimuli. When I edit the number it does not update at the main activity.
This is into Main activity onCreate
settings = new SettingsActivity();
setNrOfStimuli = settings.getSetNrOfStimuli();
stimuli = new int[setNrOfStimuli];
This is on Main activity
public void onSettingBtnClicked(View view) {
startActivity(new Intent(getApplicationContext(),SettingsActivity.class));
}
This is on Settings activity
public void onBackBtnClicked(View view) {
setNrOfStimuli = Integer.parseInt(inputNrOfStimuliView.getText().toString());
finish();
}
I can transfer the value of number by Intent or getter & setter but the problem is with initialization when it comes back to Main activity from Settings.
I think you should use SharedPreferences to store user's settings. You can go through this tutorial to learn about it.
https://www.javatpoint.com/android-preferences-example
You have to change this in the tutorial's code:
In prefs.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- you do not worry about how this information will be stored, it will be handled
by the android. You have to use those data by getting that data by their key -->
<EditTextPreference
android:key="stimuli_numbers"
android:summary="Please enter Number of stimuli"
android:inputType="numberDecimal"
android:digits="0123456789"
android:title="Number of stimuli" />
</PreferenceScreen>
and in your Main Activity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
//get the number of stimuli
//stimuli_numbers is the key and 0 is the default value (you can change this according to yours.
setNrOfStimuli = Integer.valueOf(prefs.getString("stimuli_numbers","0");
Related
I would like to check programmatically whether an sd card is installed, and if yes, give the user the choice to switch between external and internal storage.
I have my other static settings organized inside a preferences.xml.
It seems that I have to rewrite all the settings of the xml file in code if I start to work with preferences more dynamically.
Or is there an option to enhance the preferences from the xml with preferences from code which get used just once needed?
Thanks
Add this to manifest for install app on sd card if is possible:
android:installLocation="preferExternal">
To verify is sd card writable and readable use this method:
private boolean isExternalStorageWritable() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);}
To get folder of appfiles on sdCard (externalStorageVolumes[0] is primary folder):
File[] externalStorageVolumes =
ContextCompat.getExternalFilesDirs(getApplicationContext(), null);
Oficial documentation
I found out myself, it looks a bit clumsy, but it works.
Once again: My problem is that I have certain setting options pre configured in an xml file as described here:
Preferences with XML
Here is my preferences.xml:
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:title="#string/download_header">
<SwitchPreferenceCompat
app:key="dl_background"
app:title="#string/background_behaviour"
app:defaultValue="false"/>
<ListPreference
app:title="#string/dl_qual"
app:defaultValue="#string/low_qual"
app:key="dl_qual"
app:entries="#array/dl_qual_arry"
app:entryValues="#array/dl_qual_arry"/>
</PreferenceCategory>
<PreferenceCategory app:title="#string/tc_header">
<SwitchPreferenceCompat
app:key="tc_installed"
app:title="#string/tc_behaviour"
app:defaultValue="false"/>
<ListPreference
app:title="#string/dl_dir_root"
app:key="dl_dir_root"/>
</PreferenceCategory>
</PreferenceScreen>
Here you can define arrays which map to ListPrefrence objects.
Each option list is then populated from a resource xml file holding the actual list entries.
I used this approach for the first ListPreference "dl_qual" above.
This is the resource.xml file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="dl_qual_arry">
<item>Higher quality (128kbps)</item>
<item>Lower quality (64kbps)</item>
</string-array>
</resources>
But then I had the idea to insert a ListPreference where the values of the options list are only known at runtime.
This is my second ListPreference above "dl_dir_root".
I was too lazy to rewrite (and read how to do it in advance) the complete settings activity from code.
So I ended up with this SettingsFragment inside my SettingsActivity:
public static class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
//First, lets check whether we have initialized preferences already
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
String selectedDir = prefs.getString("dl_dir_root", "INIT");
setPreferencesFromResource(R.xml.root_preferences, rootKey);
PreferenceScreen root = getPreferenceScreen();
ListPreference dlDirRoot = root.findPreference("dl_dir_root");
CharSequence[] arryValues = BBCWorldServiceDownloaderUtils.getStoragePaths(getContext());
CharSequence[] arryEntrys = BBCWorldServiceDownloaderUtils.getStoragePaths(getContext());
dlDirRoot.setEntries(arryEntrys);
dlDirRoot.setEntryValues(arryValues);
if(selectedDir.equals("INIT")) {
//Initialize value/index
dlDirRoot.setDefaultValue(arryValues[0]);
dlDirRoot.setValueIndex(0);
}
else{
//Position at already selected value/index
dlDirRoot.setDefaultValue(selectedDir);
dlDirRoot.setValue(selectedDir);
dlDirRoot.setValueIndex(dlDirRoot.findIndexOfValue(selectedDir));
}
}
}
The pre defined xml is applied first, then the ListPreference object for "dl_dir_root" is acessed and the options are added:
ListPreference dlDirRoot = root.findPreference("dl_dir_root");
CharSequence[] arryValues = BBCWorldServiceDownloaderUtils.getStoragePaths(getContext());
CharSequence[] arryEntrys = BBCWorldServiceDownloaderUtils.getStoragePaths(getContext());
dlDirRoot.setEntries(arryEntrys);
dlDirRoot.setEntryValues(arryValues);
The rest is checking/keeping state between the calls to the activity.
If anyone knows of a more elegant way, I would be curious.
Best
Matthias
I am very new to Java. I am doing a school project at the moment and I have my main activity, then I have a settings activity. I am trying to modify the xml from the main activity with the settings activity. I am able to modify the settings xml file with the settings.java, but I would like to modify the main activity xml with settings.java
public class Settings extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
// Get the Intent that started this activity and extract the string
Switch switchButton;
final RelativeLayout mRelativeLayout = (RelativeLayout) findViewById(R.id.activity_settings);
final RelativeLayout mRelativeLayoutMain = (RelativeLayout) findViewById(R.id.activity_main);
switchButton = (Switch) findViewById(R.id.switch1);
switchButton.setChecked(true);
switchButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean bChecked) {
if (bChecked) {
mRelativeLayoutMain.setBackgroundColor(Color.GRAY);
mRelativeLayout.setBackgroundColor(Color.GRAY);
} else {
mRelativeLayoutMain.setBackgroundColor(Color.WHITE);
mRelativeLayout.setBackgroundColor(Color.WHITE);
}
}
});
if (switchButton.isChecked()) {
mRelativeLayoutMain.setBackgroundColor(Color.GRAY);
mRelativeLayout.setBackgroundColor(Color.GRAY);
} else {
mRelativeLayoutMain.setBackgroundColor(Color.WHITE);
mRelativeLayout.setBackgroundColor(Color.WHITE);
}}
public void toast1(View view) {
android.widget.Toast.makeText(this, "Created by Cody Walls and Tommy Serfas", android.widget.Toast.LENGTH_LONG).show();
}
/*public void switch1(View view) {
ScrollView mScrollView = (ScrollView) findViewById(R.id.scrollView);
mScrollView.setBackgroundColor(Color.GRAY);
}*/
}
In the Code I am trying to change the background of the main activity xml with :
mRelativeLayoutMain.setBackgroundColor(Color.GRAY);
and when I run the app and click the intent it will crash with the error:
"java.lang.NullPointerException: Attempt to invoke virtual method
'void android.widget.RelativeLayout.setBackgroundColor(int)' on a null
object reference"
I think the easiest way is to create an PreferenceManager.SharedPreferences, in which I recommend you to store current app data. This will help you not to loose any changes in app after you exit the it. Here is short instructions:
Create button in settings activity which will change something in main activity.
Create onClickListener for your button.
Use .SharedPreferences to store was you button clicked or not. (I recommend storing boolean variables, this way you can store was button clicked or not.)
I both of your activities in onCreate method call .getSharedPreferences to read saved app values. (I mean to read was the button clicked or not.)
Use app values you got from 4. to change any element in activity. (For example if you stored that button was clicked, then change some TextView text or etc.)
I hope you understood the idea.
Link to the Android developer tutorial about App key values storing & saving
Link to the StackOverflow much easier explanation & examples
There are a couple of ways of doing this (Some of which depends on how you are switching back and forth from each activity). It also depends on what things you are changing.
From your settings page, as you are changing different settings, you'll save this content within Preferences. (You can see more how to use Preferences here: https://examples.javacodegeeks.com/android/core/ui/settings/android-settings-example/ or by just Googling it).
On you main activity, depending on how you come back to it (onStart most likely), you can setup the things you need to programmatically.
So, you may need to do a little research on the Android lifecycle and how each cycle works (https://developer.android.com/guide/components/activities/activity-lifecycle.html), how to program the UI programmatically through Java (http://startandroid.ru/en/lessons/220-lesson-16-creating-layout-programmatically-layoutparams.html), and the Preferences Android library to save certain settings.
The xml isn't meant to be "altered". You can change the UI programmatically. It's possible to build an Android app without any xml. When Android was first built, it didn't use the xml to create the UI. It was all done through Java. It was then added to use xml to create your activities or fragments or any UI component. This made things easier for more static activities or activities with very little dynamic content.
I searched a lot but i did not find my answer. I have developed an android application where on the very first lunch user will be shown a welcome screen made of viewpager. The problem is i don't know which place is the best to put the welcome activity code in my application.
The simplest way it could be that in the main activity at the very fist line even before super.onCreate(), inside onCreate method where i try to get the shared preference value and then evaluate whether it is fist lunch. If it is, then i start the welcome activity as shown below
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean welcome = sharedPreferences.getBoolean(getString(R.string.key_welcome), true);
if (welcome) {
// go and start welcoming activity
Intent intent = new Intent(this, WelcomeSlideActivity.class);
startActivity(intent);
}
super.onCreate();
}
}
But i found another approach to deal with it. It is Application class. Since Application class is the first one, which runs even before any other codes in my application. So i thought, i would be nice to do it there as shown below
public class App extends Application {
#Override
public void onCreate() {
super.onCreate();
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean welcome = sharedPreferences.getBoolean(getString(R.string.key_welcome), true);
if (welcome) {
// go and start welcoming activity
Intent intent = new Intent(this, WelcomeSlideActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
}
So i am in dilemma, which one would be the best option to choose. And i am even not sure if i am doing it in the right way since there is no such documentation in android developer website or anywhere.
Have a look at how to create splash screens the correct way. https://www.bignerdranch.com/blog/splash-screens-the-right-way/
As for using the Application class - this is primarily used for Application-wide configuration for maintaining a global application state. Hence starting an activity from here does not make much sense as it's purpose has changed into becoming an entry point into the application rather than providing state for the app as a whole.
Furthermore, why not make the WelcomeSlideActivity the first 'launcher' activity? Then in there, you can create the logic of whether to launch the next activity without history or whether to show the current view.
Ideally, you should create a splash screen activity, which determines whether to show the WelcomeSlideActivity Or the MainActivity. The advantage of this is that while he app determines which Activity to launch, the user is presented with a splash screen that informs the user that the app has started
Here, I'm trying to start an activity on different devices (Android Tablet and Android Phone). Is there a way to use if statement to check which activity should to load based on the devices?
Here's my code:
Button buttonGo = (Button) findViewById(R.id.button_goToActivity);
buttonGo.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (tablet device) {
startActivity(new Intent(MainActivity.this, TabletActivity.class));
} else {
startActivity(new Intent(MainActivity.this, AndroidPhoneActivity.class));
}
});
Thanks for your effort...
In order to achieve that you must use Fragment not an Activity. the Design Philosophy of Fragments is exactly what you want. you can take a look at Example to see how it is implemented. This is a master-detail app with two Fragments, when device in a portrait mode or it is not a tablet it just shows master, otherwise it also shows detail beside the master and when you select an item from the list you will see the details without going to other Activity.
Firstly as Android Best Practice it is adviced to use Fragments rather than Activity to achieve your requirement.
But if you are keen on using Activity, then below is the solution to find device type and load different activities.
1) Have 2 values folders: values -> strings.xml and values-sw600dp -> strings.xml
2) Create string value in both the xml
<string name="device_type">PHONE</string> in values -> strings.xml
<string name="device_type">TABLET</string> in values-sw600dp -> strings.xml
3) create a method to check if current device is Phone or not
public boolean isPhone() {
String deviceType = getResource().getString(R.string.device_type);
if (deviceType.equalsIgnoreCase("PHONE") {
return true;
} else {
return false;
}
}
4) Depending on the device load your activity as you have already done in your above code snippet
Let me know if this helps...
Most likely, you should not have two separate activities here. Instead, you should have two different layouts for the same activity. The layout for phones should be in the regular res/layout folder and the layout for tablets should be in the res/layout-large folder. Read Supporting Different Screens for more details.
If you are using same fuctionality for Tablet Activity and Phone activity then you do not need two activities for this purpose. You need to make two different Layout xml for Tablet as well as Phone.
Make a Layout folder named : layout-large and layout-xlarge.
Now copy the xml file from normal layout folder and paste in both new layout folders.
No need to change the name of xml file.
Now Adjust xml file of layout-large and layot-xlarge as you want to make design for tablet.
Now on running application Tablet and phone bot will pick xml according to there size and screen density.
Note : the functionality should be same.
And if: you want to show different screen with different functionality for phone and tablet then. use this code for check.
if ((getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {
}
Hope this wll help you.
I use CheckBoxPreference in my PreferenceActivity to set a value. Later on, I want to check that value from Receiver and/or Service. findPreference() method is not available from that context. I know, that this preference value is stored in SharedPreferences anyway, but what is the key? How could I get the value of the checkbox?
I know, that this preference value is stored in SharedPreferences anyway, but what is the key?
Whatever value you have for android:key in your preference XML.
How could I get the value of the checkbox?
Call PreferenceManager.getDefaultSharedPreferences() to get the SharedPreferences, then call getBoolean() with the key you used in android:key.
In your preferences XML you'll have something like this:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference android:enabled="true"
android:title="#string/s_pref" android:key="#string/pref"
android:defaultValue="#string/d_pref"></CheckBoxPreference>
</PreferenceScreen>
Your strings.xml would have something like this:
<string name="pref">my.package.PREF</string>
<string name="s_pref">Prompt</string>
<string name="d_pref">true</string>
Your Activity's onCreate() would have something like this:
prefs = PreferenceManager.getDefaultSharedPreferences(this);
pref = prefs.getBoolean(getString(R.string.pref), true));
If you want to do something when someone changes the preferences, add an onActivityResult() to your activity and start the preferences activity with startActivityForResult(). When onActivityResult() is invoked with whatever result code you want to indicate a change in preferences, you can do another getDefaultSharedPreferences().
The shared preferences framework automatically persists the data... you don't have to actively deal with it yourself, though you can if you wish with an OnPreferenceChangeListener in the preferences activity
The only thing I would add to CommonsWare's answer is, since you mentioned a service, you can put whatever preferences the service needs to know about in its Intent extras. For example:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Intent intent = new Intent(this, MyService.class);
intent.putExtra("mypref", prefs.getString("mypref", ""));
startService(intent);
try to write this in your service
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplication());
and here specify the key that you have used in xml
if(preferences.getBoolean(your key ,true))
{
hope this help .