I'm writing a process that downloads/ copies a file attached to Gmail on to the SD card that my application can then read.
When a user clicks on the attachment my activity is fired and I use the following code to save to local storage;
InputStream in = getContentResolver().openInputStream( intent.getData() );
String ext = intent.getType().equals("text/xml") ? ".xml" : ".gpkg";
localFile = new File( TILE_DIRECTORY, "tmp/"+intent.getDataString().hashCode()+ext);
// If we haven't already cached the file, go get it..
if (!localFile.exists()) {
localFile.getParentFile().mkdirs();
FileIO.streamCopy(in, new BufferedOutputStream(new FileOutputStream(localFile)) );
}
The FileIO.streamCopy is simply;
public static void streamCopy(InputStream in, OutputStream out) throws IOException{
byte[] b = new byte[BUFFER];
int read;
while ((read = in.read(b)) != -1) {
out.write(b, 0, read);
}
out.close();
in.close();
}
This all works fine on a small file, but with a 6Mb attachment only 12Kb is ever getting written. I'm not even getting an error, the process just runs through very quickly and i'm left with a corrupt file.
This process is run in its own thread and is part of a larger app with a lot of fileIO, so there is no issue with permissions/ directories etc.
Is there something different I should be doing with the stream?
Incidentally, intent.getData() is
content://gmail-ls/mexxx#gmail.com/messages/6847/attachments/0.1/BEST/false
and intent.getType() is
application/octet-stream
Thanks
All work's fine with this code
InputStream in = new BufferedInputStream(
getContentResolver().openInputStream(intent.getData()) );
File dir = getExternalCacheDir();
File file = new File(dir, Utils.md5(uri.getPath()));
OutputStream out = new BufferedOutputStream( new FileOutputStream(file) );
streamCopy(in, out);
Related
Trying to copy a PDF file (template) to a custom directory in the external storage (non-sd card).
public void copyPDFToExternal(String newFileName) throws IOException {
// Create directory folder if it doesnt exist.
File folder = new File(Environment.getExternalStorageDirectory() +
File.separator + "pdfFolder");
if (!folder.exists()){
folder.mkdir();
}
// Copy template
InputStream in = getResources().openRawResource(R.raw.pdf_template);
FileOutputStream out = new FileOutputStream(Environment.getExternalStorageDirectory() +
File.separator + "pdfFolder/"+newFileName+".pdf");
byte[] buff = new byte[1024];
int read = 0;
try {
while ((read = in.read(buff)) > 0 ) {
out.write(buff, 0, read);
}
} finally {
in.close();
out.close();
}
}
I have added the following to AndroidManifest.xml, not in the application tag.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Full error: http://pastebin.com/TBtbekiB
If you need me to post anything else let me know.
Where have I gone wrong?
Update: No longer crashes but now doesn't seem to do anything... the mkdirs returns true.
public void copyPDFToExternal(String newFileName) throws IOException {
File folder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/test/");
if (!folder.exists()){
if (!folder.mkdirs()){
eme.setText("Failed");
return;
};
}
InputStream in = getResources().openRawResource(R.raw.ohat);
FileOutputStream out = new FileOutputStream(folder.getAbsolutePath() +"/"+newFileName+".pdf");
byte[] buff = new byte[1024];
int read = 0;
try {
while ((read = in.read(buff)) > 0 ) {
out.write(buff, 0, read);
}
} finally {
in.close();
out.close();
}
}
I've also added a permission request, this is a little long so using pastebin.
http://pastebin.com/KgivWNuc
Edit 2:
So it seems it does work, just the directory cannot be see when the device is connected to a computer (in MTP mode). But I guess that's another issue.
if you are installing in device os version android M and more you need to take permission at runtime. Adding in manifest alone is not sufficient. Refer this for more details.
Can you specify which external storage you are using as you have said it is (non SD Card) because if you are using Environment.getExternalStorageDirectory() then it will give you the path of SD Card Storage, something like this /storage/emulated/0/ where 0 represents primary storage device.
I have a png file in the raw folder. I get the inputStream using :
inputStream = getResources().openRawResource(R.raw.test);
I am trying to write this inputStream in a new file in an Android application. This is my code:
inputStream = getResources().openRawResource(R.raw.test);
File file = new File("/test.png");
outputStream = new FileOutputStream(file);
int read = 0;
byte[] bytes = new byte[1024*1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
outputStream.close();
inputStream.close();
When I run the application, I get the following error in the logcat:
java.io.FileNotFoundException: /test.png: open failed: EROFS (Read-only file system)
Basically I want to create a File object so that I can send this to my server.
Thank you.
You will not have access to the file-system root, which is what you're attempting to access. For your purposes, you can write to internal files new File("test.png"), which places the file in the application-internal storage -- better yet, access it explicitly using getFilesDir().
For truly temporary files, you might want to look into getCacheDir() -- should you forget to delete those temporary files, the system will reclaim the space when it runs out of room.
Here's my solution:
inputStream = getResources().openRawResource(R.raw.earth);
file = new File(Environment.getExternalStorageDirectory() + File.separator + "test.png");
file.createNewFile();
outputStream = new FileOutputStream(file);
int read = 0;
byte[] bytes = new byte[1024*1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
outputStream.close();
inputStream.close();
Official facebook App has a bug, when you try to share an image with share intent, the image gets deleted from the sdcard. This is the way you have to pass the image to facebook app using the uri of the image:
File myFile= new File(Environment.getExternalStorageDirectory(), "car.jpg");
Uri uri = Uri.fromFile(myFile);
i.putExtra(Intent.EXTRA_STREAM, uri);
Then, suppose that if i create a copy from the original myFile object, and i pass the uri of the copy to facebook app, then, my original image will not be deleted.
I tried with this code, but it doesn't work, the original image file is still getting deleted:
File myFile= new File(Environment.getExternalStorageDirectory(), "car.jpg");
File auxFile=myFile.getAbsoluteFile();
Uri uri = Uri.fromFile(auxFile);
Can someone tell me how to do a exact copy of a file that doesn't redirect to the original File?
Please check: Android file copy
The file is copied byte by byte so no reference to the old file is maintained.
Here, this should be able to create a copy of your file:
private void CopyFile() {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(<file path>);
out = new FileOutputStream(<output path>);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(Exception e) {
Log.e("tag", e.getMessage());
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
Can anyone explain why downloading/playing a video from my applications cache directory does not work, but downloading/playing the same video from my sdcard does work?
Note: this video is being downloaded. I am saving to memory before calling VideoView.setVideoPath(...).
// Works
File file = new File(Environment.getExternalStorageDirectory(), "vid-test.3gp");
// Does not work
File file = new File(getCacheDir(), "vid-test.3gp");
In each case the file in question does exist.
If I attempt to call VideoView.setVideoURI(...) and "stream" the video to my VideoView, it is hit and miss whether or not it will work.
Can anyone explain this behavior?
It's probably a permission issue. Here is a working snipped:
InputStream in = connection.getInputStream();
File file = new File(getApplicationContext().getCacheDir() ,fileName);
if(!file.exists()){
file.setReadable(true);
file.createNewFile();
if (file.canWrite()){
FileOutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) > 0 ) {
out.write(buffer,0, len1);
}
out.close();
}
in.close();
Runtime.getRuntime().exec("chmod 755 "+getCacheDir() +"/"+ fileName);
}
What i want to do: delete an image file from the private internal storage in my app. I save images in internal storage so they are deleted on app uninstall.
I have successfully created and saved:
String imageName = System.currentTimeMillis() + ".jpeg";
FileOutputStream fos = openFileOutput(imageName, Context.MODE_PRIVATE);
bitmap.compress(Bitmap.CompressFormat.JPEG, 35, fos);
an image that i receive through
bitmap = BitmapFactory.decodeStream(inputStream);
I am able to retrieve the image later for display:
FileInputStream fis = openFileInput(imageName);
ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
DataOutputStream outWriter = new DataOutputStream(bufStream);
int ch;
while((ch = fis.read()) != -1)
outWriter.write(ch);
outWriter.close();
byte[] data = bufStream.toByteArray();
bufStream.close();
fis.close();
imageBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
I now want to delete this file permanently. I have tried creating a new file and deleting it, but the file is not found:
File file = new File(imageName);
file.delete();
I have read on the android developer website that i must open private internal files using the openFileInput(...) method which returns an InputStream allowing me to read the contents, which i don't really care about - i just want to delete it.
can anyone point me in the right direction for deleting a file which is stored in internal storage?
Erg, I found the answer myself. Simple answer too :(
All you have to do is call the deleteFile(imageName) method.
if(activity.deleteFile(imageName))
Log.i(TAG, "Image deleted.");
Done!