开发者

Account preferences crashes on ListPreference

I have created an account type using the AccountAuthenticator stuff as done in the SampleSyncAdapter tutorial. I am now trying to get account preferences working.

I have added the line android:accountPreferences="@xml/account_preferences" to my account-authenticator and account_preferences.xml looks like so:

<?xml version="1.0" encoding="utf-8"?>

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

<CheckBoxPreference
    android:key="sync_alum"
    android:title="@string/sync_alum"
    android:sum开发者_如何学CmaryOn="@string/sync_alum_check"
    android:summaryOff="@string/sync_alum_nocheck"/>

<ListPreference
    android:key="sync_alum_since"
    android:title="@string/alum_years"
    android:entries="@array/years"
    android:entryValues="@array/years"
    android:dependency="sync_alum"/>
</PreferenceScreen>

The checkbox preference works exactly like it should but the ListPreference crashes the entire system with the following message:

05-14 22:32:16.794: ERROR/AndroidRuntime(63): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application

I get the same error with EditTextPreference and with the custom subclass of DialogPreference I created.


I've finally managed to successfully launch my custom preferences activity. The pit fall was that you have to keep the following XML layout (like above):

<PreferenceScreen
   xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
   android:title="Account settings" />
<PreferenceScreen
   android:key="key"
   android:title="General settings"
   android:summary="Some summary">

   <!-- package relative class name-->
   <intent
      android:action="my.account.preference.MAIN"          
      android:targetClass="prefs.AccountPreferencesActivity.class">
   </intent>          
</PreferenceScreen>
</PreferenceScreen>

And the according AndroidManifest.xml entry:

<activity
   android:label="Account preferences"
   android:name=".prefs.AccountPreferencesActivity">
   <intent-filter>
      <action
         android:name="my.account.preference.MAIN" />
      <category
         android:name="android.intent.category.DEFAULT" />
    </intent-filter>
 </activity>

If you look in the Android code you can find the following lines of code:

    private void updatePreferenceIntents(PreferenceScreen prefs) {
    for (int i = 0; i < prefs.getPreferenceCount(); i++) {
        Intent intent = prefs.getPreference(i).getIntent();
        if (intent != null) {
            intent.putExtra(ACCOUNT_KEY, mAccount);
            // This is somewhat of a hack. Since the preference screen we're accessing comes
            // from another package, we need to modify the intent to launch it with
            // FLAG_ACTIVITY_NEW_TASK.
            // TODO: Do something smarter if we ever have PreferenceScreens of our own.
            intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
        }
    }
}

and these add the flag to the Intent specified in XML. But this only works for all 1st grade children of the PreferenceScreen. My fault was I encapsulated my Intent in the PreferenceCategory and so the flag was never OR-ed.

Hope I could help.


I've got the very same issue and ran into the same Exception mentioned above. After looking into the Android source it seems to be the case that this happens to every preference that wants to create a dialog or new window. This seems to be created as APPLICATION_WINDOW what is wrong.

In the docs to AbstractAccountAuthenticator the example uses an intent on click.

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/title_fmt" />
<PreferenceScreen
     android:key="key1"
     android:title="@string/key1_action"
     android:summary="@string/key1_summary">
     <intent
         android:action="key1.ACTION"
         android:targetPackage="key1.package"
         android:targetClass="key1.class" />
 </PreferenceScreen>

I think the intention is to launch a new preference activity from the account preferences and not use them in place. The bad thing is this let pop up a new Exception:

 10-01 09:33:36.935: ERROR/AndroidRuntime(52): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

The big question is how to give the intent the flag? I've seen no way to set intent flags by XML. I've already created my own preference and launch the intent during onClick(). But it seems that the account preferences are launched in the account & sync settings context and the classloader cannot find my class.

I see two solutions here:

  1. Set the flags to the intent.
  2. Subclass Preference and handle onClick() to launch your activity. But how to publish my own class?


Yes this is seems to be a bug. There are some bugs against it at Google.

I can confirm the same issue with Edit and List preferences. So far I can only get CheckBox to work without crashing. The state is persistent but I have no idea where the state is stored.


For grins, try nuking your PreferenceCategory. It's not doing you much good as-is anyway, since it's not wrapping any preferences. I doubt this is your problem, but it's the only thing odd I see with the XML.

Otherwise, that exception screans "Android bug" to me, so if you can create a project that reproduces the error, post it and this info to http://b.android.com.


Maybe it's because you're using the same array? for your entries as your entryValues?

try making another array and trying

android:entries="@array/years"
android:entryValues="@array/years_values"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜