Import Contact

Embed Size (px)

Citation preview

  • 7/29/2019 Import Contact

    1/18

    /** Copyright (C) 2009 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0*

    * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/

    package com.android.contacts;import android.accounts.Account;import android.app.Activity;import android.app.AlertDialog;import android.app.Dialog;import android.app.ProgressDialog;import android.content.ContentResolver;

    import android.content.ContentUris;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.DialogInterface.OnCancelListener;import android.content.DialogInterface.OnClickListener;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.PowerManager;import android.pim.vcard.VCardConfig;import android.pim.vcard.VCardEntryCommitter;

    import android.pim.vcard.VCardEntryConstructor;import android.pim.vcard.VCardEntryCounter;import android.pim.vcard.VCardInterpreter;import android.pim.vcard.VCardInterpreterCollection;import android.pim.vcard.VCardParser_V21;import android.pim.vcard.VCardParser_V30;import android.pim.vcard.VCardSourceDetector;import android.pim.vcard.exception.VCardException;import android.pim.vcard.exception.VCardNestedException;import android.pim.vcard.exception.VCardNotSupportedException;import android.pim.vcard.exception.VCardVersionException;import android.provider.ContactsContract.RawContacts;import android.text.SpannableStringBuilder;

    import android.text.Spanned;import android.text.TextUtils;import android.text.style.RelativeSizeSpan;import android.util.Log;import com.android.contacts.model.Sources;import com.android.contacts.util.AccountSelectionUtil;import java.io.File;import java.io.IOException;

  • 7/29/2019 Import Contact

    2/18

    import java.io.InputStream;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Arrays;import java.util.Date;import java.util.HashSet;import java.util.List;import java.util.Locale;import java.util.Set;import java.util.Vector;class More ...VCardFile {

    private String mName;private String mCanonicalPath;private long mLastModified;

    public More ...VCardFile(String name, String canonicalPath, long lastModifi

    ed) {mName = name;mCanonicalPath = canonicalPath;mLastModified = lastModified;

    }

    public String More ...getName() {return mName;}

    public String More ...getCanonicalPath() {

    return mCanonicalPath;}

    public long More ...getLastModified() {

    return mLastModified;}

    }

    public class More ...ImportVCardActivity extends Activity {private static final String LOG_TAG = "ImportVCardActivity";private static final boolean DO_PERFORMANCE_PROFILE = false;

    // Run on the UI thread. Must not be null except after onDestroy().private Handler mHandler = new Handler();

    private AccountSelectionUtil.AccountSelectedListener mAccountSelectionListener;

    private Account mAccount;

    private ProgressDialog mProgressDialogForScanVCard;

    private List mAllVCardFileList;private VCardScanThread mVCardScanThread;private VCardReadThread mVCardReadThread;private ProgressDialog mProgressDialogForReadVCard;

    private String mErrorMessage;

    private boolean mNeedReview = false;

  • 7/29/2019 Import Contact

    3/18

    // Runs on the UI thread.private class More ...DialogDisplayer implements Runnable {

    private final int mResId;public More ...DialogDisplayer(int resId) {

    mResId = resId;}public More ...DialogDisplayer(String errorMessage) {

    mResId = R.id.dialog_error_with_message;mErrorMessage = errorMessage;

    }public void More ...run() {

    showDialog(mResId);}

    }

    private class More ...CancelListenerimplements DialogInterface.OnClickListener, DialogInterface.OnCancelList

    ener {public void More ...onClick(DialogInterface dialog, int which) {

    finish();}

    public void More ...onCancel(DialogInterface dialog) {finish();

    }}

    private CancelListener mCancelListener = new CancelListener();

    private class More ...VCardReadThread extends Threadimplements DialogInterface.OnCancelListener {

    private ContentResolver mResolver;private VCardParser_V21 mVCardParser;private boolean mCanceled;private PowerManager.WakeLock mWakeLock;private Uri mUri;private File mTempFile;

    private List mSelectedVCardFileList;private List mErrorFileNameList;

    public More ...VCardReadThread(Uri uri) {mUri = uri;init();

    }

    public More ...VCardReadThread(final List selectedVCardFileList) {

    mSelectedVCardFileList = selectedVCardFileList;mErrorFileNameList = new ArrayList();

    init();}

    private void More ...init() {Context context = ImportVCardActivity.this;mResolver = context.getContentResolver();PowerManager powerManager = (PowerManager)context.getSystemService(

    Context.POWER_SERVICE);mWakeLock = powerManager.newWakeLock(

    PowerManager.SCREEN_DIM_WAKE_LOCK |

  • 7/29/2019 Import Contact

    4/18

    PowerManager.ON_AFTER_RELEASE, LOG_TAG);}

    @Overridepublic void More ...finalize() {

    if (mWakeLock != null && mWakeLock.isHeld()) {mWakeLock.release();

    }}

    @Overridepublic void More ...run() {

    boolean shouldCallFinish = true;mWakeLock.acquire();Uri createdUri = null;mTempFile = null;// Some malicious vCard data may make this thread broken// (e.g. OutOfMemoryError).// Even in such cases, some should be done.try {

    if (mUri != null) { // Read one vCard expressed by mUrifinal Uri targetUri = mUri;mProgressDialogForReadVCard.setProgressNumberFormat("");mProgressDialogForReadVCard.setProgress(0);

    // Count the number of VCard entriesmProgressDialogForReadVCard.setIndeterminate(true);long start;if (DO_PERFORMANCE_PROFILE) {

    start = System.currentTimeMillis();}VCardEntryCounter counter = new VCardEntryCounter();VCardSourceDetector detector = new VCardSourceDetector();VCardInterpreterCollection builderCollection = new VCardInte

    rpreterCollection(Arrays.asList(counter, detector));

    boolean result;

    try {result = readOneVCardFile(targetUri,VCardConfig.DEFAULT_CHARSET, builderCollection,

    null, true, null);} catch (VCardNestedException e) {

    try {// Assume that VCardSourceDetector was able to detec

    t the source.// Try again with the detector.result = readOneVCardFile(targetUri,

    VCardConfig.DEFAULT_CHARSET, counter, detector, false, null);

    } catch (VCardNestedException e2) {

    result = false;Log.e(LOG_TAG, "Must not reach here. " + e2);

    }}if (DO_PERFORMANCE_PROFILE) {

    long time = System.currentTimeMillis() - start;Log.d(LOG_TAG, "time for counting the number of vCard en

    tries: " +time + " ms");

    }

  • 7/29/2019 Import Contact

    5/18

    if (!result) {shouldCallFinish = false;return;

    }

    mProgressDialogForReadVCard.setProgressNumberFormat(getString(R.string.reading_vcard_contacts));

    mProgressDialogForReadVCard.setIndeterminate(false);mProgressDialogForReadVCard.setMax(counter.getCount());String charset = detector.getEstimatedCharset();createdUri = doActuallyReadOneVCard(targetUri, null, charset

    , true, detector,mErrorFileNameList);

    } else { // Read multiple files.mProgressDialogForReadVCard.setProgressNumberFormat(

    getString(R.string.reading_vcard_files));mProgressDialogForReadVCard.setMax(mSelectedVCardFileList.si

    ze());mProgressDialogForReadVCard.setProgress(0);

    for (VCardFile vcardFile : mSelectedVCardFileList) {if (mCanceled) {

    return;}

    // TODO: detect scheme!final Uri targetUri =Uri.parse("file://" + vcardFile.getCanonicalPath());

    VCardSourceDetector detector = new VCardSourceDetector();

    try {if (!readOneVCardFile(targetUri, VCardConfig.DEFAULT

    _CHARSET,detector, null, true, mErrorFileNameList)) {

    continue;}

    } catch (VCardNestedException e) {

    // Assume that VCardSourceDetector was able to detect the source.}String charset = detector.getEstimatedCharset();doActuallyReadOneVCard(targetUri, mAccount,

    charset, false, detector, mErrorFileNameList);mProgressDialogForReadVCard.incrementProgressBy(1);

    }}

    } finally {mWakeLock.release();mProgressDialogForReadVCard.dismiss();if (mTempFile != null) {

    if (!mTempFile.delete()) {Log.w(LOG_TAG, "Failed to delete a cache file.");

    }mTempFile = null;

    }// finish() is called via mCancelListener, which is used in Dial

    ogDisplayer.if (shouldCallFinish && !isFinishing()) {

    if (mErrorFileNameList == null || mErrorFileNameList.isEmpty()) {

  • 7/29/2019 Import Contact

    6/18

    finish();if (mNeedReview) {

    mNeedReview = false;Log.v("importVCardActivity", "Prepare to review the

    imported contact");

    if (createdUri != null) {// get contact_id of this raw_contactfinal long rawContactId = ContentUris.parseId(cr

    eatedUri);Uri contactUri = RawContacts.getContactLookupUri

    (getContentResolver(), ContentUris.withAp

    pendedId(RawContacts.CONTENT_URI, rawCont

    actId));

    Intent viewIntent = new Intent(Intent.ACTION_VIEW, contactUri);

    startActivity(viewIntent);}

    }} else {

    StringBuilder builder = new StringBuilder();

    boolean first = true;for (String fileName : mErrorFileNameList) {if (first) {

    first = false;} else {

    builder.append(", ");}builder.append(fileName);

    }

    runOnUIThread(new DialogDisplayer(getString(R.string.fail_reason_failed_to_read_fi

    les,

    builder.toString())));}}

    }}

    private Uri More ...doActuallyReadOneVCard(Uri uri, Account account,String charset, boolean showEntryParseProgress,VCardSourceDetector detector, List errorFileNameList) {

    final Context context = ImportVCardActivity.this;VCardEntryConstructor builder;final String currentLanguage = Locale.getDefault().getLanguage();int vcardType = VCardConfig.getVCardTypeFromString(

    context.getString(R.string.config_import_vcard_type));if (charset != null) {

    builder = new VCardEntryConstructor(charset, charset, false, vcardType, mAccount);

    } else {charset = VCardConfig.DEFAULT_CHARSET;builder = new VCardEntryConstructor(null, null, false, vcardType

    , mAccount);}VCardEntryCommitter committer = new VCardEntryCommitter(mResolver);

  • 7/29/2019 Import Contact

    7/18

    builder.addEntryHandler(committer);if (showEntryParseProgress) {

    builder.addEntryHandler(new ProgressShower(mProgressDialogForReadVCard,

    context.getString(R.string.reading_vcard_message),ImportVCardActivity.this,mHandler));

    }

    try {if (!readOneVCardFile(uri, charset, builder, detector, false, nu

    ll)) {return null;

    }} catch (VCardNestedException e) {

    Log.e(LOG_TAG, "Never reach here.");}final ArrayList createdUris = committer.getCreatedUris();return (createdUris == null || createdUris.size() != 1) ? null : cre

    atedUris.get(0);}

    private boolean More ...readOneVCardFile(Uri uri, String charset,VCardInterpreter builder, VCardSourceDetector detector,

    boolean throwNestedException, List errorFileNameList)throws VCardNestedException {InputStream is;try {

    is = mResolver.openInputStream(uri);mVCardParser = new VCardParser_V21(detector);

    try {mVCardParser.parse(is, charset, builder, mCanceled);

    } catch (VCardVersionException e1) {try {

    is.close();} catch (IOException e) {

    }if (builder instanceof VCardEntryConstructor) {// Let the object clean up internal temporal objects,((VCardEntryConstructor)builder).clear();

    }is = mResolver.openInputStream(uri);

    try {mVCardParser = new VCardParser_V30();mVCardParser.parse(is, charset, builder, mCanceled);

    } catch (VCardVersionException e2) {throw new VCardException("vCard with unspported version.

    ");

    }} finally {

    if (is != null) {try {

    is.close();} catch (IOException e) {}

    }}

    } catch (IOException e) {

  • 7/29/2019 Import Contact

    8/18

    Log.e(LOG_TAG, "IOException was emitted: " + e.getMessage());

    mProgressDialogForReadVCard.dismiss();

    if (errorFileNameList != null) {errorFileNameList.add(uri.toString());

    } else {runOnUIThread(new DialogDisplayer(

    getString(R.string.fail_reason_io_error) +": " + e.getLocalizedMessage()));

    }return false;

    } catch (VCardNotSupportedException e) {if ((e instanceof VCardNestedException) && throwNestedException)

    {throw (VCardNestedException)e;

    }if (errorFileNameList != null) {

    errorFileNameList.add(uri.toString());} else {

    runOnUIThread(new DialogDisplayer(getString(R.string.fail_reason_vcard_not_supported_e

    rror) +" (" + e.getMessage() + ")"));

    }return false;} catch (VCardException e) {

    if (errorFileNameList != null) {errorFileNameList.add(uri.toString());

    } else {runOnUIThread(new DialogDisplayer(

    getString(R.string.fail_reason_vcard_parse_error) +" (" + e.getMessage() + ")"));

    }return false;

    }return true;

    }

    public void More ...cancel() {mCanceled = true;if (mVCardParser != null) {

    mVCardParser.cancel();}

    }

    public void More ...onCancel(DialogInterface dialog) {cancel();

    }}

    private class More ...ImportTypeSelectedListener implementsDialogInterface.OnClickListener {

    public static final int IMPORT_ONE = 0;public static final int IMPORT_MULTIPLE = 1;public static final int IMPORT_ALL = 2;public static final int IMPORT_TYPE_SIZE = 3;

    private int mCurrentIndex;

  • 7/29/2019 Import Contact

    9/18

    public void More ...onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_POSITIVE) {

    switch (mCurrentIndex) {case IMPORT_ALL:

    importMultipleVCardFromSDCard(mAllVCardFileList);break;

    case IMPORT_MULTIPLE:showDialog(R.id.dialog_select_multiple_vcard);break;

    default:showDialog(R.id.dialog_select_one_vcard);break;

    }} else if (which == DialogInterface.BUTTON_NEGATIVE) {

    finish();} else {

    mCurrentIndex = which;}

    }}

    private class More ...VCardSelectedListener implementsDialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickL

    istener {

    private int mCurrentIndex;private Set mSelectedIndexSet;

    public More ...VCardSelectedListener(boolean multipleSelect) {mCurrentIndex = 0;if (multipleSelect) {

    mSelectedIndexSet = new HashSet();}

    }

    public void More ...onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_POSITIVE) {

    if (mSelectedIndexSet != null) {

    List selectedVCardFileList = new ArrayList();int size = mAllVCardFileList.size();// We'd like to sort the files by its index, so we do not us

    e Set iterator.for (int i = 0; i < size; i++) {

    if (mSelectedIndexSet.contains(i)) {selectedVCardFileList.add(mAllVCardFileList.get(i));

    }}importMultipleVCardFromSDCard(selectedVCardFileList);

    } else {String canonicalPath = mAllVCardFileList.get(mCurrentIndex).

    getCanonicalPath();final Uri uri = Uri.parse("file://" + canonicalPath);importOneVCardFromSDCard(uri);

    }} else if (which == DialogInterface.BUTTON_NEGATIVE) {

    finish();} else {

    // Some file is selected.mCurrentIndex = which;if (mSelectedIndexSet != null) {

  • 7/29/2019 Import Contact

    10/18

    if (mSelectedIndexSet.contains(which)) {mSelectedIndexSet.remove(which);

    } else {mSelectedIndexSet.add(which);

    }}

    }}

    public void More ...onClick(DialogInterface dialog, int which, boolean isChecked) {

    if (mSelectedIndexSet == null || (mSelectedIndexSet.contains(which)== isChecked)) {

    Log.e(LOG_TAG, String.format("Inconsist state in index %d (%s)",which,

    mAllVCardFileList.get(which).getCanonicalPath()));} else {

    onClick(dialog, which);}

    }}

    private class More ...VCardScanThread extends Thread implements OnCancelListener, OnClickListener {

    private boolean mCanceled;private boolean mGotIOException;private File mRootDirectory;

    // To avoid recursive link.private Set mCheckedPaths;private PowerManager.WakeLock mWakeLock;

    private class More ...CanceledException extends Exception {}

    public More ...VCardScanThread(File sdcardDirectory) {mCanceled = false;

    mGotIOException = false;mRootDirectory = sdcardDirectory;mCheckedPaths = new HashSet();PowerManager powerManager = (PowerManager)ImportVCardActivity.this.g

    etSystemService(Context.POWER_SERVICE);

    mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK |PowerManager.ON_AFTER_RELEASE, LOG_TAG);

    }

    @Overridepublic void More ...run() {

    mAllVCardFileList = new Vector();try {

    mWakeLock.acquire();getVCardFileRecursively(mRootDirectory);

    } catch (CanceledException e) {mCanceled = true;

    } catch (IOException e) {mGotIOException = true;

    } finally {mWakeLock.release();

  • 7/29/2019 Import Contact

    11/18

    }

    if (mCanceled) {mAllVCardFileList = null;

    }

    mProgressDialogForScanVCard.dismiss();mProgressDialogForScanVCard = null;

    if (mGotIOException) {runOnUIThread(new DialogDisplayer(R.id.dialog_io_exception));

    } else if (mCanceled) {finish();

    } else {int size = mAllVCardFileList.size();final Context context = ImportVCardActivity.this;if (size == 0) {

    runOnUIThread(new DialogDisplayer(R.id.dialog_vcard_not_found));

    } else {startVCardSelectAndImport();

    }}

    }

    private void More ...getVCardFileRecursively(File directory)throws CanceledException, IOException {

    if (mCanceled) {throw new CanceledException();

    }

    // e.g. secured directory may return null toward listFiles().final File[] files = directory.listFiles();if (files == null) {

    Log.w(LOG_TAG, "listFiles() returned null (directory: " + directory + ")");

    return;

    }for (File file : directory.listFiles()) {if (mCanceled) {

    throw new CanceledException();}String canonicalPath = file.getCanonicalPath();if (mCheckedPaths.contains(canonicalPath)) {

    continue;}

    mCheckedPaths.add(canonicalPath);

    if (file.isDirectory()) {

    getVCardFileRecursively(file);} else if (canonicalPath.toLowerCase().endsWith(".vcf") &&

    file.canRead()){String fileName = file.getName();VCardFile vcardFile = new VCardFile(

    fileName, canonicalPath, file.lastModified());mAllVCardFileList.add(vcardFile);

    }}

    }

  • 7/29/2019 Import Contact

    12/18

    public void More ...onCancel(DialogInterface dialog) {mCanceled = true;

    }

    public void More ...onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_NEGATIVE) {

    mCanceled = true;}

    }}

    private void More ...startVCardSelectAndImport() {int size = mAllVCardFileList.size();if (getResources().getBoolean(R.bool.config_import_all_vcard_from_sdcard

    _automatically)) {importMultipleVCardFromSDCard(mAllVCardFileList);

    } else if (size == 1) {String canonicalPath = mAllVCardFileList.get(0).getCanonicalPath();Uri uri = Uri.parse("file://" + canonicalPath);importOneVCardFromSDCard(uri);

    } else if (getResources().getBoolean(R.bool.config_allow_users_select_all_vcard_import)) {

    runOnUIThread(new DialogDisplayer(R.id.dialog_select_import_type));

    } else {runOnUIThread(new DialogDisplayer(R.id.dialog_select_one_vcard));}

    }

    private void More ...importMultipleVCardFromSDCard(final List selectedVCardFileList) {

    runOnUIThread(new Runnable() {public void More ...run() {

    mVCardReadThread = new VCardReadThread(selectedVCardFileList);showDialog(R.id.dialog_reading_vcard);

    }});

    }

    private void More ...importOneVCardFromSDCard(final Uri uri) {runOnUIThread(new Runnable() {

    public void More ...run() {mVCardReadThread = new VCardReadThread(uri);showDialog(R.id.dialog_reading_vcard);

    }});

    }

    private Dialog More ...getSelectImportTypeDialog() {DialogInterface.OnClickListener listener =

    new ImportTypeSelectedListener();AlertDialog.Builder builder = new AlertDialog.Builder(this)

    .setTitle(R.string.select_vcard_title)

    .setPositiveButton(android.R.string.ok, listener)

    .setOnCancelListener(mCancelListener)

    .setNegativeButton(android.R.string.cancel, mCancelListener);

    String[] items = new String[ImportTypeSelectedListener.IMPORT_TYPE_SIZE];

    items[ImportTypeSelectedListener.IMPORT_ONE] =

  • 7/29/2019 Import Contact

    13/18

    getString(R.string.import_one_vcard_string);items[ImportTypeSelectedListener.IMPORT_MULTIPLE] =

    getString(R.string.import_multiple_vcard_string);items[ImportTypeSelectedListener.IMPORT_ALL] =

    getString(R.string.import_all_vcard_string);builder.setSingleChoiceItems(items, ImportTypeSelectedListener.IMPORT_ON

    E, listener);return builder.create();

    }

    private Dialog More ...getVCardFileSelectDialog(boolean multipleSelect) {int size = mAllVCardFileList.size();VCardSelectedListener listener = new VCardSelectedListener(multipleSelec

    t);AlertDialog.Builder builder =

    new AlertDialog.Builder(this).setTitle(R.string.select_vcard_title).setPositiveButton(android.R.string.ok, listener).setOnCancelListener(mCancelListener).setNegativeButton(android.R.string.cancel, mCancelListener);

    CharSequence[] items = new CharSequence[size];DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");for (int i = 0; i < size; i++) {

    VCardFile vcardFile = mAllVCardFileList.get(i);SpannableStringBuilder stringBuilder = new SpannableStringBuilder();stringBuilder.append(vcardFile.getName());stringBuilder.append('\n');int indexToBeSpanned = stringBuilder.length();// Smaller date text looks better, since each file name becomes easi

    er to read.// The value set to RelativeSizeSpan is arbitrary. You can change it

    to any other// value (but the value bigger than 1.0f would not make nice appeara

    nce :)stringBuilder.append(

    "(" + dateFormat.format(new Date(vcardFile.getLastModifi

    ed())) + ")");stringBuilder.setSpan(new RelativeSizeSpan(0.7f), indexToBeSpanned, stringBuilder.

    length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

    items[i] = stringBuilder;}if (multipleSelect) {

    builder.setMultiChoiceItems(items, (boolean[])null, listener);} else {

    builder.setSingleChoiceItems(items, 0, listener);}return builder.create();

    }

    @Overrideprotected void More ...onCreate(Bundle bundle) {

    super.onCreate(bundle);

    final Intent intent = getIntent();if (intent != null) {

    final String accountName = intent.getStringExtra("account_name");final String accountType = intent.getStringExtra("account_type");

  • 7/29/2019 Import Contact

    14/18

    if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {

    mAccount = new Account(accountName, accountType);}

    } else {Log.e(LOG_TAG, "intent does not exist");

    }

    // The caller often does not know account information at all, so we showthe UI instead.

    if (mAccount == null) {// There's three possibilities:// - more than one accounts -> ask the user// - just one account -> use the account without asking the user// - no account -> use phone-local storage without asking the userfinal Sources sources = Sources.getInstance(this);final List accountList = sources.getAccounts(true);final int size = accountList.size();if (size > 1) {

    final int resId = R.string.import_from_sdcard;mAccountSelectionListener =

    new AccountSelectionUtil.AccountSelectedListener(this, accountList, resId) {

    @Override

    public void More ...onClick(DialogInterface dialog, int which) {dialog.dismiss();mAccount = mAccountList.get(which);// Instead of using Intent mechanism, call the relevant

    private method,// to avoid throwing an Intent to itself again.startImport();

    }};showDialog(resId);return;

    } else {

    mAccount = size > 0 ? accountList.get(0) : null;}}

    startImport();}

    private void More ...startImport() {Intent intent = getIntent();final String action = intent.getAction();final Uri uri = intent.getData();Log.v(LOG_TAG, "action = " + action + " ; path = " + uri);if (Intent.ACTION_VIEW.equals(action)) {

    // Import the file directly and then go to EDIT screenmNeedReview = true;

    }

    if (uri != null) {importOneVCardFromSDCard(uri);

    } else {doScanExternalStorageAndImportVCard();

    }}

  • 7/29/2019 Import Contact

    15/18

    @Overrideprotected Dialog More ...onCreateDialog(int resId) {

    switch (resId) {case R.string.import_from_sdcard: {

    if (mAccountSelectionListener == null) {throw new NullPointerException(

    "mAccountSelectionListener must not be null.");}return AccountSelectionUtil.getSelectAccountDialog(this, resId,

    mAccountSelectionListener,new CancelListener());

    }case R.id.dialog_searching_vcard: {

    if (mProgressDialogForScanVCard == null) {String title = getString(R.string.searching_vcard_title);String message = getString(R.string.searching_vcard_message)

    ;mProgressDialogForScanVCard =

    ProgressDialog.show(this, title, message, true, false);mProgressDialogForScanVCard.setOnCancelListener(mVCardScanTh

    read);mVCardScanThread.start();

    }

    return mProgressDialogForScanVCard;}case R.id.dialog_sdcard_not_found: {

    AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle(R.string.no_sdcard_title).setIcon(android.R.drawable.ic_dialog_alert).setMessage(R.string.no_sdcard_message).setOnCancelListener(mCancelListener).setPositiveButton(android.R.string.ok, mCancelListener);

    return builder.create();}case R.id.dialog_vcard_not_found: {

    String message = (getString(R.string.scanning_sdcard_failed_mess

    age, getString(R.string.fail_reason_no_vcard_file)));AlertDialog.Builder builder = new AlertDialog.Builder(this)

    .setTitle(R.string.scanning_sdcard_failed_title)

    .setMessage(message)

    .setOnCancelListener(mCancelListener)

    .setPositiveButton(android.R.string.ok, mCancelListener);return builder.create();

    }case R.id.dialog_select_import_type: {

    return getSelectImportTypeDialog();}case R.id.dialog_select_multiple_vcard: {

    return getVCardFileSelectDialog(true);}case R.id.dialog_select_one_vcard: {

    return getVCardFileSelectDialog(false);}case R.id.dialog_reading_vcard: {

    if (mProgressDialogForReadVCard == null) {String title = getString(R.string.reading_vcard_title);String message = getString(R.string.reading_vcard_message);mProgressDialogForReadVCard = new ProgressDialog(this);

  • 7/29/2019 Import Contact

    16/18

    mProgressDialogForReadVCard.setTitle(title);mProgressDialogForReadVCard.setMessage(message);mProgressDialogForReadVCard.setProgressStyle(ProgressDialog.

    STYLE_HORIZONTAL);mProgressDialogForReadVCard.setOnCancelListener(mVCardReadTh

    read);mVCardReadThread.start();

    }return mProgressDialogForReadVCard;

    }case R.id.dialog_io_exception: {

    String message = (getString(R.string.scanning_sdcard_failed_message,

    getString(R.string.fail_reason_io_error)));AlertDialog.Builder builder = new AlertDialog.Builder(this)

    .setTitle(R.string.scanning_sdcard_failed_title)

    .setIcon(android.R.drawable.ic_dialog_alert)

    .setMessage(message)

    .setOnCancelListener(mCancelListener)

    .setPositiveButton(android.R.string.ok, mCancelListener);return builder.create();

    }case R.id.dialog_error_with_message: {

    String message = mErrorMessage;

    if (TextUtils.isEmpty(message)) {Log.e(LOG_TAG, "Error message is null while it must not.");message = getString(R.string.fail_reason_unknown);

    }AlertDialog.Builder builder = new AlertDialog.Builder(this)

    .setTitle(getString(R.string.reading_vcard_failed_title))

    .setIcon(android.R.drawable.ic_dialog_alert)

    .setMessage(message)

    .setOnCancelListener(mCancelListener)

    .setPositiveButton(android.R.string.ok, mCancelListener);return builder.create();

    }}

    return super.onCreateDialog(resId);}

    @Overrideprotected void More ...onPause() {

    super.onPause();if (mVCardReadThread != null) {

    // The Activity is no longer visible. Stop the thread.mVCardReadThread.cancel();mVCardReadThread = null;

    }

    // ImportVCardActivity should not be persistent. In other words, if there's some

    // event calling onPause(), this Activity should finish its work and give the main

    // screen back to the caller Activity.if (!isFinishing()) {

    finish();}

    }

  • 7/29/2019 Import Contact

    17/18

    @Overrideprotected void More ...onDestroy() {

    // The code assumes the handler runs on the UI thread. If not,// clearing the message queue is not enough, one would have to// make sure that the handler does not run any callback when// this activity isFinishing().

    // Need to make sure any worker thread is done before we flush and// nullify the message handler.if (mVCardReadThread != null) {

    Log.w(LOG_TAG, "VCardReadThread exists while this Activity is now being killed!");

    mVCardReadThread.cancel();int attempts = 0;while (mVCardReadThread.isAlive() && attempts < 10) {

    try {Thread.currentThread().sleep(20);

    } catch (InterruptedException ie) {// Keep on going until max attempts is reached.

    }attempts++;

    }if (mVCardReadThread.isAlive()) {

    // Find out why the thread did not exit in a timely

    // fashion. Last resort: increase the sleep duration// and/or the number of attempts.Log.e(LOG_TAG, "VCardReadThread is still alive after max attempt

    s.");}mVCardReadThread = null;

    }

    // Callbacks messages have what == 0.if (mHandler.hasMessages(0)) {

    mHandler.removeMessages(0);}

    mHandler = null; // Prevents memory leaks by breaking any circular dependency.super.onDestroy();

    }

    private void More ...runOnUIThread(Runnable runnable) {if (mHandler == null) {

    Log.w(LOG_TAG, "Handler object is null. No dialog is shown.");} else {

    mHandler.post(runnable);}

    }

    @Overridepublic void More ...finalize() {

    // TODO: This should not be needed. Throw exception instead.if (mVCardReadThread != null) {

    // Not sure this procedure is really needed, but just in case...Log.e(LOG_TAG, "VCardReadThread exists while this Activity is now be

    ing killed!");mVCardReadThread.cancel();mVCardReadThread = null;

    }

  • 7/29/2019 Import Contact

    18/18

    }

    private void More ...doScanExternalStorageAndImportVCard() {// TODO: should use getExternalStorageState().final File file = Environment.getExternalStorageDirectory();if (!file.exists() || !file.isDirectory() || !file.canRead()) {

    showDialog(R.id.dialog_sdcard_not_found);} else {

    mVCardScanThread = new VCardScanThread(file);showDialog(R.id.dialog_searching_vcard);

    }}

    }