0

I'm trying to create an option in my android app for the user to be able to export his data, without requiring extra permissions for writting to external storage. The steps are:

  1. Create a text file from the database (csv)
  2. Send the file via Intent so the user can send it via email or store it in the desired cloud space.

I tried these examples - How to open private files saved to the internal storage using Intent.ACTION_VIEW? - Create and Share a File from Internal Storage

But i get a FileNotFoundException message on the logcat.

I hope you can help me find out what am I doing wrong. Thanks

Edit: It's working now! Followed Commonsware suggetions, I wans't using getFilesDir to create the files, and did a sync to make sure the file was already written when sending.

Here's the manifest:

<provider
        android:name=".FileExportProvider"
        android:authorities="com.mypackage.myappfileexport"
        android:exported="true"
        />

Here's the provider:

public class FileExportProvider extends ContentProvider {

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        File privateFile = new File(getContext().getFilesDir(), uri.getPath());
        return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY);
    }

    @Override
    public int delete(Uri arg0, String arg1, String[] arg2) {
        return 0;
    }

    @Override
    public String getType(Uri arg0) {
        return null;
    }

    @Override
    public Uri insert(Uri arg0, ContentValues arg1) {
        return null;
    }

    @Override
    public boolean onCreate() {
        return false;
    }

    @Override
    public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
            String arg4) {
        return null;
    }

    @Override
    public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
        return 0;
    }

}

Here's the code for the export dialog:

String filename = exp.ExportToFile(filter1, filter2, filter3, filter4);

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); 
emailIntent.setType("text/plain");

Uri uri = Uri.parse("content://com.mypackage.myappfilexport/" + filename);
emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(emailIntent, "Send..."));

Here's how I create the file:

public String ExportToFile(Cursor cursor) {
        File directory = _context.getFilesDir();
        String filename = "file_export.csv";
        FileOutputStream outputStream;
        File file = new File(directory, filename);

        try {
              //outputStream = _context.openFileOutput(filename, Context.MODE_PRIVATE);
              //Edit: suggested by Commonsware, in order to use getFilesDir()
              outputStream = new FileOutputStream(file);  

              String header = "";
              for(int i=0; i < cursor.getColumnCount(); i = i+1){
                  header = header+cursor.getColumnName(i);
                  if (i < cursor.getColumnCount()-1)
                      header = header+",";
              }

              header = header + "\r\n";
              outputStream.write(header.getBytes());


              //loop cursor
              cursor.moveToFirst();
                while (!cursor.isAfterLast()) {
                    String line = "";
                    for(int i=0; i < cursor.getColumnCount(); i = i+1){
                        String value = cursor.getString(i);
                        if (value==null)
                            value = "";
                        line = line + value;
                        if (i < cursor.getColumnCount()-1)
                            line = line+",";
                    }
                    line = line + "\r\n";

                    outputStream.write(line.getBytes());

                    cursor.moveToNext();
                }
                //Edit: suggested by Commonsware, getFD().sync() before sending the file
                outputStream.getFD().sync();
                outputStream.close();
            } catch (Exception e) {
              e.printStackTrace();
            }


        return filename;
    }
Community
  • 1
  • 1
pedroren
  • 5
  • 3
  • If you use `getFilesDir()` in one place, I recommend that you use it everywhere (instead of using `openFileOutput()`). You may need `query()` to handle `OpenableColumns`. You may need to call `getFD().sync()` on your `FileOutputStream` to get all bytes committed to disk before you try to invoke the `ACTION_SEND` `Intent`. Beyond all of that, if you crash and post a Stack Overflow question about it, please post the stack trace as part of your question (along with cross-references to your code snippets), as nobody knows exactly where in your code the `FileNotFoundException` is coming from. – CommonsWare Nov 02 '14 at 09:24
  • It's working now! Thanks! I changed to getFilesDir and used getFD().sync(). I didn't include a stack trace because my app didn't crash, I just observed warnings from the receiving apps. – pedroren Nov 02 '14 at 19:46

0 Answers0