com.nuvolect.securesuite.data.ExportVcf.java Source code

Java tutorial

Introduction

Here is the source code for com.nuvolect.securesuite.data.ExportVcf.java

Source

/*
 * Copyright (c) 2017. Nuvolect LLC
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * Contact legal@nuvolect.com for a less restrictive commercial license if you would like to use the
 * software without the GPLv3 restrictions.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program.  If not,
 * see <http://www.gnu.org/licenses/>.
 *
 */

package com.nuvolect.securesuite.data;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.support.v4.content.FileProvider;
import android.util.Base64;
import android.widget.Toast;

import com.nuvolect.securesuite.R;
import com.nuvolect.securesuite.data.SqlCipher.ATab;
import com.nuvolect.securesuite.data.SqlCipher.DTab;
import com.nuvolect.securesuite.data.SqlCipher.KvTab;
import com.nuvolect.securesuite.main.CConst;
import com.nuvolect.securesuite.util.LogUtil;
import com.nuvolect.securesuite.util.LogUtil.LogType;
import com.nuvolect.securesuite.util.Persist;
import com.nuvolect.securesuite.util.Util;

import net.sqlcipher.Cursor;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import ezvcard.Ezvcard;
import ezvcard.VCard;
import ezvcard.parameter.AddressType;
import ezvcard.parameter.EmailType;
import ezvcard.parameter.ImageType;
import ezvcard.parameter.TelephoneType;
import ezvcard.property.Address;
import ezvcard.property.Kind;
import ezvcard.property.Note;
import ezvcard.property.Photo;
import ezvcard.property.StructuredName;

public class ExportVcf {

    private static Activity m_act;
    private static Cursor m_cursor;

    public static void emailVcf(Activity act, long contact_id) {

        String messageTitle = "vCard for ";
        String messageBody = "\n\n\nContact from SecureSuite, a secure contact manager";

        try {
            String displayName = SqlCipher.get(contact_id, ATab.display_name);
            String fileName = displayName.replaceAll("\\W+", "");
            if (fileName.isEmpty())
                fileName = "contact";
            fileName = fileName + ".vcf";

            new File(act.getFilesDir() + CConst.SHARE_FOLDER).mkdirs();
            File vcf_file = new File(act.getFilesDir() + CConst.SHARE_FOLDER + fileName);

            writeContactVcard(contact_id, vcf_file);

            // Must match "authorities" in Manifest provider definition
            String authorities = act.getResources().getString(R.string.app_authorities) + ".provider";

            Uri uri = null;
            try {
                uri = FileProvider.getUriForFile(act, authorities, vcf_file);
            } catch (IllegalArgumentException e) {
                LogUtil.logException(act, LogType.EXPORT_VCF, e);
            }

            //convert from paths to Android friendly Parcelable Uri's
            ArrayList<Uri> uris = new ArrayList<Uri>();
            uris.add(uri);

            Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
            intent.setType("text/plain");
            intent.putExtra(Intent.EXTRA_SUBJECT, messageTitle + displayName);
            intent.putExtra(Intent.EXTRA_TEXT, messageBody);
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.putExtra("path", vcf_file.getAbsolutePath());

            intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
            act.startActivityForResult(Intent.createChooser(intent, "Share with..."),
                    CConst.RESPONSE_CODE_SHARE_VCF);

        } catch (Exception e) {
            LogUtil.logException(act, LogType.EXPORT_VCF, e);
        }
    }

    /**
     * Get the filename for exporting a vCard for a single contact.
     * @param contact_id
     * @return
     */
    public static String getExportFilename(long contact_id) {

        String displayName = SqlCipher.get(contact_id, ATab.display_name);
        String fileName = displayName.replaceAll("\\W+", "");
        if (fileName.isEmpty())
            fileName = "contact";
        fileName = fileName + ".vcf";

        return fileName;
    }

    /**
     * Create a vcard for a single contact record
     * @param contact_id
     * @param f1 to save vcard
     */
    public static void writeContactVcard(long contact_id, File f1) {

        VCard vcard = makeVcard(contact_id);

        try {
            Ezvcard.write(vcard).go(f1);

        } catch (IOException e) {
            LogUtil.logException(m_act, LogType.EXPORT_VCF, e);
        }
    }

    /**
     * Create a vCard file from a collection of contacts.
     * @param arrayListId
     * @param outputFile
     * @return
     */
    public static int writeContactVcard(ArrayList<Long> arrayListId, File outputFile) {

        outputFile.getParentFile().mkdirs();
        int count = 0;

        try {
            for (long id : arrayListId) {

                VCard vcard = makeVcard(id);
                if (count == 0)
                    Ezvcard.write(vcard).go(outputFile);
                else
                    Ezvcard.write(vcard).go(outputFile, true);
                ++count;
            }

        } catch (IOException e) {
            LogUtil.logException(m_act, LogType.EXPORT_VCF, e);
            count = -1;
        }
        String summary = "Exported " + count + " contacts to " + outputFile.getName();
        LogUtil.log(summary);

        return count;
    }

    /**
     * Create a single vcard from a contact record
     * @param contact_id
     * @return appended vcard
     */
    public static VCard makeVcard(long contact_id) {

        VCard vcard = new VCard();
        try {
            vcard.setKind(Kind.individual());
            vcard.addLanguage("en-US");

            String full_name = NameUtil.getFullName(contact_id);
            vcard.setFormattedName(full_name);
            {
                StructuredName n = new StructuredName();
                String prefix = SqlCipher.getKv(contact_id, KvTab.name_prefix);
                n.addPrefix(prefix);
                String first = SqlCipher.getKv(contact_id, KvTab.name_first);
                n.setGiven(first);
                String last = SqlCipher.getKv(contact_id, KvTab.name_last);
                n.setFamily(last);
                String suffix = SqlCipher.getKv(contact_id, KvTab.name_suffix);
                n.addSuffix(suffix);
                vcard.setStructuredName(n);

                //                if( prefix.isEmpty() && first.isEmpty() && last.isEmpty() && suffix.isEmpty())//TODO remove
                //                    n.setFamily(full_name);
            }
            {
                JSONArray itemArray = new JSONArray(SqlCipher.get(contact_id, DTab.address));
                for (int i = 0; i < itemArray.length(); i++) {

                    JSONObject item = itemArray.getJSONObject(i);
                    Iterator<?> item_keys = item.keys();
                    String item_label = (String) item_keys.next();
                    final String item_value = item.getString(item_label);

                    Address adr = new Address();
                    adr.setStreetAddress(item_value);
                    if (item_label.contentEquals("HOME"))
                        adr.addType(AddressType.HOME);
                    else if (item_label.contentEquals("WORK"))
                        adr.addType(AddressType.WORK);

                    vcard.addAddress(adr);
                }
            }
            {
                JSONArray itemArray = new JSONArray(SqlCipher.get(contact_id, DTab.phone));
                for (int i = 0; i < itemArray.length(); i++) {

                    JSONObject item = itemArray.getJSONObject(i);
                    Iterator<?> item_keys = item.keys();
                    String item_label = (String) item_keys.next();
                    final String item_value = item.getString(item_label);

                    TelephoneType type = null;
                    if (item_label.contentEquals("HOME"))
                        type = TelephoneType.HOME;
                    else if (item_label.contentEquals("WORK"))
                        type = TelephoneType.WORK;

                    if (type == null)
                        vcard.addTelephoneNumber(item_value);
                    else
                        vcard.addTelephoneNumber(item_value, type);
                }
            }
            {
                JSONArray itemArray = new JSONArray(SqlCipher.get(contact_id, DTab.email));
                for (int i = 0; i < itemArray.length(); i++) {

                    JSONObject item = itemArray.getJSONObject(i);
                    Iterator<?> item_keys = item.keys();
                    String item_label = (String) item_keys.next();
                    final String item_value = item.getString(item_label);

                    EmailType type = null;
                    if (item_label.contentEquals("HOME"))
                        type = EmailType.HOME;
                    else if (item_label.contentEquals("WORK"))
                        type = EmailType.WORK;

                    if (type == null)
                        vcard.addEmail(item_value);
                    else
                        vcard.addEmail(item_value, type);
                }
            }
            {
                JSONArray itemArray = new JSONArray(SqlCipher.get(contact_id, DTab.website));
                for (int i = 0; i < itemArray.length(); i++) {

                    JSONObject item = itemArray.getJSONObject(i);
                    Iterator<?> item_keys = item.keys();
                    String item_label = (String) item_keys.next();
                    final String item_value = item.getString(item_label);

                    vcard.addUrl(item_value);
                }
            }
            {
                String photoStr = SqlCipher.get(contact_id, DTab.photo);
                byte[] b = null;
                b = Base64.decode(photoStr.getBytes(), Base64.DEFAULT);
                Photo photo = new Photo(b, ImageType.PNG);
                vcard.addPhoto(photo);
            }
            {
                String noteStr = SqlCipher.getKv(contact_id, KvTab.note);
                Note note = vcard.addNote(noteStr); // can contain newlines
                note.setLanguage("en-us");
            }
            {
                String organization = SqlCipher.getKv(contact_id, KvTab.organization);
                vcard.setOrganization(organization, "");// second parameter is department
            }
            {
                String title = SqlCipher.getKv(contact_id, KvTab.title);
                vcard.addTitle(title);
            }
            //FUTURE export im
            //FUTURE export dates
            //FUTURE export relation

        } catch (JSONException e) {
            LogUtil.logException(m_act, LogType.EXPORT_VCF, e);
        }
        return vcard;
    }

    /** Export all contacts to a single vcard file */
    public static void exportAllVcardAsync(Activity act) {

        m_act = act;
        m_act.setProgressBarIndeterminateVisibility(true);

        // Cursor is closed in async task
        m_cursor = SqlCipher.getATabCursor();
        new ExportGroupVcardAsync().execute();
    }

    /** Export an account to a single vcard file */
    public static void exportAccountVcardAsync(Activity act, String account) {

        m_act = act;
        m_act.setProgressBarIndeterminateVisibility(true);

        // Cursor is closed in async task
        m_cursor = MyAccounts.getAccountCursor(account);
        new ExportGroupVcardAsync().execute();
    }

    /** Export a group to a single vcard file */
    public static void exportGroupVcardAsync(Activity act, int group_id) {

        m_act = act;
        m_act.setProgressBarIndeterminateVisibility(true);

        // Cursor is closed in async task
        m_cursor = MyGroups.getGroupContactsCursor(group_id);
        new ExportGroupVcardAsync().execute();
    }

    private static class ExportGroupVcardAsync extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... groups) {

            Util.createAppPublicFolder();
            String basePath = Environment.getExternalStorageDirectory() + CConst.FOLDER_NAME;

            int c_id_index = m_cursor.getColumnIndex("contact_id");

            String aVcf = Persist.getNextVcfFilename(m_act);
            File f1 = new File(basePath + "/" + aVcf);
            int count = 0;

            VCard vcard;
            while (m_cursor.moveToNext()) {

                long contact_id = m_cursor.getLong(c_id_index);
                if (contact_id <= 0)
                    break;

                vcard = makeVcard(contact_id);

                try {
                    Ezvcard.write(vcard).go(f1, true); // true == append
                    ++count;

                } catch (IOException e) {
                    LogUtil.logException(m_act, LogType.EXPORT_VCF, e);
                }
            }
            m_cursor.close();

            String summary = "Exported " + count + " contacts to " + aVcf;
            LogUtil.log(summary);

            return summary;
        }

        @Override
        protected void onPostExecute(String exportMsg) {

            Toast.makeText(m_act, exportMsg, Toast.LENGTH_LONG).show();
            m_act.setProgressBarIndeterminateVisibility(false);
        }
    }
}