14

I want to export the Phone contacts to External storage area. I didn't work with this type of method. Anyone guide me to do this?

Praveenkumar
  • 24,084
  • 23
  • 95
  • 173

8 Answers8

29

In your code, you wrote one function but from where is this function called? And what is the meaning of get(View view) function? This function is not being called so it can be removed.

I've edited my answer as per your requirements and tested it with 500 Contacts to save a single vCard file with 500 contacts in my sd card.

package com.vcard;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;

import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.View;

public class VCardActivity extends Activity 
{
    Cursor cursor;
    ArrayList<String> vCard ;
    String vfile;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        vfile = "Contacts" + "_" + System.currentTimeMillis()+".vcf";
        /**This Function For Vcard And here i take one Array List in Which i store every Vcard String of Every Conatact
         * Here i take one Cursor and this cursor is not null and its count>0 than i repeat one loop up to cursor.getcount() means Up to number of phone contacts.
         * And in Every Loop i can make vcard string and store in Array list which i declared as a Global.
         * And in Every Loop i move cursor next and print log in logcat.
         * */
        getVcardString();

    }
    private void getVcardString() {
        // TODO Auto-generated method stub
        vCard = new ArrayList<String>();
        cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
        if(cursor!=null&&cursor.getCount()>0)
        {
            cursor.moveToFirst();
            for(int i =0;i<cursor.getCount();i++)
            {

                get(cursor);
                Log.d("TAG", "Contact "+(i+1)+"VcF String is"+vCard.get(i));
                cursor.moveToNext();
            }

        }
        else
        {
            Log.d("TAG", "No Contacts in Your Phone");
        }

    }

    public void get(Cursor cursor)
    {


        //cursor.moveToFirst();
        String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
        Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
        AssetFileDescriptor fd;
        try {
            fd = this.getContentResolver().openAssetFileDescriptor(uri, "r");

            // Your Complex Code and you used function without loop so how can you get all Contacts Vcard.??


           /* FileInputStream fis = fd.createInputStream();
            byte[] buf = new byte[(int) fd.getDeclaredLength()];
            fis.read(buf);
            String VCard = new String(buf);
            String path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
            FileOutputStream out = new FileOutputStream(path);
            out.write(VCard.toString().getBytes());
            Log.d("Vcard",  VCard);*/

            FileInputStream fis = fd.createInputStream();
            byte[] buf = new byte[(int) fd.getDeclaredLength()];
            fis.read(buf);
            String vcardstring= new String(buf);
            vCard.add(vcardstring);

            String storage_path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
            FileOutputStream mFileOutputStream = new FileOutputStream(storage_path, false);
            mFileOutputStream.write(vcardstring.toString().getBytes());

        } catch (Exception e1) 
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
}
tipycalFlow
  • 7,594
  • 4
  • 34
  • 45
sam_k
  • 5,983
  • 14
  • 76
  • 110
  • u have to bind YOur own Cursor than u should apply this code. – sam_k Nov 16 '11 at 06:45
  • java.lang.IllegalArgumentException: URI: content://com.android.contacts/contacts/as_vcard, calling user: com.android.phonecontacts, calling package:com.android.phonecontacts – Praveenkumar Nov 16 '11 at 07:06
  • 1
    When i run this code i've this exception. This is the full detail. – Praveenkumar Nov 16 '11 at 07:09
  • hello sam_k i want to send .vcf file to mail id but after using ur code i get all contact's seprate .vcf file on my external storage(SD card) but problem is mine is that how to write all .vcf file in one single file and send it via attachment, i know how to send mail in android but how to make .vcf of all contacts in single file if its possible..vv thanks – shyam Dec 13 '11 at 09:42
  • and can u also explain about .vcf and how to use it for our contacts in android as i have done with .csv – shyam Dec 13 '11 at 09:44
  • @shyam ya we can do in one file also dear – sam_k Dec 13 '11 at 10:04
  • @shyam Means You want to get all contacts in one file ?? if this is problem than send me code i will do and send back to you – sam_k Dec 13 '11 at 10:21
  • i only use ur above code for save contact information in sd card as.vcf file – shyam Dec 13 '11 at 10:26
  • but now how to send all the existing contacts as single .vcf file to any email id – shyam Dec 13 '11 at 10:59
  • hello sam_k i am waiting for ur response..sam_k i dont know more about vcard file and uses of vcf file can u pls explain it..and how to send .vcf file for all contacts as an attachment via mail – shyam Dec 13 '11 at 11:25
  • simple Attach the File vcard.vcf from SDcard than send it – sam_k Dec 13 '11 at 11:37
  • where is vcard.vcf file in sdcard...using our above code...there is only "Contacts" + "_" + System.currentTimeMillis()+".vcf"; named files in sd card where all vcf are diffrentiated by System.currentTimeMillis() method – shyam Dec 13 '11 at 11:49
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/5811/discussion-between-sam-k-and-shyam) – sam_k Dec 13 '11 at 12:06
  • @CautionContinues ya all contacts in one .vcf file – sam_k Nov 27 '12 at 08:06
  • I have not read all the above comments....What I saw in code based on that get() method will be called again and again till the last contact we have...hence these lines will also execute every time : String storage_path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile; FileOutputStream mFileOutputStream = new FileOutputStream(storage_path, false); mFileOutputStream.write(vcardstring.toString().getBytes());....hence @last we will have only one contact & I hv ran abov code & got wht I hv told in earlier lines. Hence I edited & posted again. – Caution Continues Nov 27 '12 at 08:57
  • @CautionContinues ya your are right. i will genrate multiple files for contacts. because the question requirement is like that ,dats y :) – sam_k Nov 27 '12 at 09:26
  • @ sam_k. I can't see any file .VCF in my device ! –  Feb 27 '18 at 10:50
  • (int) fd.getDeclaredLength() gives value -1. Any idea why? – Sumit Kumar Jun 22 '18 at 10:27
8

Android Nougat Update :

Other answers code working for lots of people before Nougat update.

Please take care of :

byte[] buf = new byte[(int) fd.getDeclaredLength()];

is not working on Android Nougat.

fd.getDeclaredLength() is always return -1.

Please use below code for read bytes without any library :

byte[] buf = readBytes(fis);

public byte[] readBytes(InputStream inputStream) throws IOException {
    // this dynamically extends to take the bytes you read
    ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();

    // this is storage overwritten on each iteration with bytes
    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];

    // we need to know how may bytes were read to write them to the byteBuffer
    int len = 0;
    while ((len = inputStream.read(buffer)) != -1) {
        byteBuffer.write(buffer, 0, len);
    }

    // and then we can return your byte array.
    return byteBuffer.toByteArray();
}

The method readBytes() get from this answer.

Community
  • 1
  • 1
SANAT
  • 8,489
  • 55
  • 66
  • I had this problem and had to post this [question](http://stackoverflow.com/q/42017591/4333665) – Balakrishna Avulapati Feb 13 '17 at 05:10
  • I am getting `java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.util.ArrayList.add(java.lang.Object)' on a null object reference` with this method. And `fd.getDeclaredLength()` is returning -1. – Shahbaz Talpur Oct 19 '17 at 15:30
  • @SANAT could you see please? – Shahbaz Talpur Oct 20 '17 at 06:52
  • @Shahbaz Talpur you are adding item to the list which is already null, means not initialized. Please initialize it before adding any data. fd.getDeclaredLength() return -1 in nougat, please use above code by passing your FileInputStrem to it. – SANAT Oct 20 '17 at 10:48
  • @SANAT I used your above code and it is giving me that null exception. I have passed my FileInputStream to it. – Shahbaz Talpur Oct 20 '17 at 11:05
  • @Shahbaz Talpur there is no java List and its add method in above readbytes() function. Please check your error's line number carefully. – SANAT Oct 20 '17 at 11:41
  • it's failed when number of contacts huge , error is FAILED BINDER TRANSACTION !!! (parcel size = 472) – iamkdblue Mar 20 '18 at 13:44
7

Try out this. its work for me to create a .vcf file of all contact and stored it into SDCARD.

make sure all permission are give properly.

public static void getVCF() 

{

 final String vfile = "POContactsRestore.vcf";

 Cursor phones = mContext.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null, null, null);

 phones.moveToFirst();
   for(int i =0;i<phones.getCount();i++)
   {
      String lookupKey =  phones.getString(phones.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
     Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);

    AssetFileDescriptor fd;
     try 
     {
         fd = mContext.getContentResolver().openAssetFileDescriptor(uri, "r");
         FileInputStream fis = fd.createInputStream();
         byte[] buf = new byte[(int) fd.getDeclaredLength()];
         fis.read(buf);
         String VCard = new String(buf);
         String path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
         FileOutputStream mFileOutputStream = new FileOutputStream(path, true);
                    mFileOutputStream.write(VCard.toString().getBytes());           
         phones.moveToNext();                           
         Log.d("Vcard",  VCard);
     } 
     catch (Exception e1) 
     {
          // TODO Auto-generated catch block
          e1.printStackTrace();
     }

 }
}
pratik
  • 983
  • 3
  • 13
  • 25
7

I have removed the exception and other error and below is my CODE :

    private final String vfile = "POContactsRestore.vcf";
    Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                    null, null, null);
            phones.moveToFirst();
            String lookupKey = phones.getString(phones.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
            Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
            AssetFileDescriptor fd;
            try {
                fd = this.getContentResolver().openAssetFileDescriptor(uri, "r");
                FileInputStream fis = fd.createInputStream();
                byte[] buf = new byte[(int) fd.getDeclaredLength()];
                fis.read(buf);
                String vCard = new String(buf);
                String path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
                FileOutputStream mFileOutputStream = new FileOutputStream(path, false);
                mFileOutputStream.write(vCard.toString().getBytes());
                Log.d("Vcard",  vCard);
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

If you can iterate through loop and get the vCard for the contacts and store it in the SDCARD.

Bruno Bieri
  • 9,724
  • 11
  • 63
  • 92
Dinesh Prajapati
  • 9,274
  • 5
  • 30
  • 47
6

I tried above two codes and I got the .VCF file too, but it was containing only one contact. so here is Perfectly Edited and running code....you will get all contacts in .VCF file:

private void getVcardString() throws IOException {
    // TODO Auto-generated method stub
    vCard = new ArrayList<String>();  // Its global....
    cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
    if(cursor!=null&&cursor.getCount()>0)
    {
        int i;
        String storage_path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
        FileOutputStream mFileOutputStream = new FileOutputStream(storage_path, false);
        cursor.moveToFirst();
        for(i = 0;i<cursor.getCount();i++)
        {
            get(cursor);
            Log.d("TAG", "Contact "+(i+1)+"VcF String is"+vCard.get(i));
            cursor.moveToNext();
            mFileOutputStream.write(vCard.get(i).toString().getBytes());
        }
        mFileOutputStream.close();
        cursor.close();
    }
    else
    {
        Log.d("TAG", "No Contacts in Your Phone");
    }
}

Second Method:

private void get(Cursor cursor2) {
    String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
    Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
    AssetFileDescriptor fd;
    try {
        fd = this.getContentResolver().openAssetFileDescriptor(uri, "r");

        FileInputStream fis = fd.createInputStream();
        byte[] buf = new byte[(int) fd.getDeclaredLength()];
        fis.read(buf);
        String vcardstring= new String(buf);
        vCard.add(vcardstring);
    } catch (Exception e1) 
    {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
}

Please Don't forget to add :

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Caution Continues
  • 743
  • 2
  • 10
  • 25
  • 1
    I have used above code and getting error in `fis.read(buf)`, `java.io.IOException: read failed: EINVAL (Invalid argument)` – Dharmik Jun 29 '13 at 05:03
  • I am using same method no issue at all...let me check – Caution Continues Sep 19 '13 at 07:20
  • Where r u testing I mean emulator or real device ??? and If you are using emulator then make sure that you have allocated some space to emulator SD cards coz we are writing .VCF file on SD cards. On real device I am not getting any problem....Pls check and let me know... – Caution Continues Sep 19 '13 at 07:21
1

It's working for me and as well working in Nougat devices. Thank you so much @pratik and @sanat .

public static void getVCF(Context context)
    {

        final String vfile = "POContactsRestore.vcf";

        Cursor phones = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null, null, null);

        phones.moveToFirst();
        for(int i =0;i<phones.getCount();i++)
        {
            String lookupKey =  phones.getString(phones.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
            Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);

            AssetFileDescriptor fd;
            try
            {
                fd = context.getContentResolver().openAssetFileDescriptor(uri, "r");
                FileInputStream fis = fd.createInputStream();
                byte[] buf = readBytes(fis);
                fis.read(buf);
                String VCard = new String(buf);
                String path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
                FileOutputStream mFileOutputStream = new FileOutputStream(path, true);
                mFileOutputStream.write(VCard.toString().getBytes());
                phones.moveToNext();
                Log.d("Vcard",  VCard);
            }
            catch (Exception e1)
            {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        }
    }

    public static byte[] readBytes(InputStream inputStream) throws IOException {
        // this dynamically extends to take the bytes you read
        ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();

        // this is storage overwritten on each iteration with bytes
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];

        // we need to know how may bytes were read to write them to the byteBuffer
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            byteBuffer.write(buffer, 0, len);
        }

        // and then we can return your byte array.
        return byteBuffer.toByteArray();
    }
iamkdblue
  • 3,448
  • 2
  • 25
  • 43
0
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.ContactsContract;
import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.util.Log;

public class Contacts extends Activity{

    Cursor cursor;
ArrayList<String> vCard ;
String vfile;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    try {
        getVcardString();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
private void getVcardString() throws IOException {

     final String vfile = "POContactsRestore.vcf";
    // TODO Auto-generated method stub
    vCard = new ArrayList<String>();
    cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
    if(cursor!=null&&cursor.getCount()>0)
    {
        int i;
        String storage_path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
        FileOutputStream mFileOutputStream = new FileOutputStream(storage_path, false);
        cursor.moveToFirst();
        for(i = 0;i<cursor.getCount();i++)
        {
            get(cursor);
            Log.d("TAG", "Contact "+(i+1)+"VcF String is"+vCard.get(i));
            cursor.moveToNext();
            mFileOutputStream.write(vCard.get(i).toString().getBytes());
        }
        mFileOutputStream.close();
        cursor.close();
    }
    else
    {
        Log.d("TAG", "No Contacts in Your Phone");
    }
}
private void get(Cursor cursor2) {
    String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
    Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
    AssetFileDescriptor fd;
    try {
        fd = this.getContentResolver().openAssetFileDescriptor(uri, "r");

        FileInputStream fis = fd.createInputStream();
        byte[] buf = new byte[(int) fd.getDeclaredLength()];
        fis.read(buf);
        String vcardstring= new String(buf);
        vCard.add(vcardstring);
    } catch (Exception e1) 
    {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
}





<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.anthem.contactbackup"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="5"
    android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".Con"
        android:label="@string/title_activity_contact_backup" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

kamal
  • 290
  • 3
  • 20
0
private void convertToVcfFile(String contactId, File contactFile) {
    Cursor mCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            null, ContactsContract.CommonDataKinds.Phone._ID + " = " + contactId,
            null, null);
    if(mCursor != null && mCursor.moveToFirst()) {
        do {
            String mLookupKey = mCursor.getString(mCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
            Uri mUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, mLookupKey);
            try {
                AssetFileDescriptor mAssetFileDescriptor = getContentResolver().openAssetFileDescriptor(mUri, "r");
                if (mAssetFileDescriptor != null) {
                    FileInputStream mFileInputStream = mAssetFileDescriptor.createInputStream();
                    byte[] mBuffer = new byte[(int) mAssetFileDescriptor.getDeclaredLength()];
                    mFileInputStream.read(mBuffer);
                    String VCardString = new String(mBuffer);
                    FileOutputStream mFileOutputStream = new FileOutputStream(contactFile, true);
                    mFileOutputStream.write(VCardString.getBytes());
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        } while (mCursor.moveToNext());
        mCursor.close();
    }
}
Akhtar
  • 91
  • 1
  • 2