lundi 7 avril 2014

Android créant un fichier d'entrée résident de mémoire qui peut être joint à un e-mail - Stack Overflow


The final objective will be clear shortly.


I want to create a file object and instead of getting data from a real physical file I want to provide the buffer myself.


Then, I want to use this file, which does not really exist in the sdcard or anywhere outside my app, give it a name and send it by email as an attachment (using the EXTRA_STREAM).


I found the following bit of code, by Adriaan Koster (@adriaankoster), the post Write byte[] to File in Java


// convert byte[] to File
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
File fileFromBytes = (File) ois.readObject();
bis.close();
ois.close();

System.out.println(fileFromBytes);

I used it to create this function


private File fileFromBytes(byte[] buf) {
File f = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream(buf);
ObjectInputStream ois = new ObjectInputStream(bis);
f = (File) ois.readObject();
bis.close();
ois.close();
}
catch (Exception e) {}
return f;
}

and here is where I am stuck, because when I use it:


// When sent as body the mail is sent OK
// emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, dump());

// When I try to attach the mail is empty
emailIntent.putExtra(android.content.Intent.EXTRA_STREAM, fileFromBytes(dump().getBytes()));

I know from examples I've seen the second argument should be an URI, but: How do I create a virtual URI to fit my file?


EDIT: The option to attach data directly from within the application is important to certain kind of applications. Namely, security & banking applications that do not want to move sensitive data around too much. Surely if the data does not reach the sdcard and goes directly to a mail attachment it is harder to sniff than within the application memory.
This is not my specific case, but I wanted to point out that this capability is important to have.




The first thing you'll want to do, I imagine, is create a ContentProvider. You can see an example implementation here


https://github.com/dskinner/AndroidWeb/blob/master/src/org/tsg/web/WebContentProvider.java


where in the above link's case, you would add this to your AndroidManifest.xml


<provider
android:name="org.tsg.web.WebContentProvider"
android:authorities="your.package.name" />

Now, you'll have a content uri available for use, content://your.package.name/.


The portion of the above ContentProvider your interested in, again I imagine, is the openFile method. When sharing data by intent across apps, certain things are expected. In your case, you're looking to share some byte data that's meant to be attached to the email.


So if you pass in a content uri to the email app such as content://your.package.name/foo with the appropriate intent flags, then openFile will get called on your ContentProvider. In this case, you can inspect the end of the uri segment to see foo was requested, and return appropriately.


The next issue you bring up is not having the file actually on disk. While I can't vouch for the method you used above (though it looks kosher), what you need to be returning is a ParcelFileDescriptor from your ContentProvider. If you look at the link I provided, you could possibly try to use that as a sample to get the file descriptor from your File object (my knowledge waivers here), but I imagine, the data simply wont be available at that point.


What you do bring up is security though. It's important to note that you can write data to disk privately so only the app has access to the data. I believe, but you might want to double check on this, if that data is private to the app, you can expose it via the ContentProvider and possibly lock down who and how the provider gets used, who can call it, etc. You may want to dig into android docs for that portion or look at some other SO questions.


Anyway, good luck.




Create the file in the application's cache directory. It will be created in the internal filesystem. Use 'getCacheDir()' API for getting the path to the cache dir. Write the data into this dir and then get the URI from the File object using ' Uri.fromFile (File file) '. When you are finished with the file, delete it.


Your application's cache is only available to your app, hence its safe to use for your purpose.


You can do some encryption if the data is too critical.




I think in order to do this, you are going to have to expose a ContentProvider, which will allow you handle a URI. The email application should then openInputStream on your URI, at which point you return an InputStream on your in-memory data.


I've not tried it, but in theory this should work.




i was busy with adding attachment to mail and i can send mail with attachment. if you want to take a look: can not send mail with attachment in Android



The final objective will be clear shortly.


I want to create a file object and instead of getting data from a real physical file I want to provide the buffer myself.


Then, I want to use this file, which does not really exist in the sdcard or anywhere outside my app, give it a name and send it by email as an attachment (using the EXTRA_STREAM).


I found the following bit of code, by Adriaan Koster (@adriaankoster), the post Write byte[] to File in Java


// convert byte[] to File
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
File fileFromBytes = (File) ois.readObject();
bis.close();
ois.close();

System.out.println(fileFromBytes);

I used it to create this function


private File fileFromBytes(byte[] buf) {
File f = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream(buf);
ObjectInputStream ois = new ObjectInputStream(bis);
f = (File) ois.readObject();
bis.close();
ois.close();
}
catch (Exception e) {}
return f;
}

and here is where I am stuck, because when I use it:


// When sent as body the mail is sent OK
// emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, dump());

// When I try to attach the mail is empty
emailIntent.putExtra(android.content.Intent.EXTRA_STREAM, fileFromBytes(dump().getBytes()));

I know from examples I've seen the second argument should be an URI, but: How do I create a virtual URI to fit my file?


EDIT: The option to attach data directly from within the application is important to certain kind of applications. Namely, security & banking applications that do not want to move sensitive data around too much. Surely if the data does not reach the sdcard and goes directly to a mail attachment it is harder to sniff than within the application memory.
This is not my specific case, but I wanted to point out that this capability is important to have.



The first thing you'll want to do, I imagine, is create a ContentProvider. You can see an example implementation here


https://github.com/dskinner/AndroidWeb/blob/master/src/org/tsg/web/WebContentProvider.java


where in the above link's case, you would add this to your AndroidManifest.xml


<provider
android:name="org.tsg.web.WebContentProvider"
android:authorities="your.package.name" />

Now, you'll have a content uri available for use, content://your.package.name/.


The portion of the above ContentProvider your interested in, again I imagine, is the openFile method. When sharing data by intent across apps, certain things are expected. In your case, you're looking to share some byte data that's meant to be attached to the email.


So if you pass in a content uri to the email app such as content://your.package.name/foo with the appropriate intent flags, then openFile will get called on your ContentProvider. In this case, you can inspect the end of the uri segment to see foo was requested, and return appropriately.


The next issue you bring up is not having the file actually on disk. While I can't vouch for the method you used above (though it looks kosher), what you need to be returning is a ParcelFileDescriptor from your ContentProvider. If you look at the link I provided, you could possibly try to use that as a sample to get the file descriptor from your File object (my knowledge waivers here), but I imagine, the data simply wont be available at that point.


What you do bring up is security though. It's important to note that you can write data to disk privately so only the app has access to the data. I believe, but you might want to double check on this, if that data is private to the app, you can expose it via the ContentProvider and possibly lock down who and how the provider gets used, who can call it, etc. You may want to dig into android docs for that portion or look at some other SO questions.


Anyway, good luck.



Create the file in the application's cache directory. It will be created in the internal filesystem. Use 'getCacheDir()' API for getting the path to the cache dir. Write the data into this dir and then get the URI from the File object using ' Uri.fromFile (File file) '. When you are finished with the file, delete it.


Your application's cache is only available to your app, hence its safe to use for your purpose.


You can do some encryption if the data is too critical.



I think in order to do this, you are going to have to expose a ContentProvider, which will allow you handle a URI. The email application should then openInputStream on your URI, at which point you return an InputStream on your in-memory data.


I've not tried it, but in theory this should work.



i was busy with adding attachment to mail and i can send mail with attachment. if you want to take a look: can not send mail with attachment in Android


0 commentaires:

Enregistrer un commentaire