James Laskey | 1e2102f | 2016-09-19 10:09:08 -0700 | [diff] [blame] | 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 | |
Gary Mai | 69c182a | 2016-12-05 13:07:03 -0800 | [diff] [blame] | 17 | package com.android.contacts.interactions; |
James Laskey | 1e2102f | 2016-09-19 10:09:08 -0700 | [diff] [blame] | 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 | |
Arthur Wang | 3f6a244 | 2016-12-05 14:51:59 -0800 | [diff] [blame] | 41 | import com.android.contacts.R; |
Gary Mai | 69c182a | 2016-12-05 13:07:03 -0800 | [diff] [blame] | 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; |
James Laskey | 1e2102f | 2016-09-19 10:09:08 -0700 | [diff] [blame] | 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 */ |
| 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 |
| 77 | public Context getContext() { |
| 78 | return getActivity(); |
| 79 | } |
| 80 | |
| 81 | @Override |
| 82 | public void onAttach(Activity activity) { |
| 83 | super.onAttach(activity); |
| 84 | } |
| 85 | |
| 86 | @Override |
| 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) { |
Marcus Hagerott | 8636d1e | 2016-10-27 19:14:12 -0700 | [diff] [blame] | 100 | final View result = convertView != null ? convertView : |
| 101 | dialogInflater.inflate(R.layout.select_dialog_item, parent, false); |
James Laskey | 1e2102f | 2016-09-19 10:09:08 -0700 | [diff] [blame] | 102 | |
Marcus Hagerott | 8636d1e | 2016-10-27 19:14:12 -0700 | [diff] [blame] | 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); |
James Laskey | 1e2102f | 2016-09-19 10:09:08 -0700 | [diff] [blame] | 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 | |
| 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 | |
| 222 | public AdapterEntry(CharSequence label, int resId, int subId) { |
| 223 | mLabel = label; |
| 224 | mChoiceResourceId = resId; |
| 225 | mSubscriptionId = subId; |
| 226 | } |
| 227 | |
| 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 | } |