Mega Code Archive

 
Categories / Android / Core Class
 

Contact Manager

//src\com\example\android\contactmanager\ContactAdder.java /*  * Copyright (C) 2009 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ package com.example.android.contactmanager; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AuthenticatorDescription; import android.accounts.OnAccountsUpdateListener; import android.app.Activity; import android.content.ContentProviderOperation; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.provider.ContactsContract; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemSelectedListener; import java.util.ArrayList; import java.util.Iterator; public final class ContactAdder extends Activity implements OnAccountsUpdateListener {     public static final String TAG = "ContactsAdder";     public static final String ACCOUNT_NAME =             "com.example.android.contactmanager.ContactsAdder.ACCOUNT_NAME";     public static final String ACCOUNT_TYPE =             "com.example.android.contactmanager.ContactsAdder.ACCOUNT_TYPE";     private ArrayList<AccountData> mAccounts;     private AccountAdapter mAccountAdapter;     private Spinner mAccountSpinner;     private EditText mContactEmailEditText;     private ArrayList<Integer> mContactEmailTypes;     private Spinner mContactEmailTypeSpinner;     private EditText mContactNameEditText;     private EditText mContactPhoneEditText;     private ArrayList<Integer> mContactPhoneTypes;     private Spinner mContactPhoneTypeSpinner;     private Button mContactSaveButton;     private AccountData mSelectedAccount;     /**      * Called when the activity is first created. Responsible for initializing the UI.      */     @Override     public void onCreate(Bundle savedInstanceState)     {         Log.v(TAG, "Activity State: onCreate()");         super.onCreate(savedInstanceState);         setContentView(R.layout.contact_adder);         // Obtain handles to UI objects         mAccountSpinner = (Spinner) findViewById(R.id.accountSpinner);         mContactNameEditText = (EditText) findViewById(R.id.contactNameEditText);         mContactPhoneEditText = (EditText) findViewById(R.id.contactPhoneEditText);         mContactEmailEditText = (EditText) findViewById(R.id.contactEmailEditText);         mContactPhoneTypeSpinner = (Spinner) findViewById(R.id.contactPhoneTypeSpinner);         mContactEmailTypeSpinner = (Spinner) findViewById(R.id.contactEmailTypeSpinner);         mContactSaveButton = (Button) findViewById(R.id.contactSaveButton);         // Prepare list of supported account types         // Note: Other types are available in ContactsContract.CommonDataKinds         //       Also, be aware that type IDs differ between Phone and Email, and MUST be computed         //       separately.         mContactPhoneTypes = new ArrayList<Integer>();         mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_HOME);         mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_WORK);         mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);         mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_OTHER);         mContactEmailTypes = new ArrayList<Integer>();         mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_HOME);         mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_WORK);         mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_MOBILE);         mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_OTHER);         // Prepare model for account spinner         mAccounts = new ArrayList<AccountData>();         mAccountAdapter = new AccountAdapter(this, mAccounts);         mAccountSpinner.setAdapter(mAccountAdapter);         // Populate list of account types for phone         ArrayAdapter<String> adapter;         adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);         Iterator<Integer> iter;         iter = mContactPhoneTypes.iterator();         while (iter.hasNext()) {             adapter.add(ContactsContract.CommonDataKinds.Phone.getTypeLabel(                     this.getResources(),                     iter.next(),                     getString(R.string.undefinedTypeLabel)).toString());         }         mContactPhoneTypeSpinner.setAdapter(adapter);         mContactPhoneTypeSpinner.setPrompt(getString(R.string.selectLabel));         // Populate list of account types for email         adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);         iter = mContactEmailTypes.iterator();         while (iter.hasNext()) {             adapter.add(ContactsContract.CommonDataKinds.Email.getTypeLabel(                     this.getResources(),                     iter.next(),                     getString(R.string.undefinedTypeLabel)).toString());         }         mContactEmailTypeSpinner.setAdapter(adapter);         mContactEmailTypeSpinner.setPrompt(getString(R.string.selectLabel));         // Prepare the system account manager. On registering the listener below, we also ask for         // an initial callback to pre-populate the account list.         AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);         // Register handlers for UI elements         mAccountSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {             public void onItemSelected(AdapterView<?> parent, View view, int position, long i) {                 updateAccountSelection();             }             public void onNothingSelected(AdapterView<?> parent) {                 // We don't need to worry about nothing being selected, since Spinners don't allow                 // this.             }         });         mContactSaveButton.setOnClickListener(new View.OnClickListener() {             public void onClick(View v) {                 onSaveButtonClicked();             }         });     }     /**      * Actions for when the Save button is clicked. Creates a contact entry and terminates the      * activity.      */     private void onSaveButtonClicked() {         Log.v(TAG, "Save button clicked");         createContactEntry();         finish();     }     /**      * Creates a contact entry from the current UI values in the account named by mSelectedAccount.      */     protected void createContactEntry() {         // Get values from UI         String name = mContactNameEditText.getText().toString();         String phone = mContactPhoneEditText.getText().toString();         String email = mContactEmailEditText.getText().toString();         int phoneType = mContactPhoneTypes.get(                 mContactPhoneTypeSpinner.getSelectedItemPosition());         int emailType = mContactEmailTypes.get(                 mContactEmailTypeSpinner.getSelectedItemPosition());;         // Prepare contact creation request         //         // Note: We use RawContacts because this data must be associated with a particular account.         //       The system will aggregate this with any other data for this contact and create a         //       coresponding entry in the ContactsContract.Contacts provider for us.         ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();         ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)                 .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType())                 .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName())                 .build());         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)                 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)                 .withValue(ContactsContract.Data.MIMETYPE,                         ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)                 .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)                 .build());         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)                 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)                 .withValue(ContactsContract.Data.MIMETYPE,                         ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)                 .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)                 .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType)                 .build());         ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)                 .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)                 .withValue(ContactsContract.Data.MIMETYPE,                         ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)                 .withValue(ContactsContract.CommonDataKinds.Email.DATA, email)                 .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType)                 .build());         // Ask the Contact provider to create a new contact         Log.i(TAG,"Selected account: " + mSelectedAccount.getName() + " (" +                 mSelectedAccount.getType() + ")");         Log.i(TAG,"Creating contact: " + name);         try {             getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);         } catch (Exception e) {             // Display warning             Context ctx = getApplicationContext();             CharSequence txt = getString(R.string.contactCreationFailure);             int duration = Toast.LENGTH_SHORT;             Toast toast = Toast.makeText(ctx, txt, duration);             toast.show();             // Log exception             Log.e(TAG, "Exceptoin encoutered while inserting contact: " + e);         }     }     /**      * Called when this activity is about to be destroyed by the system.      */     @Override     public void onDestroy() {         // Remove AccountManager callback         AccountManager.get(this).removeOnAccountsUpdatedListener(this);         super.onDestroy();     }     /**      * Updates account list spinner when the list of Accounts on the system changes. Satisfies      * OnAccountsUpdateListener implementation.      */     public void onAccountsUpdated(Account[] a) {         Log.i(TAG, "Account list update detected");         // Clear out any old data to prevent duplicates         mAccounts.clear();         // Get account data from system         AuthenticatorDescription[] accountTypes = AccountManager.get(this).getAuthenticatorTypes();         // Populate tables         for (int i = 0; i < a.length; i++) {             // The user may have multiple accounts with the same name, so we need to construct a             // meaningful display name for each.             String systemAccountType = a[i].type;             AuthenticatorDescription ad = getAuthenticatorDescription(systemAccountType,                     accountTypes);             AccountData data = new AccountData(a[i].name, ad);             mAccounts.add(data);         }         // Update the account spinner         mAccountAdapter.notifyDataSetChanged();     }     /**      * Obtain the AuthenticatorDescription for a given account type.      * @param type The account type to locate.      * @param dictionary An array of AuthenticatorDescriptions, as returned by AccountManager.      * @return The description for the specified account type.      */     private static AuthenticatorDescription getAuthenticatorDescription(String type,             AuthenticatorDescription[] dictionary) {         for (int i = 0; i < dictionary.length; i++) {             if (dictionary[i].type.equals(type)) {                 return dictionary[i];             }         }         // No match found         throw new RuntimeException("Unable to find matching authenticator");     }     /**      * Update account selection. If NO_ACCOUNT is selected, then we prohibit inserting new contacts.      */     private void updateAccountSelection() {         // Read current account selection         mSelectedAccount = (AccountData) mAccountSpinner.getSelectedItem();     }     /**      * A container class used to repreresent all known information about an account.      */     private class AccountData {         private String mName;         private String mType;         private CharSequence mTypeLabel;         private Drawable mIcon;         /**          * @param name The name of the account. This is usually the user's email address or          *        username.          * @param description The description for this account. This will be dictated by the          *        type of account returned, and can be obtained from the system AccountManager.          */         public AccountData(String name, AuthenticatorDescription description) {             mName = name;             if (description != null) {                 mType = description.type;                 // The type string is stored in a resource, so we need to convert it into something                 // human readable.                 String packageName = description.packageName;                 PackageManager pm = getPackageManager();                 if (description.labelId != 0) {                     mTypeLabel = pm.getText(packageName, description.labelId, null);                     if (mTypeLabel == null) {                         throw new IllegalArgumentException("LabelID provided, but label not found");                     }                 } else {                     mTypeLabel = "";                 }                 if (description.iconId != 0) {                     mIcon = pm.getDrawable(packageName, description.iconId, null);                     if (mIcon == null) {                         throw new IllegalArgumentException("IconID provided, but drawable not " +                                 "found");                     }                 } else {                     mIcon = getResources().getDrawable(android.R.drawable.sym_def_app_icon);                 }             }         }         public String getName() {             return mName;         }         public String getType() {             return mType;         }         public CharSequence getTypeLabel() {             return mTypeLabel;         }         public Drawable getIcon() {             return mIcon;         }         public String toString() {             return mName;         }     }     /**      * Custom adapter used to display account icons and descriptions in the account spinner.      */     private class AccountAdapter extends ArrayAdapter<AccountData> {         public AccountAdapter(Context context, ArrayList<AccountData> accountData) {             super(context, android.R.layout.simple_spinner_item, accountData);             setDropDownViewResource(R.layout.account_entry);         }         public View getDropDownView(int position, View convertView, ViewGroup parent) {             // Inflate a view template             if (convertView == null) {                 LayoutInflater layoutInflater = getLayoutInflater();                 convertView = layoutInflater.inflate(R.layout.account_entry, parent, false);             }             TextView firstAccountLine = (TextView) convertView.findViewById(R.id.firstAccountLine);             TextView secondAccountLine = (TextView) convertView.findViewById(R.id.secondAccountLine);             ImageView accountIcon = (ImageView) convertView.findViewById(R.id.accountIcon);             // Populate template             AccountData data = getItem(position);             firstAccountLine.setText(data.getName());             secondAccountLine.setText(data.getTypeLabel());             Drawable icon = data.getIcon();             if (icon == null) {                 icon = getResources().getDrawable(android.R.drawable.ic_menu_search);             }             accountIcon.setImageDrawable(icon);             return convertView;         }     } } //src\com\example\android\contactmanager\ContactManager.java /*  * Copyright (C) 2009 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ package com.example.android.contactmanager; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ListView; import android.widget.SimpleCursorAdapter; public final class ContactManager extends Activity {     public static final String TAG = "ContactManager";     private Button mAddAccountButton;     private ListView mContactList;     private boolean mShowInvisible;     private CheckBox mShowInvisibleControl;     /**      * Called when the activity is first created. Responsible for initializing the UI.      */     @Override     public void onCreate(Bundle savedInstanceState)     {         Log.v(TAG, "Activity State: onCreate()");         super.onCreate(savedInstanceState);         setContentView(R.layout.contact_manager);         // Obtain handles to UI objects         mAddAccountButton = (Button) findViewById(R.id.addContactButton);         mContactList = (ListView) findViewById(R.id.contactList);         mShowInvisibleControl = (CheckBox) findViewById(R.id.showInvisible);         // Initialize class properties         mShowInvisible = false;         mShowInvisibleControl.setChecked(mShowInvisible);         // Register handler for UI elements         mAddAccountButton.setOnClickListener(new View.OnClickListener() {             public void onClick(View v) {                 Log.d(TAG, "mAddAccountButton clicked");                 launchContactAdder();             }         });         mShowInvisibleControl.setOnCheckedChangeListener(new OnCheckedChangeListener() {             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                 Log.d(TAG, "mShowInvisibleControl changed: " + isChecked);                 mShowInvisible = isChecked;                 populateContactList();             }         });         // Populate the contact list         populateContactList();     }     /**      * Populate the contact list based on account currently selected in the account spinner.      */     private void populateContactList() {         // Build adapter with contact entries         Cursor cursor = getContacts();         String[] fields = new String[] {                 ContactsContract.Data.DISPLAY_NAME         };         SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_entry, cursor,                 fields, new int[] {R.id.contactEntryText});         mContactList.setAdapter(adapter);     }     /**      * Obtains the contact list for the currently selected account.      *      * @return A cursor for for accessing the contact list.      */     private Cursor getContacts()     {         // Run query         Uri uri = ContactsContract.Contacts.CONTENT_URI;         String[] projection = new String[] {                 ContactsContract.Contacts._ID,                 ContactsContract.Contacts.DISPLAY_NAME         };         String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" +                 (mShowInvisible ? "0" : "1") + "'";         String[] selectionArgs = null;         String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";         return managedQuery(uri, projection, selection, selectionArgs, sortOrder);     }     /**      * Launches the ContactAdder activity to add a new contact to the selected accont.      */     protected void launchContactAdder() {         Intent i = new Intent(this, ContactAdder.class);         startActivity(i);     } } //res\layout\account_entry.xml <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2009 The Android Open Source Project      Licensed under the Apache License, Version 2.0 (the "License");      you may not use this file except in compliance with the License.      You may obtain a copy of the License at           http://www.apache.org/licenses/LICENSE-2.0      Unless required by applicable law or agreed to in writing, software      distributed under the License is distributed on an "AS IS" BASIS,      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.      See the License for the specific language governing permissions and      limitations under the License. --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="?android:attr/listPreferredItemHeight"     android:padding="6dip">     <ImageView         android:id="@+id/accountIcon"         android:layout_width="wrap_content"         android:layout_height="match_parent"         android:layout_alignParentTop="true"         android:layout_alignParentBottom="true"         android:layout_marginRight="6dip" />     <TextView         android:id="@+id/secondAccountLine"         android:layout_width="match_parent"         android:layout_height="26dip"         android:layout_toRightOf="@id/accountIcon"         android:layout_alignParentBottom="true"         android:layout_alignParentRight="true"         android:singleLine="true"         android:ellipsize="marquee"         android:textColor="@android:color/secondary_text_light" />     <TextView         android:id="@+id/firstAccountLine"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:layout_toRightOf="@id/accountIcon"         android:layout_alignParentRight="true"         android:layout_alignParentTop="true"         android:layout_above="@id/secondAccountLine"         android:layout_alignWithParentIfMissing="true"         android:gravity="center_vertical"         android:textColor="@android:color/primary_text_light"/> </RelativeLayout> //res\layout\contact_adder.xml <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2009 The Android Open Source Project      Licensed under the Apache License, Version 2.0 (the "License");      you may not use this file except in compliance with the License.      You may obtain a copy of the License at           http://www.apache.org/licenses/LICENSE-2.0      Unless required by applicable law or agreed to in writing, software      distributed under the License is distributed on an "AS IS" BASIS,      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.      See the License for the specific language governing permissions and      limitations under the License. --> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"             android:layout_width="match_parent"             android:layout_height="match_parent">     <TableLayout android:layout_width="match_parent"                  android:layout_height="match_parent">         <TableRow>             <TextView android:layout_width="wrap_content"                       android:layout_height="wrap_content"                       android:text="@string/targetAccountLabel"/>         </TableRow>         <TableRow>             <Spinner android:layout_height="wrap_content"                      android:layout_width="match_parent"                      android:layout_weight="1"                      android:id="@+id/accountSpinner"/>         </TableRow>         <TableRow>             <TextView android:layout_width="wrap_content"                       android:layout_height="wrap_content"                       android:text="@string/contactNameLabel"/>         </TableRow>         <TableRow>             <EditText android:id="@+id/contactNameEditText"                       android:layout_height="wrap_content"                       android:layout_width="wrap_content"                       android:layout_weight="1"/>         </TableRow>         <TableRow>             <TextView android:text="@string/contactPhoneLabel"                       android:layout_width="wrap_content"                       android:layout_height="wrap_content"/>         </TableRow>         <TableRow>             <EditText android:id="@+id/contactPhoneEditText"                       android:layout_height="wrap_content"                       android:layout_width="wrap_content"                       android:layout_weight="1"/>             <Spinner android:id="@+id/contactPhoneTypeSpinner"                      android:layout_width="wrap_content"                      android:layout_height="wrap_content"/>         </TableRow>         <TableRow>             <TextView android:text="@string/contactEmailLabel"                       android:layout_width="wrap_content"                       android:layout_height="wrap_content"/>         </TableRow>         <TableRow>             <EditText android:id="@+id/contactEmailEditText"                       android:layout_height="wrap_content"                       android:layout_width="wrap_content"                       android:layout_weight="1"/>             <Spinner android:id="@+id/contactEmailTypeSpinner"                      android:layout_width="wrap_content"                      android:layout_height="wrap_content"/>         </TableRow>         <TableRow>             <Button android:layout_height="wrap_content"                     android:text="@string/save"                     android:id="@+id/contactSaveButton"                     android:layout_width="match_parent"                     android:layout_weight="1"/>         </TableRow>     </TableLayout> </ScrollView> //res\layout\contact_entry.xml <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2009 The Android Open Source Project      Licensed under the Apache License, Version 2.0 (the "License");      you may not use this file except in compliance with the License.      You may obtain a copy of the License at           http://www.apache.org/licenses/LICENSE-2.0      Unless required by applicable law or agreed to in writing, software      distributed under the License is distributed on an "AS IS" BASIS,      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.      See the License for the specific language governing permissions and      limitations under the License. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"               android:layout_width="wrap_content"               android:layout_height="wrap_content">     <TextView android:text="@+id/contactEntryText"               android:id="@+id/contactEntryText"               android:layout_width="match_parent"               android:layout_height="wrap_content"/> </LinearLayout> //res\layout\contact_manager.xml <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2009 The Android Open Source Project      Licensed under the Apache License, Version 2.0 (the "License");      you may not use this file except in compliance with the License.      You may obtain a copy of the License at           http://www.apache.org/licenses/LICENSE-2.0      Unless required by applicable law or agreed to in writing, software      distributed under the License is distributed on an "AS IS" BASIS,      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.      See the License for the specific language governing permissions and      limitations under the License. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"               android:orientation="vertical"               android:layout_width="match_parent"               android:layout_height="match_parent">     <ListView android:layout_width="match_parent"               android:id="@+id/contactList"               android:layout_height="wrap_content"               android:layout_weight="1"/>     <CheckBox android:layout_width="wrap_content"               android:layout_height="wrap_content"               android:id="@+id/showInvisible"               android:text="@string/showInvisible"/>     <Button android:layout_width="match_parent"             android:layout_height="wrap_content"             android:id="@+id/addContactButton"             android:text="@string/addContactButtonLabel"/> </LinearLayout> //res\values\strings.xml <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2009 The Android Open Source Project      Licensed under the Apache License, Version 2.0 (the "License");      you may not use this file except in compliance with the License.      You may obtain a copy of the License at           http://www.apache.org/licenses/LICENSE-2.0      Unless required by applicable law or agreed to in writing, software      distributed under the License is distributed on an "AS IS" BASIS,      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.      See the License for the specific language governing permissions and      limitations under the License. --> <resources>     <string name="accountSpinnerLabel">Account</string>     <string name="addContactButtonLabel">Add Contact</string>     <string name="addContactTitle">Add Contact</string>     <string name="allAccounts">All Accounts</string>     <string name="app_name">Contact Manager</string>     <string name="contactCreationFailure">Contact creation failed, check logs.</string>     <string name="contactEmailLabel">Contact Email</string>     <string name="contactNameLabel">Contact Name</string>     <string name="contactPhoneLabel">Contact Phone</string>     <string name="save">Save</string>     <string name="selectAccountLabel">Select</string>     <string name="selectLabel">Select label</string>     <string name="showInvisible">Show Invisible Contacts (Only)</string>     <string name="targetAccountLabel">Target Account</string>     <string name="undefinedTypeLabel">(Undefined)</string> </resources>