Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do we control an Android sync adapter preference?

In an attempt to write a custom Android sync adapter I followed this. I was success at showing an entry (Account settings) in General setting with the following code snippet from above said example.

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory android:title="General Settings" />
        <PreferenceScreen android:key="account_settings"
             android:title="Account Settings"  android:summary="Sync frequency, notifications, etc.">
             <intent android:action="fm.last.android.activity.Preferences.ACCOUNT_SETUP"
                 android:targetPackage="fm.last.android"
                 android:targetClass="fm.last.android.activity.Preferences" />
        </PreferenceScreen>
    </PreferenceCategory>
</PreferenceScreen>

The code resulted me an entry (Account Settings) in General settings:

Upon clicking the Account Settings I'm getting an error as follows and the device reboots unnecessarily.

ERROR/AndroidRuntime(30057): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

I know this error can be solved through code. Since "Account Settings" preference is XML-based code I'm stuck with the error.

  1. Can anyone help to solve the Issue?

  2. How do we control these kind of preferences through code?

like image 279
user221837 Avatar asked Mar 30 '11 12:03

user221837


2 Answers

I won't exactly answer your 2 questions, but I addressed this problem by working around it using the following 3 steps:

  1. Set up Account Preferences XML
  2. Create an activity to manage preferences
  3. Extract the account information from the "preference editing" Intent

Setting up the account preferences XML

I used an account_preferences.xml very similar to the one in the SDK sample and the c99 Last.fm application. Consider the following snippet:

<PreferenceScreen
          android:key="account_settings"
          android:title="Account Preferences"
          android:summary="Misc account preferences">
          <intent
              android:action="some.unique.action.name.account.EDIT"
              android:targetPackage="com.example.preferences"
              android:targetClass="com.example.preferences.PreferencesActivity">
          </intent>
</PreferenceScreen>

Given this, here are some of the important points I've found: (Note that I've found these through experimentation and not through any specific Android documentation -- if future readers of this question have those references, it'd be great to link those in.)

  • The android:key for this PreferenceScreen must be "account_settings" or Android will not find & display your preferences
  • By using an explicit Intent and specifying the targetPackage and targetClass, android will start your Activity directly and you don't need to worry about an Intent filter.
  • Android stores the Account object for the currently selected account in this Intent's Extras -- which is very important on the receiving end so you can know which account you're managing. More on this below.

Creating the preference managing Activity

Next I created an Activity to correspond to the package and class specified in the above XML. Note that as far as I can tell, the choice of Activity is up to you -- it's most common to subclass android.preference.PreferenceActivity but I've also subclassed Activity directly. Standard Activity development guidelines apply here...

Getting the Account from the "preference editing" Intent

When your Activity starts up, you can extract the corresponding Account object from the Extras Bundle (using this.getIntent().getExtras()) and the key "account". Recall that this Intent will be the one that you specified in preferences XML file initially. (Again, I could not find doc on this so found it by dumping the contents of the Extras Bundle passed in with my Intent.) Once you have the Account, it should be straightforward to load/save preferences for that account using SharedPreferences, your database, or whatever other method you prefer.

Hope that helps...

like image 126
James Avatar answered Nov 09 '22 15:11

James


The files/resources refered to above in the are not in the stand alone package : this is the only thing the author forgot to adapt i guess : you have to create your own preference class . here is my class :

public class AccountPreferences extends PreferenceActivity {
public static final String TAG = "AccountPreferences";
private boolean shouldForceSync = false;

@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    Log.i(TAG, "onCreate");
    addPreferencesFromResource(R.xml.preferences_resources);

@Override
public void onPause() {
    super.onPause();
    if (shouldForceSync) {
        AccountAuthenticatorService.resyncAccount(this);
    }
}

Preference.OnPreferenceChangeListener syncToggle = new Preference.OnPreferenceChangeListener() {
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        shouldForceSync = true;
        return true;
    }
};

and here is the preferences file : preferences_resources.xml

    <PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/privacy_preferences">

    <CheckBoxPreference
        android:key="privacy_contacts"
        android:defaultValue="true"
        android:summary="@string/privacy_contacts_summary" android:title="@string/privacy_contacts_title"/>
</PreferenceCategory>

<PreferenceCategory android:title="@string/outgoing_preferences">

    <CheckBoxPreference
        android:key="allow_mail"
        android:defaultValue="true"
        android:summary="@string/allow_mail" android:title="@string/allow_mail_text"/>

</PreferenceCategory>

you will have to adapt those, or have a deeper look at the files in his last.fm project.

hope this helps, good luck.

like image 22
olamotte Avatar answered Nov 09 '22 15:11

olamotte