0

I'm trying to export my contacts to vCard format with this code :

(found here : http://androidcodeexamples.blogspot.in/2012/06/export-contacts-as-vcf-file-in-android.html)

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();
               }
        }

But I have an exception caused by the fis.read(buf) I think.

The exception is : "read failed : EINVAL (Invalid argument)."

Can someone help me please?

Thank you! :)

jcavandoli
  • 297
  • 2
  • 9

4 Answers4

1

I just saw the same behavior (tried emulator with Android 4.0.3 and 4.1.2). It works fine on a real device and doesn't work on emulator.

Victor Ronin
  • 22,758
  • 18
  • 92
  • 184
1
package com.example.temp;

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

  import android.app.Activity;
  import android.content.Context;
  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;

  public class MainActivity extends Activity {
Cursor cursor;
ArrayList<String> vCard;
String vfile;
static Context mContext;

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = MainActivity.this;
        getVCF();
    }

    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");
                FileDescriptor fdd = fd.getFileDescriptor();
                InputStream in = new FileInputStream(fdd);
                //FileInputStream fis = fd.createInputStream();
                Log.d("BLA BLA", "Len is :: " + (int) fd.getDeclaredLength());
                byte[] buf = new byte[(int) fd.getDeclaredLength()];
                in.read(buf);
                fd.close();
                String VCard = new String(buf);
                String path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
                FileOutputStream mFileOutputStream = new FileOutputStream(path, true);
                mFileOutputStream.write(VCard.toString().getBytes());
                mFileOutputStream.close();
                in.close();
                phones.moveToNext();
                Log.d("Vcard", VCard);

            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }
    }
}
Rohit
  • 3,401
  • 4
  • 33
  • 60
0

getDeclaredLength returns -1 if the AssetFileDescriptor is not initialized with length.
You would be better off using getStatSize() in this case.

nandeesh
  • 24,740
  • 6
  • 69
  • 79
  • Thank for your answer! I tried with `byte[] buf = new byte[(int) fd.getParcelFileDescriptor().getStatSize()];` Now I have `"java.lang.NegativeArraySizeException : -1"`. So it means that my fd "is not a file"... Do you have an idea why? – jcavandoli Aug 24 '12 at 00:26
  • i am not too sure why. But you could take an arbitrary number and keep reading from the stream until you reach end of stream – nandeesh Aug 24 '12 at 07:27
  • 1
    It's working on a real phone!! can't figure out why not on the emulator... Thank anyway – jcavandoli Aug 25 '12 at 12:21
0

I had the same exception, but on a real device. The problem was one contact which had emails with undefined email type

Marian Klühspies
  • 15,824
  • 16
  • 93
  • 136