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