1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.contacts.util; 18 19 import android.accounts.AccountManager; 20 import android.accounts.AuthenticatorDescription; 21 import android.content.Context; 22 import android.content.pm.PackageManager; 23 import android.content.pm.PackageManager.NameNotFoundException; 24 import android.content.res.Resources; 25 import android.content.res.Resources.NotFoundException; 26 import android.content.res.TypedArray; 27 import android.content.res.XmlResourceParser; 28 import android.util.AttributeSet; 29 import android.util.Xml; 30 31 import com.android.contacts.R; 32 import com.android.contacts.model.account.ExternalAccountType; 33 34 import org.xmlpull.v1.XmlPullParser; 35 import org.xmlpull.v1.XmlPullParserException; 36 37 import java.io.IOException; 38 39 /** 40 * Retrieves localized names per account type. This allows customizing texts like 41 * "All Contacts" for certain account types, but e.g. "All Friends" or "All Connections" for others. 42 */ 43 public class LocalizedNameResolver { 44 private static final String TAG = "LocalizedNameResolver"; 45 46 private static final String CONTACTS_DATA_KIND = "ContactsDataKind"; 47 48 /** 49 * Returns the name for All Contacts for the specified account type. 50 */ getAllContactsName(Context context, String accountType)51 public static String getAllContactsName(Context context, String accountType) { 52 if (context == null) throw new IllegalArgumentException("Context must not be null"); 53 if (accountType == null) return null; 54 55 return resolveAllContactsName(context, accountType); 56 } 57 58 /** 59 * Finds "All Contacts"-Name for the specified account type. 60 */ resolveAllContactsName(Context context, String accountType)61 private static String resolveAllContactsName(Context context, String accountType) { 62 final AccountManager am = AccountManager.get(context); 63 64 for (AuthenticatorDescription auth : am.getAuthenticatorTypes()) { 65 if (accountType.equals(auth.type)) { 66 return resolveAllContactsNameFromMetaData(context, auth.packageName); 67 } 68 } 69 70 return null; 71 } 72 73 /** 74 * Finds the meta-data XML containing the contacts configuration and 75 * reads the picture priority from that file. 76 */ resolveAllContactsNameFromMetaData(Context context, String packageName)77 private static String resolveAllContactsNameFromMetaData(Context context, String packageName) { 78 final XmlResourceParser parser = ExternalAccountType.loadContactsXml(context, packageName); 79 if (parser != null) { 80 return loadAllContactsNameFromXml(context, parser, packageName); 81 } 82 return null; 83 } 84 loadAllContactsNameFromXml(Context context, XmlPullParser parser, String packageName)85 private static String loadAllContactsNameFromXml(Context context, XmlPullParser parser, 86 String packageName) { 87 try { 88 final AttributeSet attrs = Xml.asAttributeSet(parser); 89 int type; 90 while ((type = parser.next()) != XmlPullParser.START_TAG 91 && type != XmlPullParser.END_DOCUMENT) { 92 // Drain comments and whitespace 93 } 94 95 if (type != XmlPullParser.START_TAG) { 96 throw new IllegalStateException("No start tag found"); 97 } 98 99 final int depth = parser.getDepth(); 100 while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 101 && type != XmlPullParser.END_DOCUMENT) { 102 String name = parser.getName(); 103 if (type == XmlPullParser.START_TAG && CONTACTS_DATA_KIND.equals(name)) { 104 final TypedArray typedArray = context.obtainStyledAttributes(attrs, 105 R.styleable.ContactsDataKind); 106 try { 107 // See if a string has been hardcoded directly into the xml 108 final String nonResourceString = typedArray.getNonResourceString( 109 R.styleable.ContactsDataKind_android_allContactsName); 110 if (nonResourceString != null) { 111 return nonResourceString; 112 } 113 114 // See if a resource is referenced. We can't rely on getString 115 // to automatically resolve it as the resource lives in a different package 116 int id = typedArray.getResourceId( 117 R.styleable.ContactsDataKind_android_allContactsName, 0); 118 if (id == 0) return null; 119 120 // Resolve the resource Id 121 final PackageManager packageManager = context.getPackageManager(); 122 final Resources resources; 123 try { 124 resources = packageManager.getResourcesForApplication(packageName); 125 } catch (NameNotFoundException e) { 126 return null; 127 } 128 try { 129 return resources.getString(id); 130 } catch (NotFoundException e) { 131 return null; 132 } 133 } finally { 134 typedArray.recycle(); 135 } 136 } 137 } 138 return null; 139 } catch (XmlPullParserException e) { 140 throw new IllegalStateException("Problem reading XML", e); 141 } catch (IOException e) { 142 throw new IllegalStateException("Problem reading XML", e); 143 } 144 } 145 } 146