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.interactions; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.app.Dialog; 22 import android.app.DialogFragment; 23 import android.app.FragmentManager; 24 import android.content.Context; 25 import android.content.DialogInterface; 26 import android.content.Intent; 27 import android.content.res.Resources; 28 import android.database.Cursor; 29 import android.net.Uri; 30 import android.os.Bundle; 31 import android.provider.ContactsContract.Contacts; 32 import android.telephony.SubscriptionManager; 33 import android.util.Log; 34 import android.view.LayoutInflater; 35 import android.view.View; 36 import android.view.ViewGroup; 37 import android.widget.ArrayAdapter; 38 import android.widget.TextView; 39 import android.widget.Toast; 40 41 import com.android.contacts.R; 42 import com.android.contacts.util.ImplicitIntentsUtil; 43 import com.android.contacts.vcard.ExportVCardActivity; 44 import com.android.contacts.vcard.ShareVCardActivity; 45 import com.android.contacts.vcard.VCardCommonArguments; 46 47 /** 48 * An dialog invoked to import/export contacts. 49 */ 50 public class ExportDialogFragment extends DialogFragment { 51 public static final String TAG = "ExportDialogFragment"; 52 53 public static final int EXPORT_MODE_FAVORITES = 0; 54 public static final int EXPORT_MODE_ALL_CONTACTS = 1; 55 public static final int EXPORT_MODE_DEFAULT = -1; 56 57 private static int mExportMode = EXPORT_MODE_DEFAULT; 58 59 private final String[] LOOKUP_PROJECTION = new String[] { 60 Contacts.LOOKUP_KEY 61 }; 62 63 private SubscriptionManager mSubscriptionManager; 64 65 /** Preferred way to show this dialog */ show(FragmentManager fragmentManager, Class callingActivity, int exportMode)66 public static void show(FragmentManager fragmentManager, Class callingActivity, 67 int exportMode) { 68 final ExportDialogFragment fragment = new ExportDialogFragment(); 69 Bundle args = new Bundle(); 70 args.putString(VCardCommonArguments.ARG_CALLING_ACTIVITY, callingActivity.getName()); 71 fragment.setArguments(args); 72 fragment.show(fragmentManager, TAG); 73 mExportMode = exportMode; 74 } 75 76 @Override getContext()77 public Context getContext() { 78 return getActivity(); 79 } 80 81 @Override onAttach(Activity activity)82 public void onAttach(Activity activity) { 83 super.onAttach(activity); 84 } 85 86 @Override onCreateDialog(Bundle savedInstanceState)87 public Dialog onCreateDialog(Bundle savedInstanceState) { 88 // Wrap our context to inflate list items using the correct theme 89 final Resources res = getActivity().getResources(); 90 final LayoutInflater dialogInflater = (LayoutInflater)getActivity() 91 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 92 final String callingActivity = getArguments().getString( 93 VCardCommonArguments.ARG_CALLING_ACTIVITY); 94 95 // Adapter that shows a list of string resources 96 final ArrayAdapter<AdapterEntry> adapter = new ArrayAdapter<AdapterEntry>(getActivity(), 97 R.layout.select_dialog_item) { 98 @Override 99 public View getView(int position, View convertView, ViewGroup parent) { 100 final View result = convertView != null ? convertView : 101 dialogInflater.inflate(R.layout.select_dialog_item, parent, false); 102 103 final TextView text = (TextView) result.findViewById(R.id.primary_text); 104 final View secondaryText = result.findViewById(R.id.secondary_text); 105 secondaryText.setVisibility(View.GONE); 106 107 text.setText(getItem(position).mLabel); 108 return result; 109 } 110 }; 111 112 if (res.getBoolean(R.bool.config_allow_export)) { 113 adapter.add(new AdapterEntry(getString(R.string.export_to_vcf_file), 114 R.string.export_to_vcf_file)); 115 } 116 if (res.getBoolean(R.bool.config_allow_share_contacts)) { 117 if (mExportMode == EXPORT_MODE_FAVORITES) { 118 // share favorite and frequently contacted contacts from Favorites tab 119 adapter.add(new AdapterEntry(getString(R.string.share_favorite_contacts), 120 R.string.share_contacts)); 121 } else { 122 // share "all" contacts (in groups selected in "Customize") from All tab for now 123 // TODO: change the string to share_visible_contacts if implemented 124 adapter.add(new AdapterEntry(getString(R.string.share_contacts), 125 R.string.share_contacts)); 126 } 127 } 128 129 final DialogInterface.OnClickListener clickListener = 130 new DialogInterface.OnClickListener() { 131 @Override 132 public void onClick(DialogInterface dialog, int which) { 133 boolean dismissDialog; 134 final int resId = adapter.getItem(which).mChoiceResourceId; 135 if (resId == R.string.export_to_vcf_file) { 136 dismissDialog = true; 137 final Intent exportIntent = new Intent( 138 getActivity(), ExportVCardActivity.class); 139 exportIntent.putExtra(VCardCommonArguments.ARG_CALLING_ACTIVITY, 140 callingActivity); 141 getActivity().startActivity(exportIntent); 142 } else if (resId == R.string.share_contacts) { 143 dismissDialog = true; 144 if (mExportMode == EXPORT_MODE_FAVORITES) { 145 doShareFavoriteContacts(); 146 } else { // EXPORT_MODE_ALL_CONTACTS 147 final Intent exportIntent = new Intent( 148 getActivity(), ShareVCardActivity.class); 149 exportIntent.putExtra(VCardCommonArguments.ARG_CALLING_ACTIVITY, 150 callingActivity); 151 getActivity().startActivity(exportIntent); 152 } 153 } else { 154 dismissDialog = true; 155 Log.e(TAG, "Unexpected resource: " 156 + getActivity().getResources().getResourceEntryName(resId)); 157 } 158 if (dismissDialog) { 159 dialog.dismiss(); 160 } 161 } 162 }; 163 final TextView title = (TextView) View.inflate(getActivity(), R.layout.dialog_title, null); 164 title.setText(R.string.dialog_export); 165 return new AlertDialog.Builder(getActivity()) 166 .setCustomTitle(title) 167 .setSingleChoiceItems(adapter, -1, clickListener) 168 .create(); 169 } 170 doShareFavoriteContacts()171 private void doShareFavoriteContacts() { 172 try{ 173 final Cursor cursor = getActivity().getContentResolver().query( 174 Contacts.CONTENT_STREQUENT_URI, LOOKUP_PROJECTION, null, null, 175 Contacts.DISPLAY_NAME + " COLLATE NOCASE ASC"); 176 if (cursor != null) { 177 try { 178 if (!cursor.moveToFirst()) { 179 Toast.makeText(getActivity(), R.string.no_contact_to_share, 180 Toast.LENGTH_SHORT).show(); 181 return; 182 } 183 184 // Build multi-vcard Uri for sharing 185 final StringBuilder uriListBuilder = new StringBuilder(); 186 int index = 0; 187 do { 188 if (index != 0) 189 uriListBuilder.append(':'); 190 uriListBuilder.append(cursor.getString(0)); 191 index++; 192 } while (cursor.moveToNext()); 193 final Uri uri = Uri.withAppendedPath( 194 Contacts.CONTENT_MULTI_VCARD_URI, 195 Uri.encode(uriListBuilder.toString())); 196 197 final Intent intent = new Intent(Intent.ACTION_SEND); 198 intent.setType(Contacts.CONTENT_VCARD_TYPE); 199 intent.putExtra(Intent.EXTRA_STREAM, uri); 200 ImplicitIntentsUtil.startActivityOutsideApp(getActivity(), intent); 201 } finally { 202 cursor.close(); 203 } 204 } 205 } catch (Exception e) { 206 Log.e(TAG, "Sharing contacts failed", e); 207 getActivity().runOnUiThread(new Runnable() { 208 @Override 209 public void run() { 210 Toast.makeText(getContext(), R.string.share_contacts_failure, 211 Toast.LENGTH_SHORT).show(); 212 } 213 }); 214 } 215 } 216 217 private static class AdapterEntry { 218 public final CharSequence mLabel; 219 public final int mChoiceResourceId; 220 public final int mSubscriptionId; 221 AdapterEntry(CharSequence label, int resId, int subId)222 public AdapterEntry(CharSequence label, int resId, int subId) { 223 mLabel = label; 224 mChoiceResourceId = resId; 225 mSubscriptionId = subId; 226 } 227 AdapterEntry(String label, int resId)228 public AdapterEntry(String label, int resId) { 229 // Store a nonsense value for mSubscriptionId. If this constructor is used, 230 // the mSubscriptionId value should not be read later. 231 this(label, resId, /* subId = */ -1); 232 } 233 } 234 } 235