File picker dialog in PreferenceFragment - java

I want to get a pick file dialog in my PreferenceActivity how do I get to that? Can I override onClick for PreferenceActivity somehow? Android API 14.
Here's my PreferensActivity:
import android.preference.PreferenceActivity;
import java.util.List;
public class SettingsActivity extends PreferenceActivity {
#Override
public boolean onIsMultiPane() {
return true;
}
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.pref_head, target);
}
}
Header xml is:
<?xml version="1.0" encoding="utf-8"?>
<preference-headers
xmlns:android="http://schemas.android.com/apk/res/android">
<header
android:fragment="com.bfx.rfid.FragmentSetApp"
android:icon="#android:drawable/ic_menu_call"
android:title="Application"
android:summary="Application settings">
</header>
<header
android:fragment="com.bfx.rfid.FragmentSetConnection"
android:icon="#android:drawable/ic_menu_call"
android:title="Connectivity"
android:summary="Connection settings">
</header>
</preference-headers>
PreferenceFragment class:
import android.os.Bundle;
import android.preference.PreferenceFragment;
public class FragmentSetApp extends PreferenceFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.fragment_set_app);
}
}
PreferenceFragment xml is:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:key="work_directory"
android:title="Folder to work with">
</Preference>
<PreferenceCategory
android:title="Work with a database file">
<CheckBoxPreference
android:key="DB_default"
android:summary="Choose a default database file or pick one"
android:title="Choose a database file"
android:defaultValue="true"/>
<EditTextPreference
android:key="DB_URI"
android:title="Database file"
android:dependency="DB_default">
</EditTextPreference>
</PreferenceCategory>
</PreferenceScreen>

I don't think Andorid have a native file chooser, so you'll have to implement one yourself, or find a library.
You could then use the android:onClick property in PreferenceFragment.xml:
<EditTextPreference
android:key="DB_URI"
android:title="Database file"
android:onClick="startFileChooser"
android:dependency="DB_default">
and put this in you PreferenceFragment:
public void startFileChooser(MenuItem i){
// Start the file chooser here
}
Of course, how you would to that depends on what file chooser you decide to go with. You would probably end up with the path to the selected file, which you would insert into SharedPreference.

Related

Deprecated methods in Android Studio (AS) 1.1.0 (and Eclipse Luna) "Settings Activity"

My app could have a couple of checkboxes that I'd rather the user didn't have to re-check each time the app is chased from memory. So I've been reading about preferences.
I'm not sure I've seen anything as complicated as "a modern fragment-based PreferenceActivity", so I was looking for guidance/example from AS 1.1.0, but I got code with a total of 9 references in 4 hunks of code to addPreferencesFromResource, getPreferenceScreen, and findPreference, all of which carry this blurb:
This method was deprecated in API level 11. This function is not relevant for a modern fragment-based PreferenceActivity.
To have the code presented with deprecated code by two IDEs is one thing; that there's no indication of what each method has been replaced by is another (but there's nothing replacing it, as it happens).
Would it really be that hard for AS to produce "a modern fragment-based PreferenceActivity"? If so, I guess I'm right about the complexity.
Am I missing something? Am I supposed to just write/extend deprecated code? Turn off compiler checking of deprecated stuff?
Does anyone know of a nice tutorial for (or an example of) a simple (like two checkboxes) "modern fragment-based PreferenceActivity"? Or ANYthing that saves preferences but isn't deprecated?
I asked, "Does anyone know of a nice tutorial for (or an example of) a simple (like two checkboxes) modern fragment-based PreferenceActivity? Or ANYthing that saves preferences but isn't deprecated?"
I do as of 9pm last night. * EDITED 5/16/15 *
Here is a complete, working preferences activity, though it doesn't have all drawable, mipmap, dimens, and values folders and files. I downloaded it from advice in Sams Teach Yourself Android App Development in 24 Hours and modified it. Emphasis mine.
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.whatever.prefs"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.whatever.prefs.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.whatever.prefs.SettingsActivity"
android:label="#string/title_activity_settings" >
</activity>
</application>
</manifest>
MainActivity.java:
package com.whatever.prefs;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends Activity {
public static final String SETTINGS = "com.whatever.prefs.settings";
public static final String FIRST_USE = "com.whatever.prefs.firstUse";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* BAD IDEA--CREATES NEW SET OF PREFS
SharedPreferences preferences = getSharedPreferences(SETTINGS, MODE_PRIVATE);
Do this v v v v v v v v v v v instead! */
preferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean firstUse = preferences.getBoolean(FIRST_USE, true);
if (firstUse){
Toast helloMessage = Toast.makeText(getApplicationContext(), "Hello First Time
User",Toast.LENGTH_LONG);
helloMessage.show();
Editor editor = preferences.edit();
editor.putBoolean(FIRST_USE, false);
editor.commit();
}
else {
Toast.makeText(getApplicationContext(), "Second+ use", Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_settings:
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
SettingsFragment.java:
package com.whatever.prefs;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.util.Log;
public class SettingsFragment extends PreferenceFragment
implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().
registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().
unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
SharedPreferences sharedPref =
PreferenceManager.getDefaultSharedPreferences(getActivity());
if (key.equalsIgnoreCase("pie_type")){
Log.w("Settings", sharedPref.getString(key, ""));
}
}
}
res\menu\activity_main.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="#+id/menu_settings"
android:orderInCategory="100"
app:showAsAction="ifRoom"
android:title="#string/menu_settings"/>
</menu>
res\layout\activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Hi world" />
</RelativeLayout>
res\layout\activity_settings.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:name="com.whatever.prefs.SettingsFragment"
android:id="#+id/settings_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Hour11App</string>
<string name="hello_world">Hello world!</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_settings">Settings</string>
<string-array name="pie_array">
<item>apple</item>
<item>blueberry</item>
<item>cherry</item>
<item>coconut cream</item>
</string-array>
</resources>
styles.xml:
<resources>
<!-- Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices. -->
<style name="AppBaseTheme" parent="android:Holo.ButtonBar">
<!-- Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
</resources>
SettingsActivity.java:
package com.whatever.prefs;
import android.app.Activity;
import android.os.Bundle;
public class SettingsActivity extends Activity {
public static final String SETTINGS = "com.whatever.prefs.settings";
public static final String FIRST_USE = "com.whatever.prefs.firstUse";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
}
}
dimens.xml:
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
res\xml\preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Images">
<CheckBoxPreference
android:key="hires"
android:title="Hi-Res Images"
android:summary="Show high quality images. These take longer to load"
android:defaultValue="False" />
</PreferenceCategory>
<PreferenceCategory
android:title="Pie Info">
<CheckBoxPreference
android:key="pie"
android:title="Pie"
android:summary="Like Pie"
android:defaultValue="true" />
<ListPreference
android:dependency="pie"
android:key="pie_type"
android:title="Pie Type"
android:summary="Preferred pie type for eating"
android:dialogTitle="Type of Pie"
android:entries="#array/pie_array"
android:entryValues="#array/pie_array"
android:defaultValue="apple" />
<EditTextPreference
android:key="more_info"
android:title="More Info"
android:summary="More about pies"
android:defaultValue="" />
</PreferenceCategory>
<PreferenceScreen
android:key="second_preferencescreen"
android:title="Second Screen of Settings">
<EditTextPreference
android:key="extraA"
android:title="More Data"
android:summary="Another EditTextPreference"
android:defaultValue="" />
<EditTextPreference
android:key="ExtraB"
android:title="Even More Info"
android:summary="What more can we say"
android:defaultValue="" />
</PreferenceScreen>
</PreferenceScreen>

When i click on header, no preferences show up

I am working of settings activity for my application. I seted up two headers for preferences and then i made fragment for each header. Problem is when i click on header, nothing shows up. Thank you for your help.
Here is my preference activity
public class Preferences extends PreferenceActivity {
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.prefheads, target);
}
}
Here is first fragment
public class Prefs1 extends PreferenceFragment {
public static class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.fragment_prefs1);
}
}
}
Here is second fragment:
public class Prefs2 extends PreferenceFragment {
public static class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.fragment_prefs2);
}
}
}
XML files:
Headers
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<header
android:fragment="com.example.lubys.prefs.prefs1"
android:title="First category"
android:summary="This doesnt need summary" />
<header
android:fragment="com.example.lubys.prefs.prefs2"
android:title="Second cat"
android:summary="This is awful summary">
</header>
</preference-headers>
Fragment1:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.lubys.prefs.prefs1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<PreferenceCategory
android:title="the title"
android:key="key2">
<EditTextPreference android:title="Your Name"
android:key="username"
android:summary="Please provide your username"></EditTextPreference>
<CheckBoxPreference android:title="Application Updates"
android:defaultValue="false"
android:summary="This option if selected will allow the application to check for latest versions."
android:key="applicationUpdates" />
<ListPreference
android:title="Download Details"
android:summary="Select the kind of data that you would like to download"
android:key="downloadType"
android:defaultValue="1"
android:entries="#array/c"
android:entryValues="#array/c" />
</PreferenceCategory>
</PreferenceScreen>
Fragment2:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.lubys.prefs.prefs1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<PreferenceCategory
android:title="sms"
android:key="pref_key_storage_settings">
<CheckBoxPreference
android:key="saas"
android:summary="asde"
android:title="Something"
android:defaultValue="false"/>
</PreferenceCategory>
</PreferenceScreen>
check if u didn't get:
java.lang.RuntimeException:
Subclasses of PreferenceActivity must override isValidFragment(String) to verify that the Fragment class is valid!
XXX has not checked if fragment YYY is valid.
isValidFragment Android API 19
when android's isValidFragment() from PreferenceActivity gets called?
http://securityintelligence.com/new-vulnerability-android-framework-fragment-injection#.VRGSv1V_NBc

Preferences defaults and PreferenceActivity

Using Android Annotations. My prefs:
#SharedPref(value = SharedPref.Scope.APPLICATION_DEFAULT)
public interface MyPreferences {
#DefaultBoolean(true)
boolean myOption();
}
The preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="myOption"
android:title="My Option Name"/>
</PreferenceScreen>
My PreferencesActivity:
public class MyPreferencesActivity extends PreferenceActivity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
The problem is: in spite of the default value of myOption is true (and indeed - it is when calling MyPreferences_.myOption().get()) the checkbox in the preferences activity is unchecked by default.
The same happens for String preferences. They return default string given in #DefaultString annotation but it is not displayed in the PreferenceActivity. Only after I change the preference value from the activity, it is properly displayed.
I resolved default values duplication by:
values/preferences_defaults.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="default_myOption">true</bool>
<string name="default_myString">my string</string>
</resources>
Prefs:
#SharedPref(value = SharedPref.Scope.APPLICATION_DEFAULT)
public interface MyPreferences {
#DefaultRes(R.bool.default_myOption)
boolean myOption();
#DefaultRes(R.string.default_myString)
String myString();
}
And the preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="myOption"
android:defaultValue="#bool/default_myOption"
android:title="My Option Name"/>
<EditTextPreference
android:key="myString"
android:defaultValue="#string/default_myString"
android:title="My String Option"/>
</PreferenceScreen>
Now I can define default values for both annotations and PreferenceActivity in one XML file.

SettingsActivity/Fragment is showing options out of the layout bounderies

I have created an PreferenceActivity with a PreferenceFragment in it. But the content with all the settings is shown outside of it layout bounderies, what am I doing wrong?
SettingsActivity:
public class SettingsActivity extends PreferenceActivity {
#Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
}
public static class MyPreferenceFragment extends PreferenceFragment
{
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
}
preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="My list of Preferences">
<CheckBoxPreference android:title="Checkbox Preference"
android:defaultValue="false" android:summary="This preference can be true or false"
android:key="checkboxPref" />
<EditTextPreference android:name="EditText Preference"
android:summary="This allows you to enter a string"
android:defaultValue="Nothing" android:title="Edit This Text"
android:key="editTextPref" />
<RingtonePreference android:name="Ringtone Preference"
android:summary="Select a ringtone" android:title="Ringtones"
android:key="ringtonePref" />
<PreferenceScreen android:key="SecondPrefScreen"
android:title="Secondary Level" android:summary="This is a sub PreferenceScreen">
<intent android:action="android.intent.action.VIEW"
android:targetPackage="com.as400samplecode" android:targetClass="com.as400samplecode.Preferences2" />
</PreferenceScreen>
<Preference android:title="Custom Preference"
android:summary="This works almost like a button" android:key="customPref" />
</PreferenceCategory>
</PreferenceScreen>
I solved it by using a normal Activity instead of PreferenceActivity.
You are not code added for Preferences using SharedPreferences Class
I have adding one use your checkbox preference example check below code
public class PrefsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
//xml Preference.xml
<PreferenceCategory
android:title="PreferenceCategory A">
<CheckBoxPreference
android:key="checkbox_preference"
android:title="title_checkbox_preference"
android:summary="summary_checkbox_preference" />
</PreferenceCategory>
<PreferenceCategory
android:title="PreferenceCategory B">
<EditTextPreference
android:key="edittext_preference"
android:title="title_edittext_preference"
android:summary="summary_edittext_preference"
android:dialogTitle="dialog_title_edittext_preference" />
</PreferenceCategory>

android.view.InflateException: Binary XML file line #4: Error inflating class SwitchPreference

I'm trying to read my app preferences and I get this error:
Settings activity:
public class Settings extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
try
{
addPreferencesFromResource(R.xml.prefs);
}
catch (Exception ex)
{
Log.e("errorSettings", Log.getStackTraceString(ex));
}
}
}
Preferences XML File:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="General">
<SwitchPreference
android:title="Downloader"
android:defaultValue="true"
android:key="useDownloader"
android:summary="Enable to use" />
</PreferenceCategory>
</PreferenceScreen>
and on the application manifest I set this:
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="15" />
and the first error I get is:
android.view.InflateException: Binary XML file line #4: Error inflating class SwitchPreference
Thanx upfront.
SwitchPreference was added in API Level 14. You cannot use it on earlier versions of Android. Since you are trying to support back to API Level 9, you can either:
Use different preference XML for earlier versions, using a CheckBoxPreference instead of a SwitchPreference, or
Just use CheckBoxPreference and drop SwitchPreference for now

Categories