17903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng/* 27903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * Copyright (C) 2010 The Android Open Source Project 37903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * 47903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 57903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * you may not use this file except in compliance with the License. 67903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * You may obtain a copy of the License at 77903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * 87903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * http://www.apache.org/licenses/LICENSE-2.0 97903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * 107903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * Unless required by applicable law or agreed to in writing, software 117903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS, 127903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * See the License for the specific language governing permissions and 147903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * limitations under the License. 157903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng */ 167903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengpackage com.android.contacts.common.vcard; 177903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 187903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.app.Notification; 197903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.app.NotificationManager; 207903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.content.ContentResolver; 217903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.content.Context; 227903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.content.Intent; 237903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.content.res.Resources; 247903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.net.Uri; 2581c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wangimport android.os.Handler; 2681c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wangimport android.os.Message; 277903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.provider.ContactsContract.Contacts; 287903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.provider.ContactsContract.RawContactsEntity; 297903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.text.TextUtils; 307903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.util.Log; 3181c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wangimport android.widget.Toast; 327903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 337903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport com.android.contacts.common.R; 347903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport com.android.vcard.VCardComposer; 357903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport com.android.vcard.VCardConfig; 367903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 377903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.BufferedWriter; 387903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.FileNotFoundException; 397903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.IOException; 407903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.OutputStream; 417903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.OutputStreamWriter; 427903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.Writer; 437903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 447903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng/** 457903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * Class for processing one export request from a user. Dropped after exporting requested Uri(s). 467903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * {@link VCardService} will create another object when there is another export request. 477903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng */ 487903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengpublic class ExportProcessor extends ProcessorBase { 497903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private static final String LOG_TAG = "VCardExport"; 507903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private static final boolean DEBUG = VCardService.DEBUG; 517903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 527903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private final VCardService mService; 537903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private final ContentResolver mResolver; 547903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private final NotificationManager mNotificationManager; 557903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private final ExportRequest mExportRequest; 567903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private final int mJobId; 577903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private final String mCallingActivity; 587903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 597903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private volatile boolean mCanceled; 607903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private volatile boolean mDone; 617903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 6281c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang private final int SHOW_READY_TOAST = 1; 6381c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang private final Handler handler = new Handler() { 6481c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang public void handleMessage(Message msg) { 6581c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang if (msg.arg1 == SHOW_READY_TOAST) { 6681c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang // This message is long, so we set the duration to LENGTH_LONG. 6781c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang Toast.makeText(mService, 6881c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang R.string.exporting_vcard_finished_toast, Toast.LENGTH_LONG).show(); 6981c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang } 7081c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang 7181c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang } 7281c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang }; 7381c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang 747903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng public ExportProcessor(VCardService service, ExportRequest exportRequest, int jobId, 757903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng String callingActivity) { 767903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService = service; 777903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mResolver = service.getContentResolver(); 787903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mNotificationManager = 797903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng (NotificationManager)mService.getSystemService(Context.NOTIFICATION_SERVICE); 807903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mExportRequest = exportRequest; 817903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mJobId = jobId; 827903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mCallingActivity = callingActivity; 837903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 847903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 857903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng @Override 867903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng public final int getType() { 877903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return VCardService.TYPE_EXPORT; 887903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 897903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 907903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng @Override 917903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng public void run() { 927903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng // ExecutorService ignores RuntimeException, so we need to show it here. 937903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng try { 947903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng runInternal(); 957903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 967903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (isCancelled()) { 977903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng doCancelNotification(); 987903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 997903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } catch (OutOfMemoryError e) { 1007903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.e(LOG_TAG, "OutOfMemoryError thrown during import", e); 1017903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng throw e; 1027903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } catch (RuntimeException e) { 1037903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.e(LOG_TAG, "RuntimeException thrown during export", e); 1047903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng throw e; 1057903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } finally { 1067903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng synchronized (this) { 1077903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mDone = true; 1087903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1097903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1107903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1117903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 1127903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private void runInternal() { 1137903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (DEBUG) Log.d(LOG_TAG, String.format("vCard export (id: %d) has started.", mJobId)); 1147903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final ExportRequest request = mExportRequest; 1157903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng VCardComposer composer = null; 1167903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Writer writer = null; 1177903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng boolean successful = false; 1187903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng try { 1197903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (isCancelled()) { 1207903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.i(LOG_TAG, "Export request is cancelled before handling the request"); 1217903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return; 1227903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1237903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final Uri uri = request.destUri; 1247903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final OutputStream outputStream; 1257903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng try { 1267903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng outputStream = mResolver.openOutputStream(uri); 1277903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } catch (FileNotFoundException e) { 1287903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.w(LOG_TAG, "FileNotFoundException thrown", e); 1297903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng // Need concise title. 1307903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 1317903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String errorReason = 1327903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService.getString(R.string.fail_reason_could_not_open_file, 1337903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng uri, e.getMessage()); 1347903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng doFinishNotification(errorReason, null); 1357903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return; 1367903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1377903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 1387903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String exportType = request.exportType; 1397903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final int vcardType; 1407903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (TextUtils.isEmpty(exportType)) { 1417903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng vcardType = VCardConfig.getVCardTypeFromString( 1427903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService.getString(R.string.config_export_vcard_type)); 1437903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } else { 1447903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng vcardType = VCardConfig.getVCardTypeFromString(exportType); 1457903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1467903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 1477903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng composer = new VCardComposer(mService, vcardType, true); 1487903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 1497903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng // for test 1507903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng // int vcardType = (VCardConfig.VCARD_TYPE_V21_GENERIC | 1517903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng // VCardConfig.FLAG_USE_QP_TO_PRIMARY_PROPERTIES); 1527903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng // composer = new VCardComposer(ExportVCardActivity.this, vcardType, true); 1537903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 1547903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng writer = new BufferedWriter(new OutputStreamWriter(outputStream)); 1559c14089f5a08017413de04b29d2b096b22f74e82Yorke Lee final Uri contentUriForRawContactsEntity = RawContactsEntity.CONTENT_URI; 1567903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng // TODO: should provide better selection. 1577903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (!composer.init(Contacts.CONTENT_URI, new String[] {Contacts._ID}, 1587903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng null, null, 1597903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng null, contentUriForRawContactsEntity)) { 1607903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String errorReason = composer.getErrorReason(); 1617903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.e(LOG_TAG, "initialization of vCard composer failed: " + errorReason); 1627903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String translatedErrorReason = 1637903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng translateComposerError(errorReason); 1647903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String title = 1657903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService.getString(R.string.fail_reason_could_not_initialize_exporter, 1667903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng translatedErrorReason); 1677903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng doFinishNotification(title, null); 1687903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return; 1697903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1707903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 1717903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final int total = composer.getCount(); 1727903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (total == 0) { 1737903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String title = 1747903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService.getString(R.string.fail_reason_no_exportable_contact); 1757903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng doFinishNotification(title, null); 1767903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return; 1777903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1787903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 1797903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng int current = 1; // 1-origin 1807903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng while (!composer.isAfterLast()) { 1817903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (isCancelled()) { 1827903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.i(LOG_TAG, "Export request is cancelled during composing vCard"); 1837903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return; 1847903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1857903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng try { 1867903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng writer.write(composer.createOneEntry()); 1877903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } catch (IOException e) { 1887903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String errorReason = composer.getErrorReason(); 1897903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.e(LOG_TAG, "Failed to read a contact: " + errorReason); 1907903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String translatedErrorReason = 1917903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng translateComposerError(errorReason); 1927903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String title = 1937903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService.getString(R.string.fail_reason_error_occurred_during_export, 1947903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng translatedErrorReason); 1957903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng doFinishNotification(title, null); 1967903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return; 1977903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 1987903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 1997903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng // vCard export is quite fast (compared to import), and frequent notifications 2007903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng // bother notification bar too much. 2017903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (current % 100 == 1) { 2027903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng doProgressNotification(uri, total, current); 2037903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2047903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng current++; 2057903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2067903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.i(LOG_TAG, "Successfully finished exporting vCard " + request.destUri); 2077903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 2087903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (DEBUG) { 2097903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.d(LOG_TAG, "Ask MediaScanner to scan the file: " + request.destUri.getPath()); 2107903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2117903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService.updateMediaScanner(request.destUri.getPath()); 2127903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 2137903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng successful = true; 2146aa0ab91746534fe5b30a1456687485d1b38b85aWalter Jang final String filename = ExportVCardActivity.getOpenableUriDisplayName(mService, uri); 21581c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang // If it is a local file (i.e. not a file from Drive), we need to allow user to share 21681c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang // the file by pressing the notification; otherwise, it would be a file in Drive, we 21781c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang // don't need to enable this action in notification since the file is already uploaded. 21881c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang if (isLocalFile(uri)) { 21981c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang final Message msg = handler.obtainMessage(); 22081c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang msg.arg1 = SHOW_READY_TOAST; 22181c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang handler.sendMessage(msg); 22281c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang doFinishNotificationWithShareAction( 22381c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang mService.getString(R.string.exporting_vcard_finished_title_fallback), 22481c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang mService.getString(R.string.touch_to_share_contacts), uri); 22581c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang } else { 22681c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang final String title = filename == null 22781c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang ? mService.getString(R.string.exporting_vcard_finished_title_fallback) 22881c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang : mService.getString(R.string.exporting_vcard_finished_title, filename); 22981c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang doFinishNotification(title, null); 23081c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang } 2317903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } finally { 2327903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (composer != null) { 2337903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng composer.terminate(); 2347903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2357903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (writer != null) { 2367903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng try { 2377903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng writer.close(); 2387903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } catch (IOException e) { 2397903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng Log.w(LOG_TAG, "IOException is thrown during close(). Ignored. " + e); 2407903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2417903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2427903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService.handleFinishExportNotification(mJobId, successful); 2437903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2447903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2457903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 24681c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang private boolean isLocalFile(Uri uri) { 24781c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang final String authority = uri.getAuthority(); 24881c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang return mService.getString(R.string.contacts_file_provider_authority).equals(authority); 24981c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang } 25081c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang 2517903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private String translateComposerError(String errorMessage) { 2527903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final Resources resources = mService.getResources(); 2537903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (VCardComposer.FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO.equals(errorMessage)) { 2547903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return resources.getString(R.string.composer_failed_to_get_database_infomation); 2557903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } else if (VCardComposer.FAILURE_REASON_NO_ENTRY.equals(errorMessage)) { 2567903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return resources.getString(R.string.composer_has_no_exportable_contact); 2577903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } else if (VCardComposer.FAILURE_REASON_NOT_INITIALIZED.equals(errorMessage)) { 2587903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return resources.getString(R.string.composer_not_initialized); 2597903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } else { 2607903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return errorMessage; 2617903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2627903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2637903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 2647903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private void doProgressNotification(Uri uri, int totalCount, int currentCount) { 2657903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String displayName = uri.getLastPathSegment(); 2667903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String description = 2677903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService.getString(R.string.exporting_contact_list_message, displayName); 2687903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String tickerText = 2697903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mService.getString(R.string.exporting_contact_list_title); 2707903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final Notification notification = 2717903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng NotificationImportExportListener.constructProgressNotification(mService, 2727903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng VCardService.TYPE_EXPORT, description, tickerText, mJobId, displayName, 2737903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng totalCount, currentCount); 2747903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG, 2757903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mJobId, notification); 2767903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2777903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 2787903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private void doCancelNotification() { 2797903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (DEBUG) Log.d(LOG_TAG, "send cancel notification"); 2807903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final String description = mService.getString(R.string.exporting_vcard_canceled_title, 2817903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mExportRequest.destUri.getLastPathSegment()); 2827903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final Notification notification = 2837903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng NotificationImportExportListener.constructCancelNotification(mService, description); 2847903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG, 2857903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mJobId, notification); 2867903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2877903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 2887903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng private void doFinishNotification(final String title, final String description) { 2897903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (DEBUG) Log.d(LOG_TAG, "send finish notification: " + title + ", " + description); 2907903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final Intent intent = new Intent(); 2917903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng intent.setClassName(mService, mCallingActivity); 2927903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng final Notification notification = 2937903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng NotificationImportExportListener.constructFinishNotification(mService, title, 2947903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng description, intent); 2957903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG, 2967903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mJobId, notification); 2977903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 2987903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 29981c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang /** 30081c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang * Pass intent with ACTION_SEND to notification so that user can press the notification to 30181c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang * share contacts. 30281c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang */ 30381c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang private void doFinishNotificationWithShareAction(final String title, final String 30481c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang description, Uri uri) { 30581c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang if (DEBUG) Log.d(LOG_TAG, "send finish notification: " + title + ", " + description); 30681c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang final Intent intent = new Intent(Intent.ACTION_SEND); 30781c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang intent.setType(Contacts.CONTENT_VCARD_TYPE); 30881c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang intent.putExtra(Intent.EXTRA_STREAM, uri); 3092149e72ed4d55b1d9271872960b74ace5f8a3e90Wenyi Wang // Securely grant access using temporary access permissions 3102149e72ed4d55b1d9271872960b74ace5f8a3e90Wenyi Wang intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 3112149e72ed4d55b1d9271872960b74ace5f8a3e90Wenyi Wang // Build notification 31281c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang final Notification notification = 31381c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang NotificationImportExportListener.constructFinishNotificationWithFlags( 31481c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang mService, title, description, intent, Intent.FLAG_ACTIVITY_NEW_TASK); 31581c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG, 31681c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang mJobId, notification); 31781c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang } 31881c9c1da36cb58d7c583642a5f9449f113c8aeddWenyi Wang 3197903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng @Override 3207903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng public synchronized boolean cancel(boolean mayInterruptIfRunning) { 3217903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (DEBUG) Log.d(LOG_TAG, "received cancel request"); 3227903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng if (mDone || mCanceled) { 3237903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return false; 3247903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 3257903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng mCanceled = true; 3267903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return true; 3277903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 3287903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 3297903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng @Override 3307903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng public synchronized boolean isCancelled() { 3317903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return mCanceled; 3327903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 3337903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 3347903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng @Override 3357903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng public synchronized boolean isDone() { 3367903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return mDone; 3377903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 3387903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng 3397903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng public ExportRequest getRequest() { 3407903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng return mExportRequest; 3417903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng } 3427903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng} 343