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;
257903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.provider.ContactsContract.Contacts;
267903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.provider.ContactsContract.RawContactsEntity;
277903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.text.TextUtils;
287903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport android.util.Log;
297903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
307903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport com.android.contacts.common.R;
317903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport com.android.vcard.VCardComposer;
327903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport com.android.vcard.VCardConfig;
337903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
347903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.BufferedWriter;
357903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.FileNotFoundException;
367903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.IOException;
377903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.OutputStream;
387903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.OutputStreamWriter;
397903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengimport java.io.Writer;
407903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
417903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng/**
427903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * Class for processing one export request from a user. Dropped after exporting requested Uri(s).
437903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng * {@link VCardService} will create another object when there is another export request.
447903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng */
457903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Chengpublic class ExportProcessor extends ProcessorBase {
467903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private static final String LOG_TAG = "VCardExport";
477903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private static final boolean DEBUG = VCardService.DEBUG;
487903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
497903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private final VCardService mService;
507903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private final ContentResolver mResolver;
517903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private final NotificationManager mNotificationManager;
527903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private final ExportRequest mExportRequest;
537903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private final int mJobId;
547903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private final String mCallingActivity;
557903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
567903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
577903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private volatile boolean mCanceled;
587903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private volatile boolean mDone;
597903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
607903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    public ExportProcessor(VCardService service, ExportRequest exportRequest, int jobId,
617903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            String callingActivity) {
627903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mService = service;
637903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mResolver = service.getContentResolver();
647903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mNotificationManager =
657903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                (NotificationManager)mService.getSystemService(Context.NOTIFICATION_SERVICE);
667903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mExportRequest = exportRequest;
677903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mJobId = jobId;
687903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mCallingActivity = callingActivity;
697903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
707903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
717903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    @Override
727903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    public final int getType() {
737903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        return VCardService.TYPE_EXPORT;
747903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
757903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
767903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    @Override
777903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    public void run() {
787903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        // ExecutorService ignores RuntimeException, so we need to show it here.
797903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        try {
807903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            runInternal();
817903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
827903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            if (isCancelled()) {
837903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                doCancelNotification();
847903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
857903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        } catch (OutOfMemoryError e) {
867903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            Log.e(LOG_TAG, "OutOfMemoryError thrown during import", e);
877903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            throw e;
887903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        } catch (RuntimeException e) {
897903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            Log.e(LOG_TAG, "RuntimeException thrown during export", e);
907903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            throw e;
917903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        } finally {
927903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            synchronized (this) {
937903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                mDone = true;
947903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
957903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        }
967903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
977903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
987903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private void runInternal() {
997903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        if (DEBUG) Log.d(LOG_TAG, String.format("vCard export (id: %d) has started.", mJobId));
1007903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final ExportRequest request = mExportRequest;
1017903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        VCardComposer composer = null;
1027903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        Writer writer = null;
1037903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        boolean successful = false;
1047903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        try {
1057903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            if (isCancelled()) {
1067903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                Log.i(LOG_TAG, "Export request is cancelled before handling the request");
1077903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                return;
1087903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
1097903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            final Uri uri = request.destUri;
1107903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            final OutputStream outputStream;
1117903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            try {
1127903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                outputStream = mResolver.openOutputStream(uri);
1137903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            } catch (FileNotFoundException e) {
1147903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                Log.w(LOG_TAG, "FileNotFoundException thrown", e);
1157903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                // Need concise title.
1167903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1177903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                final String errorReason =
1187903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    mService.getString(R.string.fail_reason_could_not_open_file,
1197903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                            uri, e.getMessage());
1207903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                doFinishNotification(errorReason, null);
1217903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                return;
1227903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
1237903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1247903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            final String exportType = request.exportType;
1257903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            final int vcardType;
1267903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            if (TextUtils.isEmpty(exportType)) {
1277903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                vcardType = VCardConfig.getVCardTypeFromString(
1287903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                        mService.getString(R.string.config_export_vcard_type));
1297903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            } else {
1307903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                vcardType = VCardConfig.getVCardTypeFromString(exportType);
1317903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
1327903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1337903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            composer = new VCardComposer(mService, vcardType, true);
1347903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1357903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            // for test
1367903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            // int vcardType = (VCardConfig.VCARD_TYPE_V21_GENERIC |
1377903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            //     VCardConfig.FLAG_USE_QP_TO_PRIMARY_PROPERTIES);
1387903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            // composer = new VCardComposer(ExportVCardActivity.this, vcardType, true);
1397903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1407903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            writer = new BufferedWriter(new OutputStreamWriter(outputStream));
1419c14089f5a08017413de04b29d2b096b22f74e82Yorke Lee            final Uri contentUriForRawContactsEntity = RawContactsEntity.CONTENT_URI;
1427903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            // TODO: should provide better selection.
1437903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            if (!composer.init(Contacts.CONTENT_URI, new String[] {Contacts._ID},
1447903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    null, null,
1457903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    null, contentUriForRawContactsEntity)) {
1467903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                final String errorReason = composer.getErrorReason();
1477903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                Log.e(LOG_TAG, "initialization of vCard composer failed: " + errorReason);
1487903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                final String translatedErrorReason =
1497903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                        translateComposerError(errorReason);
1507903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                final String title =
1517903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                        mService.getString(R.string.fail_reason_could_not_initialize_exporter,
1527903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                                translatedErrorReason);
1537903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                doFinishNotification(title, null);
1547903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                return;
1557903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
1567903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1577903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            final int total = composer.getCount();
1587903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            if (total == 0) {
1597903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                final String title =
1607903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                        mService.getString(R.string.fail_reason_no_exportable_contact);
1617903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                doFinishNotification(title, null);
1627903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                return;
1637903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
1647903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1657903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            int current = 1;  // 1-origin
1667903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            while (!composer.isAfterLast()) {
1677903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                if (isCancelled()) {
1687903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    Log.i(LOG_TAG, "Export request is cancelled during composing vCard");
1697903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    return;
1707903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                }
1717903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                try {
1727903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    writer.write(composer.createOneEntry());
1737903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                } catch (IOException e) {
1747903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    final String errorReason = composer.getErrorReason();
1757903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    Log.e(LOG_TAG, "Failed to read a contact: " + errorReason);
1767903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    final String translatedErrorReason =
1777903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                            translateComposerError(errorReason);
1787903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    final String title =
1797903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                            mService.getString(R.string.fail_reason_error_occurred_during_export,
1807903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                                    translatedErrorReason);
1817903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    doFinishNotification(title, null);
1827903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    return;
1837903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                }
1847903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1857903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                // vCard export is quite fast (compared to import), and frequent notifications
1867903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                // bother notification bar too much.
1877903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                if (current % 100 == 1) {
1887903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    doProgressNotification(uri, total, current);
1897903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                }
1907903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                current++;
1917903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
1927903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            Log.i(LOG_TAG, "Successfully finished exporting vCard " + request.destUri);
1937903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1947903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            if (DEBUG) {
1957903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                Log.d(LOG_TAG, "Ask MediaScanner to scan the file: " + request.destUri.getPath());
1967903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
1977903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            mService.updateMediaScanner(request.destUri.getPath());
1987903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
1997903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            successful = true;
2007903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            final String filename = uri.getLastPathSegment();
2017903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            final String title = mService.getString(R.string.exporting_vcard_finished_title,
2027903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    filename);
2037903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            doFinishNotification(title, null);
2047903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        } finally {
2057903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            if (composer != null) {
2067903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                composer.terminate();
2077903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
2087903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            if (writer != null) {
2097903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                try {
2107903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    writer.close();
2117903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                } catch (IOException e) {
2127903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                    Log.w(LOG_TAG, "IOException is thrown during close(). Ignored. " + e);
2137903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                }
2147903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            }
2157903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            mService.handleFinishExportNotification(mJobId, successful);
2167903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        }
2177903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
2187903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
2197903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private String translateComposerError(String errorMessage) {
2207903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final Resources resources = mService.getResources();
2217903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        if (VCardComposer.FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO.equals(errorMessage)) {
2227903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            return resources.getString(R.string.composer_failed_to_get_database_infomation);
2237903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        } else if (VCardComposer.FAILURE_REASON_NO_ENTRY.equals(errorMessage)) {
2247903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            return resources.getString(R.string.composer_has_no_exportable_contact);
2257903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        } else if (VCardComposer.FAILURE_REASON_NOT_INITIALIZED.equals(errorMessage)) {
2267903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            return resources.getString(R.string.composer_not_initialized);
2277903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        } else {
2287903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            return errorMessage;
2297903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        }
2307903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
2317903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
2327903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private void doProgressNotification(Uri uri, int totalCount, int currentCount) {
2337903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final String displayName = uri.getLastPathSegment();
2347903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final String description =
2357903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                mService.getString(R.string.exporting_contact_list_message, displayName);
2367903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final String tickerText =
2377903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                mService.getString(R.string.exporting_contact_list_title);
2387903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final Notification notification =
2397903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                NotificationImportExportListener.constructProgressNotification(mService,
2407903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                        VCardService.TYPE_EXPORT, description, tickerText, mJobId, displayName,
2417903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                        totalCount, currentCount);
2427903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
2437903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                mJobId, notification);
2447903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
2457903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
2467903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private void doCancelNotification() {
2477903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        if (DEBUG) Log.d(LOG_TAG, "send cancel notification");
2487903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final String description = mService.getString(R.string.exporting_vcard_canceled_title,
2497903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                mExportRequest.destUri.getLastPathSegment());
2507903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final Notification notification =
2517903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                NotificationImportExportListener.constructCancelNotification(mService, description);
2527903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
2537903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                mJobId, notification);
2547903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
2557903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
2567903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    private void doFinishNotification(final String title, final String description) {
2577903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        if (DEBUG) Log.d(LOG_TAG, "send finish notification: " + title + ", " + description);
2587903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final Intent intent = new Intent();
2597903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        intent.setClassName(mService, mCallingActivity);
2607903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        final Notification notification =
2617903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                NotificationImportExportListener.constructFinishNotification(mService, title,
2627903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                        description, intent);
2637903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
2647903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng                mJobId, notification);
2657903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
2667903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
2677903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    @Override
2687903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    public synchronized boolean cancel(boolean mayInterruptIfRunning) {
2697903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        if (DEBUG) Log.d(LOG_TAG, "received cancel request");
2707903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        if (mDone || mCanceled) {
2717903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng            return false;
2727903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        }
2737903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        mCanceled = true;
2747903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        return true;
2757903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
2767903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
2777903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    @Override
2787903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    public synchronized boolean isCancelled() {
2797903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        return mCanceled;
2807903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
2817903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
2827903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    @Override
2837903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    public synchronized boolean isDone() {
2847903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        return mDone;
2857903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
2867903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng
2877903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    public ExportRequest getRequest() {
2887903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng        return mExportRequest;
2897903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng    }
2907903d2473e1120e32fa5380a7d7532d0a21e2180Chiao Cheng}
291