Upload
farhakim-effakim
View
217
Download
0
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);
}}
}