How could i run the android method that extract the contact list in a vcf format?
Is there an intent that can directly call this action?
thx
François
This may be helpful to you. Try this with your need -
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();
}
}
}
Here's how to extract to VCF file and share it via an intent, with the option of sharing a single contact if you wish:
#WorkerThread
#Nullable
public static Intent getContactShareIntent(#NonNull Context context, #Nullable String contactId, #NonNull String filePath) {
final ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = TextUtils.isEmpty(contactId) ? contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null) :
contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, Data.CONTACT_ID + "=?", new String[]{contactId}, null);
if (cursor == null || !cursor.moveToFirst())
return null;
final File file = new File(filePath);
file.delete();
do {
String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
AssetFileDescriptor fd;
try {
fd = contentResolver.openAssetFileDescriptor(uri, "r");
if (fd == null)
return null;
FileInputStream fis = fd.createInputStream();
IOUtils.copy(fis, new FileOutputStream(filePath, false));
cursor.moveToNext();
} catch (Exception e1) {
e1.printStackTrace();
}
} while (cursor.moveToNext());
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
intent.setType("*/*");
return intent;
}
You can do this manually in the contacts App. But there is no Intent for that. If you want your App to have such an export you unfortunately have to write it yourself or use code from here.vcardio
This has changed as of Sept., 2016. You can now export your contacts to a VCF file using the 'People' app: select 'Import/export' in the menu, then one of the export items. You'll still have to get the file off your phone but that's easy enough via ADB (or maybe email.)
Related
Hi guys i have this code which i use to get contacts from the phone and store them in vcf format,the code works properly for contacts that have only one number but i keep getting duplicates for contacts with multiple numbers i.e contacts that have home number,work number e.t.c...any help will be appreciated.....this is my code below
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
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 Show_contacts extends Activity {
Cursor cursor;
ArrayList<String> vCard;
String vfile;
static Context mContext;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = Show_contacts.this;
getVCF();
}
public static void getVCF() {
final String vfile = "Contacts.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);
mFileOutputStream.close();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
We have to check lookupKey. It works for me.
Cursor cursor;
ArrayList<String> vCard;
Context mContext;
ArrayList<String> saveLkKey;
String vcfFile;
String currentTime;
String rootStorage;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.save_contact_fragment, container,
false);
mContext = getActivity();
rootStorage = Environment.getExternalStorageDirectory() + "/";
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
currentTime = today.monthDay + "" + (today.month + 1) + "" + today.year
+ "-" + today.format("%k%M%S") + "";
vcfFile = "myContacts" + currentTime + ".vcf";
Button btnSaveVcf = (Button) view.findViewById(R.id.btnSave1);
btnSaveVcf.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
getVCF(vcfFile);
}
});
return view;
}
public void getVCF(String vfile) {
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));
lookupKey = lookupKey.trim();
if (saveLkKey == null) {
saveLkKey = new ArrayList<String>();
saveLkKey.add(lookupKey);
} else {
if (isDuplicate(lookupKey)) {
phones.moveToNext();
continue;
} else {
saveLkKey.add(lookupKey);
}
}
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 = rootStorage + vfile;
FileOutputStream mFileOutputStream = new FileOutputStream(path,
true);
mFileOutputStream.write(VCard.toString().getBytes());
phones.moveToNext();
Log.d("Vcard", VCard);
mFileOutputStream.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
public boolean isDuplicate(String lkKey) {
for (String s : saveLkKey) {
if (s.equals(lkKey)) {
return true;
}
}
return false;
}
In my application, a number of contacts are attached to single .vcf file and that file sent to mail, try to this one all contacts data display in log cat, but unable to send all data attached to single .vcf file?
Anyone have an idea regarding this help me, please.
here is my code
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
vCard = new ArrayList<String>();
Log.i("TAG one", "vfile" +vfile);
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 Contact 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() {
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
Log.i("TAG two", "cursor" +cursor);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
Log.i("Number of contacts", "cursorCount" +cursor.getCount());
for (int i = 0; i < cursor.getCount(); i++) {
get(cursor);
Log.i("TAG send contacts", "Contact " + (i + 1) + "VcF String is" + vCard.get(i));
cursor.moveToNext();
}
StringBuffer s = new StringBuffer();
s.append( vCard.toString());
string = s.toString();
file = new File(string);
// Log.i("s", ""+s);
// Log.i("string", ""+string);
Log.i("file", ""+file);
} else {
Log.i("TAG", "No Contacts in Your Phone");
}
}
public void get(Cursor cursor) {
String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Log.i("lookupKey", ""+lookupKey);
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
try {
AssetFileDescriptor 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);
String storage_path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
FileOutputStream mFileOutputStream = new FileOutputStream(storage_path, true);
mFileOutputStream.write(vcardstring.toString().getBytes());
vCard.add(storage_path);
} catch (Exception e1) {
e1.printStackTrace();
}
}
private void data() {
File filelocation = file;
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("vnd.android.cursor.dir/email");
sharingIntent.setType("application/x-vcard");
sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://"+filelocation));
startActivity(Intent.createChooser(sharingIntent, "Send email"));
}
}
finally my issue is solved using like this
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mContext = this;
button = (Button) findViewById(R.id.send);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
data();
}
});
/**
* This Function For Vcard And here i take one Array List in Which i
* store every Vcard String of Every Contact 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();
}
public static void getVcardString() {
String path = null;
String vfile = null;
vfile = "Contacts.vcf";
Cursor phones = mContext.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
null, null, null);
phones.moveToFirst();
Log.i("Number of contacts", "cursorCount" +phones.getCount());
for(int i =0;i<phones.getCount();i++) {
String lookupKey = phones.getString(phones.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Log.i("lookupKey", " " +lookupKey);
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);
path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
FileOutputStream mFileOutputStream = new FileOutputStream(path, true);
mFileOutputStream.write(VCard.toString().getBytes());
phones.moveToNext();
filevcf = new File(path);
Log.i("file", "file" +filevcf);
}catch(Exception e1) {
e1.printStackTrace();
}
}
Log.i("TAG", "No Contacts in Your Phone");
}
protected void data() {
File filelocation = filevcf ;
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("vnd.android.cursor.dir/email");
sharingIntent.setType("application/x-vcard");
sharingIntent.putExtra(Intent.EXTRA_EMAIL, "mail#gmail.com" );
sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://"+filelocation.getAbsolutePath()));
startActivity(Intent.createChooser(sharingIntent, "Send email"));
}
I successfully tested the following. Changes to your code are indicated with comments beginning with "CHANGE:". Don't forget to have android.permission.WRITE_EXTERNAL_STORAGE in your manifest.
public class MainActivity extends Activity {
private String vfile;
private Cursor cursor;
private ArrayList<String> vCard;
private String string;
private File file;
private String storage_path; //CHANGE: storage_path global
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vCard = new ArrayList<String>();
Log.i("TAG one", "vfile" + vfile);
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 Contact 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();
data(); //CHANGE: now calling data to send vCard intent
}
private void getVcardString() {
cursor = getContentResolver().
query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, null, null, null);
Log.i("TAG two", "cursor" +cursor);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
Log.i("Number of contacts", "cursorCount" +cursor.getCount());
for (int i = 0; i < cursor.getCount(); i++) {
get(cursor);
Log.i("TAG send contacts",
"Contact " + (i + 1) + "VcF String is" + vCard.get(i));
cursor.moveToNext();
}
// StringBuffer s = new StringBuffer(); CHANGE: not needed
// s.append( vCard.toString());
// string = s.toString();
// file = new File(string); //CHANGE: this is not what file should be
} else {
Log.i("TAG", "No Contacts in Your Phone");
}
}
public void get(Cursor cursor) {
String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Log.i("lookupKey", ""+lookupKey);
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);
try {
AssetFileDescriptor 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); //CHANGE: added this, so log statement in above method doesn't generate error
// String storage_path = Environment.getExternalStorageDirectory().toString() + File.separator + vfile;
//CHANGE: this is the path we need to get file for intent:
storage_path = getExternalFilesDir(null).toString() + File.separator + vfile;
Log.i("MainActivity", storage_path);
//CHANGE: this will create the file we need:
file = new File(getExternalFilesDir(null), vfile);
file.createNewFile(); //CHANGE
//CHANGE: this will create the stream we need:
FileOutputStream mFileOutputStream = new FileOutputStream(file, true);
mFileOutputStream.write(vcardstring.toString().getBytes());
mFileOutputStream.close(); //don't forget to close
// vCard.add(storage_path); //CHANGE: not needed
} catch (Exception e1) {
e1.printStackTrace();
}
}
private void data() {
// File filelocation = file; //CHANGE: not what we need
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("vnd.android.cursor.dir/email");
sharingIntent.setType("application/x-vcard");
//CHANGE: using correct path:
sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(storage_path));
startActivity(Intent.createChooser(sharingIntent, "Send email"));
}
}
how can i get the Contact ID and Contact group? i have used the following code which gives me the name and phone any all other info but not the id or the group
public void ExportContacts() {
vCard = new ArrayList<String>();
cursor = mContext.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
int ss = cursor.getCount();
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 {
String _id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
fd = mContext.getContentResolver().openAssetFileDescriptor(uri, "_ID");
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, true);
mFileOutputStream.write(vcardstring.toString().getBytes());
} catch (Exception e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
i want to put the ID and the Group name in the vCard that i write in file. can any one help?
Depending on which ID you want, you can use this or this for the ID field.
Group name is potentially somewhat messier: this is the row for group title, which may be what you need, but you probably need to do the appropriate error checking in case there isn't a group defined.
EDIT: Group ID you can find here.
i am making .vcf file off all contacts stored in contacts list and save it in sdcard as well but all .vcf file are storing sepratly in my SDCARD , iwant to make a folder in side Sdcard and save all the .vcf file inside it...and finally get the path of folder and able to mail it in email id..so how to make a folder to save all .vcf file inside it if there are thousands of contacts in contact list of my device.
my code for making .vcf and save it in sdcard are below. pls modified on the same or provide some new idea...
private void getVcardString() {
int j=0;
// TODO Auto-generated method stub
vCard = new ArrayList<String>();
cursor = getContentResolver().query(ContactsContract.Contacts.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));
publishProgress(Integer.toString(j));
j++;
cursor.moveToNext();
}
csv_status = true;
}
else
{
Log.d("TAG", "No Contacts in Your Phone");
}
}
public void get(Cursor cursor)
{
vfile = "Contacts" + "_" + System.currentTimeMillis()+".vcf";
//String vfile = "Contacts"+".vcf";
//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 = CsvSender.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);
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();
}
}
Similar threads here do not have answers that helped...
I want to create email message with file attach, file is on internal storage.
Here is code:
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_EMAIL , new String[]{email});
i.putExtra(Intent.EXTRA_SUBJECT, "Smart Weight Tracker");
i.putExtra(Intent.EXTRA_TEXT , "CSV file is in attachment");
Uri uri;
if(useExternal){
uri = Uri.fromFile(new File(this.getExternalFilesDir(null),fname));
}
else{
File f = new File(this.getFilesDir(),fname);
f.setReadable(true, false);
f.setWritable(true, false);
uri = Uri.fromFile(f);
}
i.putExtra(Intent.EXTRA_STREAM, uri);
try {
startActivity(Intent.createChooser(i, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(MainActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
It works perfectly with external storage, but i have no attach when use internal storage.
I checked - file opens, (it's length in my app by showing Toast - is OK, > 0).
I write it this way:
OutputStreamWriter out =
new OutputStreamWriter(con.openFileOutput(fname, Context.MODE_WORLD_READABLE));
In logcat i see
I/Gmail (28480): >>>>> Attachment uri: file:///data/data/Android.MyApp/files /31.10.2011.csv
I/Gmail (28480): >>>>> type: text/plain
I/Gmail (28480): >>>>> name: 31.10.2011.csv
I/Gmail (28480): >>>>> size: 0
Size == 0!
Any ideas?
Hi,
Try to use content providers.
emailIntent.putExtra(Intent.EXTRA_STREAM,Uri.parse("content://" + CachedFileProvider.AUTHORITY + "/"+ fileName));
........
Android: Attaching files from internal cache to Gmail
package com.stephendnicholas.gmailattach;
import java.io.File;
import java.io.FileNotFoundException;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.util.Log;
public class CachedFileProvider extends ContentProvider {
private static final String CLASS_NAME = "CachedFileProvider";
// The authority is the symbolic name for the provider class
public static final String AUTHORITY = "com.stephendnicholas.gmailattach.provider";
// UriMatcher used to match against incoming requests
private UriMatcher uriMatcher;
#Override
public boolean onCreate() {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// Add a URI to the matcher which will match against the form
// 'content://com.stephendnicholas.gmailattach.provider/*'
// and return 1 in the case that the incoming Uri matches this pattern
uriMatcher.addURI(AUTHORITY, "*", 1);
return true;
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
String LOG_TAG = CLASS_NAME + " - openFile";
Log.v(LOG_TAG,
"Called with uri: '" + uri + "'." + uri.getLastPathSegment());
// Check incoming Uri against the matcher
switch (uriMatcher.match(uri)) {
// If it returns 1 - then it matches the Uri defined in onCreate
case 1:
// The desired file name is specified by the last segment of the
// path
// E.g.
// 'content://com.stephendnicholas.gmailattach.provider/Test.txt'
// Take this and build the path to the file
String fileLocation = getContext().getCacheDir() + File.separator
+ uri.getLastPathSegment();
// Create & return a ParcelFileDescriptor pointing to the file
// Note: I don't care what mode they ask for - they're only getting
// read only
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(
fileLocation), ParcelFileDescriptor.MODE_READ_ONLY);
return pfd;
// Otherwise unrecognised Uri
default:
Log.v(LOG_TAG, "Unsupported uri: '" + uri + "'.");
throw new FileNotFoundException("Unsupported uri: "
+ uri.toString());
}
}
// //////////////////////////////////////////////////////////////
// Not supported / used / required for this example
// //////////////////////////////////////////////////////////////
#Override
public int update(Uri uri, ContentValues contentvalues, String s,
String[] as) {
return 0;
}
#Override
public int delete(Uri uri, String s, String[] as) {
return 0;
}
#Override
public Uri insert(Uri uri, ContentValues contentvalues) {
return null;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public Cursor query(Uri uri, String[] projection, String s, String[] as1,
String s1) {
return null;
}
}
<provider android:name="CachedFileProvider" android:authorities="com.stephendnicholas.gmailattach.provider">
public static void createCachedFile(Context context, String fileName,
String content) throws IOException {
File cacheFile = new File(context.getCacheDir() + File.separator
+ fileName);
cacheFile.createNewFile();
FileOutputStream fos = new FileOutputStream(cacheFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
PrintWriter pw = new PrintWriter(osw);
pw.println(content);
pw.flush();
pw.close();
}
public static Intent getSendEmailIntent(Context context, String email,
String subject, String body, String fileName) {
final Intent emailIntent = new Intent(
android.content.Intent.ACTION_SEND);
//Explicitly only use Gmail to send
emailIntent.setClassName("com.google.android.gm","com.google.android.gm.ComposeActivityGmail");
emailIntent.setType("plain/text");
//Add the recipients
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
new String[] { email });
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, body);
//Add the attachment by specifying a reference to our custom ContentProvider
//and the specific file of interest
emailIntent.putExtra(
Intent.EXTRA_STREAM,
Uri.parse("content://" + CachedFileProvider.AUTHORITY + "/"
+ fileName));
return emailIntent;
}
http://stephendnicholas.com/archives/974#comment-342
Uri fileUri = Uri.fromFile(new File(context.getCacheDir()+ "/"+ fileName));
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/plain");
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
"Test Subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,
"go on read the emails");
emailIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
startActivity(emailIntent);
Please try this code. Hope this would help.
I was following the stephendnicholas code for hours thinking I HAD to write my files to internal storage because my device had no sd card.
Creating my "internal" file like this worked just fine for me:
File file = new File(getExternalFilesDir(null), filename); // :)
It avoided Gmail limitations during attachment.
Before this I was creating my file object like this:
File file = new File(this.getFilesDir(), filename); //will not attach
But if your file is literally from internal storage, then stephendnicholas content providers etc. work if you have mad android skills.