Kotlin, how can I base64Encode the file I get back from the OnActivityResult - file

I need to make the logic to add attachments to a email client.
I have all the needed permissions and I create a intent for files:
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "*/*"
activity?.startActivityForResult(intent, ActivityResultHandler.PICK_FILE)
I choose a file, and I get result ok in my onActivityResult:
public override fun onActivityResult(reqCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(reqCode, resultCode, data)
ActivityResultHandler().onActivityResult(this, reqCode, resultCode, data)
if (reqCode == REQUEST_CODE_SET_DEFAULT_DIALER) {
activityToFragmentCommunicationCallback?.sendData("refresh")
} else if (reqCode == ActivityResultHandler.PICK_FILE && resultCode == RESULT_OK && data != null) {
val uri = data.data
val cr = this.contentResolver
val mime = cr.getType(uri)
var file = uri.toFile()
if (file.exists()) {
var base64 = convertToBase64(file)
DialogFullScreenEmailComposer.addAttachment()
}
}
}
But then it crashes at this: var file = uri.toFile()
Telling me that:
2019-09-18 16:12:12.300 20608-20608/com.xelion.android.debug E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.xelion.android.debug, PID: 20608
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=3, result=-1, data=Intent { dat=content://com.android.providers.downloads.documents/document/raw:/storage/emulated/0/Download/106.apk flg=0x1 }} to activity {com.xelion.android.debug/com.xelion.android.activity.MainActivity}: java.lang.IllegalArgumentException: Uri lacks 'file' scheme: content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2F106.apk
at android.app.ActivityThread.deliverResults(ActivityThread.java:4398)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4440)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6718)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.IllegalArgumentException: Uri lacks 'file' scheme: content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2F106.apk
at androidx.core.net.UriKt.toFile(Uri.kt:40)
at com.xelion.android.activity.MainActivity.onActivityResult(MainActivity.kt:312)
at android.app.Activity.dispatchActivityResult(Activity.java:7462)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4391)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4440) 
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:193) 
at android.app.ActivityThread.main(ActivityThread.java:6718) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
What can be done so that it can create my file? Or can I skip that and just create the base64Encoded directly?

The error message states that the Uri isn't pointing to a file (it doesn't start with file://). In newer Android versions you don't have direct access to the file you are requesting, but you can read its content through the ContentResolver. You can do that by opening an InputStream with cr.openInputStream(uri). When you have it you can read from that stream and convert the result to Base64.
Here's an example on how to read the entire content of the file into a ByteArray:
private fun readFile(cr: ContentResolver, uri: Uri): ByteArray {
val inStream = cr.openInputStream(uri) ?: return ByteArray(0)
val outStream = ByteArrayOutputStream()
val buffer = ByteArray(32)
while (inStream.read(buffer) > 0) {
outStream.write(buffer)
}
return outStream.toByteArray()
}

Related

How to read an InputStream from 'in' and write an OutputStream to 'out' in a Camel route's exchange?

Usually that's done with:
try (InputStream is = ...;
OutputStream os = ...) {
int b;
while ((b = is.read()) != -1) {
// do something with the byte
os.write(b);
}
}
In a RouteBuilder's configure() I have the following:
from("file:...")
...
to("direct:second")
from("direct:second")
...
.process(exchange -> {
try (InputStream is1 =
new BufferedInputStream(new FileInputStream(exchange.getIn().getBody(File.class));
InputStream is2 = exchange.getIn().getBody(BufferedInputStream.class);
// OutputStream os = ???
){
int b;
while ((b = [is1|is2].read()) != -1) {
System.out.print(b); // works
// now how to obtain the OutputStream, connect it to 'out' and write to it?
}
}
})
.to("direct:third")
from("direct:third")
...
I read docs, blogs, tutorials, SO answers about getIn(), getOut(), Message Translator, transform(), stream: to no avail.
Update: I also looked at src/test/java/org/apache/camel/processor, especially the StreamCachingInOutTest. The Processor there just reads an InputStream.
Follow-up question:
Is:
exchange.getIn().getBody(BufferedInputStream.class)
the same as:
new BufferedInputStream(new FileInputStream(exchange.getIn().getBody(File.class))
if the original from(...) is "file:..."?
UPDATE
I tried the following:
try (...;
final OutputStream os = new ByteArrayOutputStream()
){
while (b = is.read() ...) {
...
os.write(b);
}
exchange.getOut().setBody(os, ByteArrayOutputStream.class);
}
The result is:
Caused by: org.apache.camel.InvalidPayloadException:
No body available of type: java.io.InputStream but has value:
of type: org.apache.commons.io.output.ByteArrayOutputStream on: Message[].
Caused by: No type converter available to convert from type:
org.apache.commons.io.output.ByteArrayOutputStream to the required type:
java.io.InputStream with value . Exchange[ID-R05377-1542620554174-0-4].
Caused by: [org.apache.camel.NoTypeConversionAvailableException -
No type converter available to convert from type:
org.apache.commons.io.output.ByteArrayOutputStream to the
required type: java.io.InputStream with value ]
at org.apache.camel.impl.MessageSupport.getMandatoryBody(MessageSupport.java:117)
at org.apache.camel.component.file.FileOperations.storeFile(FileOperations.java:333)
... 17 more
Caused by: org.apache.camel.NoTypeConversionAvailableException:
No type converter available to convert from type:
org.apache.commons.io.output.ByteArrayOutputStream to the required type:
java.io.InputStream with value
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.mandatoryConvertTo(BaseTypeConverterRegistry.java:206)
at org.apache.camel.impl.MessageSupport.getMandatoryBody(MessageSupport.java:115)
... 18 more
1849 [Camel (camel-1) thread #2 - Multicast] ERROR org.apache.camel.processor.DefaultErrorHandler -
Failed delivery for (MessageId: ID-R05377-1542620554174-0-7 on
ExchangeId: ID-R05377-1542620554174-0-4). Exhausted after delivery attempt:
1 caught: org.apache.camel.component.file.GenericFileOperationFailedException:
Cannot store file: <... to(...) file path of direct:third here ...>
UPDATE to the UPDATE
The exception was thrown because I used org.apache.commons.io.output.ByteArrayOutputStream rather than java.io.ByteArrayOutputStream. It works with the latter and this also seems to be the answer to the question.
import java.io.ByteArrayOutputStream;
// DO NOT USE THIS IN CONJUNCTION WITH CAMEL!
//import org.apache.commons.io.output.ByteArrayOutputStream;
...
from(...)
...
.streamCaching()
.process(exchange -> {
...
try (final InputStream is = exchange.getIn().getBody(InputStream.class);
final OutputStream os = new ByteArrayOutputStream(OUTSTREAM_BUFFER)) {
while (b = is.read() ...) {
// do something with the byte
os.write(b);
}
exchange.getOut().setBody(os, OutputStream.class);
}
})
...
Have a look at the stream component (http://camel.apache.org/stream.html)
Example:
// Route messages to the standard output.
from("direct:in")
.to("stream:out");

read cloud storage content with "gzip" encoding for "application/octet-stream" type content

We're using "Google Cloud Storage Client Library" for app engine, with simply "GcsFileOptions.Builder.contentEncoding("gzip")" at file creation time, we got the following problem when reading the file:
com.google.appengine.tools.cloudstorage.NonRetriableException: java.lang.RuntimeException: com.google.appengine.tools.cloudstorage.SimpleGcsInputChannelImpl$1#1c07d21: Unexpected cause of ExecutionException
at com.google.appengine.tools.cloudstorage.RetryHelper.doRetry(RetryHelper.java:87)
at com.google.appengine.tools.cloudstorage.RetryHelper.runWithRetries(RetryHelper.java:129)
at com.google.appengine.tools.cloudstorage.RetryHelper.runWithRetries(RetryHelper.java:123)
at com.google.appengine.tools.cloudstorage.SimpleGcsInputChannelImpl.read(SimpleGcsInputChannelImpl.java:81)
...
Caused by: java.lang.RuntimeException: com.google.appengine.tools.cloudstorage.SimpleGcsInputChannelImpl$1#1c07d21: Unexpected cause of ExecutionException
at com.google.appengine.tools.cloudstorage.SimpleGcsInputChannelImpl$1.call(SimpleGcsInputChannelImpl.java:101)
at com.google.appengine.tools.cloudstorage.SimpleGcsInputChannelImpl$1.call(SimpleGcsInputChannelImpl.java:81)
at com.google.appengine.tools.cloudstorage.RetryHelper.doRetry(RetryHelper.java:75)
... 56 more
Caused by: java.lang.IllegalStateException: com.google.appengine.tools.cloudstorage.oauth.OauthRawGcsService$2#1d8c25d: got 46483 > wanted 19823
at com.google.common.base.Preconditions.checkState(Preconditions.java:177)
at com.google.appengine.tools.cloudstorage.oauth.OauthRawGcsService$2.wrap(OauthRawGcsService.java:418)
at com.google.appengine.tools.cloudstorage.oauth.OauthRawGcsService$2.wrap(OauthRawGcsService.java:398)
at com.google.appengine.api.utils.FutureWrapper.wrapAndCache(FutureWrapper.java:53)
at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:90)
at com.google.appengine.tools.cloudstorage.SimpleGcsInputChannelImpl$1.call(SimpleGcsInputChannelImpl.java:86)
... 58 more
What else should be added to read files with "gzip" compression to be able to read the content in app engine? ( curl cloud storage URL from client side works fine for both compressed and uncompressed file )
This is the code that works for uncompressed object:
byte[] blobContent = new byte[0];
try
{
GcsFileMetadata metaData = gcsService.getMetadata(fileName);
int fileSize = (int) metaData.getLength();
final int chunkSize = BlobstoreService.MAX_BLOB_FETCH_SIZE;
LOG.info("content encoding: " + metaData.getOptions().getContentEncoding()); // "gzip" here
LOG.info("input size " + fileSize); // the size is obviously the compressed size!
for (long offset = 0; offset < fileSize;)
{
if (offset != 0)
{
LOG.info("Handling extra size for " + filePath + " at " + offset);
}
final int size = Math.min(chunkSize, fileSize);
ByteBuffer result = ByteBuffer.allocate(size);
GcsInputChannel readChannel = gcsService.openReadChannel(fileName, offset);
try
{
readChannel.read(result); <<<< here the exception was thrown
}
finally
{
......
It is now compressed by:
GcsFilename filename = new GcsFilename(bucketName, filePath);
GcsFileOptions.Builder builder = new GcsFileOptions.Builder().mimeType(image_type);
builder = builder.contentEncoding("gzip");
GcsOutputChannel writeChannel = gcsService.createOrReplace(filename, builder.build());
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(blob_content.length);
try
{
GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
try
{
zipStream.write(blob_content);
}
finally
{
zipStream.close();
}
}
finally
{
byteStream.close();
}
byte[] compressedData = byteStream.toByteArray();
writeChannel.write(ByteBuffer.wrap(compressedData));
the blob_content is compressed from 46483 bytes to 19823 bytes.
I think it is the google code's bug
https://code.google.com/p/appengine-gcs-client/source/browse/trunk/java/src/main/java/com/google/appengine/tools/cloudstorage/oauth/OauthRawGcsService.java, L418:
Preconditions.checkState(content.length <= want, "%s: got %s > wanted %s", this, content.length, want);
the HTTPResponse has decoded the blob, so the Precondition is wrong here.
If I good understand you have to set mineType:
GcsFileOptions options = new GcsFileOptions.Builder().mimeType("text/html")
Google Cloud Storage does not compress or decompress objects:
https://developers.google.com/storage/docs/reference-headers?csw=1#contentencoding
I hope that's what you want to do .
Looking at your code it seems like there is a mismatch between what is stored and what is read. The documentation specifies that compression is not done for you (https://developers.google.com/storage/docs/reference-headers?csw=1#contentencoding). You will need to do the actual compression manually.
Also if you look at the implementation of the class that throws the exception (https://code.google.com/p/appengine-gcs-client/source/browse/trunk/java/src/main/java/com/google/appengine/tools/cloudstorage/oauth/OauthRawGcsService.java?r=81&spec=svn134) you will notice that you get the original contents back but you're actually expecting compressed content. Check the method readObjectAsync in the above mentioned class.
It looks like the content persisted might not be gzipped or the content-length is not set properly. What you should do is verify length of the compressed stream just before writing it into the channel. You should also verify that the content length is set correctly when doing the http request. It would be useful to see the actual http request headers and make sure that content length header matches the actual content length in the http response.
Also it looks like contentEncoding could be set incorrectly. Try using:.contentEncoding("Content-Encoding: gzip") as used in this TCK test. Although still the best thing to do is inspect the HTTP request and response. You can use wireshark to do that easily.
Also you need to make sure that GCSOutputChannel is closed as that's when the file is finalized.
Hope this puts you on the right track. To gzip your contents you can use java GZIPInputStream.
I'm seeing the same issue, easily reproducable by uploading a file with "gsutil cp -Z", then trying to open it with the following
ByteArrayOutputStream output = new ByteArrayOutputStream();
try (GcsInputChannel readChannel = svc.openReadChannel(filename, 0)) {
try (InputStream input = Channels.newInputStream(readChannel))
{
IOUtils.copy(input, output);
}
}
This causes an exception like this:
java.lang.IllegalStateException:
....oauth.OauthRawGcsService$2#1883798: got 64303 > wanted 4096
at ....Preconditions.checkState(Preconditions.java:199)
at ....oauth.OauthRawGcsService$2.wrap(OauthRawGcsService.java:519)
at ....oauth.OauthRawGcsService$2.wrap(OauthRawGcsService.java:499)
The only work around I've found is to read the entire file into memory using readChannel.read:
int fileSize = 64303;
ByteBuffer result = ByteBuffer.allocate(fileSize);
try (GcsInputChannel readChannel = gcs.openReadChannel(new GcsFilename("mybucket", "mygzippedfile.xml"), 0)) {
readChannel.read(result);
}
Unfortunately, this only works if the size of the bytebuffer is greater or equal to the uncompressed size of the file, which is not possible to get via the api.
I've also posted my comment to an issue registered with google: https://code.google.com/p/googleappengine/issues/detail?id=10445
This is my function for reading compressed gzip files
public byte[] getUpdate(String fileName) throws IOException
{
GcsFilename fileNameObj = new GcsFilename(defaultBucketName, fileName);
try (GcsInputChannel readChannel = gcsService.openReadChannel(fileNameObj, 0))
{
maxSizeBuffer.clear();
readChannel.read(maxSizeBuffer);
}
byte[] result = maxSizeBuffer.array();
return result;
}
The core is that you cannot use the size of the saved file cause Google Storage will give it to you with the original size, so it checks the sizes you expected and the real size and these are differents:
Preconditions.checkState(content.length <= want, "%s: got %s > wanted
%s", this, content.length, want);
So i solved it allocating the biggest amount possible for these files using BlobstoreService.MAX_BLOB_FETCH_SIZE. Actually maxSizeBuffer is only allocated once outsize of the function
ByteBuffer maxSizeBuffer = ByteBuffer.allocate(BlobstoreService.MAX_BLOB_FETCH_SIZE);
And with maxSizeBuffer.clear(); all data is flushed again.

Getting path of audio file from sdcard

In my app I tried to pass the file path from one activity to another activity using intent.In my receiving activity I got the file path as "null".But when I print the file in first activity it prints the path.From my second activity I attach that file to mail using Gmailsender.This was the code I tried,
private void startRecord()
{
File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");
try
{
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
int minBufferSize = AudioRecord.getMinBufferSize(8000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
short[] audioData = new short[minBufferSize];
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
8000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minBufferSize);
audioRecord.startRecording();
while(recording)
{
int numberOfShort = audioRecord.read(audioData, 0, minBufferSize);
for(int i = 0; i < numberOfShort; i++)
{
dataOutputStream.writeShort(audioData[i]);
}
}
audioRecord.stop();
audioRecord.release();
dataOutputStream.close();
}
catch (IOException e)
{
e.printStackTrace();
}
String audiofile;
audiofile=file.getAbsolutePath();
System.out.println("File Path::::"+audiofile);
}
Intent is,
Intent sigout=new Intent(getApplicationContext(),WeeklyendActivity.class);
sigout.putExtra("mnt/sdcard-test.pcm",audiofile);
startActivity(sigout);
In my receiving activity,
String patty=getIntent().getStringExtra("mnt/sdcard-text.pcm");
System.out.println("paathhhy frfom ::"+patty);
It prints null.Can anyone help me how to get the file path.And more thing I am not sure whether the audio would save in that file correctly?
Please anyone help me!!!Thanks in advance!
Based on your information that audioFile is a variable of type File, when you do this:
sigout.putExtra("mnt/sdcard-test.pcm",audiofile);
you are putting a File object in the extras Bundle. Then, when you try to get the extra from the Bundle you do this:
String patty=getIntent().getStringExtra("mnt/sdcard-text.pcm");
However, the object in this extra is of type File, not type String. This is why you are getting null.
If you only want to pass the name of the file, then put the extra like this:
sigout.putExtra("mnt/sdcard-test.pcm",audiofile.getAbsolutePath());

Google Drive API - too slow.

I've just working on Google Drive API. I have one problem, it's too slow. I use methods like in the Documentation. For example:
List<File> getFilesByParrentId(String Id, Drive service) throws IOException {
Children.List request = service.children().list(Id);
ChildList children = request.execute();
List<ChildReference> childList = children.getItems();
File file;
List<File> files = new ArrayList<File>();
for (ChildReference child : childList) {
file = getFilebyId(child.getId(), service);
if (file == null) {
continue;
} else if (file.getMimeType().equals(FOLDER_IDENTIFIER)) {
System.out.println(file.getTitle() + " AND "
+ file.getMimeType());
files.add(file);
}
}
return files;
}
private File getFilebyId(String fileId, Drive service) throws IOException {
File file = service.files().get(fileId).execute();
if (file.getExplicitlyTrashed() == null) {
return file;
}
return null;
}
QUESTION: that method works, but too slow, for about 30 second.
How can I optimize this? For example, not to get all files (Only folder, or only files). or something like that.
you can use the q parameter and some stuff like :
service.files().list().setQ(mimeType != 'application/vnd.google-apps.folder and 'Id' in parents and trashed=false").execute();
This will get you all the files that are not folder, not trashed and whose parent has the id Id. All in one request.
And BTW, the API is not slow. Your algorithm, which makes too many of request, is.
public void getAllFiles(String id, Drive service) throws IOException{
String query="'"+id + "'"+ " in parents and trashed=false and mimeType!='application/vnd.google-apps.folder'";
FileList files = service.files().list().setQ(query).execute();
List<File> result = new ArrayList<File>();
Files.List request = service.files().list();
do {
result.addAll(files.getItems());
request.setPageToken(files.getNextPageToken());
} while (request.getPageToken() != null && request.getPageToken().length() > 0);
}

JavaMail and non-ASCII character in filenames

I can send attachments that have non-ascii filenames in JavaMail but I am not able to download them. I am getting java.io.FileNotFoundException specifically for those attachments whose file names contain non-ascii characters.
FYI: I am using something like messageBodyPart.setFileName(MimeUtility.encodeText(filename[i])) to encode the text and MimeUtility.decodeText(bodyPart.getFileName()) to decode the non-ascii file names
Is there a workaround for this?
EDIT
#Bill, here is part of my code that reads attachments. I have also added the properties.setProperty("mail.mime.decodeparameters", "true") and properties.setProperty("mail.mime.decodefilename", "true") properties in my code.
if (message[a].getContent() instanceof MimeMultipart) {
Multipart multipart = (Multipart) message[a].getContent();
for (int i = 0; i < multipart.getCount(); i++) {
bodyPart = multipart.getBodyPart(i);
disposition = bodyPart.getDisposition();
if (disposition != null && (disposition.equals(BodyPart.ATTACHMENT) || (disposition.equals(BodyPart.INLINE)))) {
DataHandler handler = bodyPart.getDataHandler();
String path = bodyPart.getFileName();
String[] str = path.split("/");
String fileName = str[str.length - 1];
String filePath = ReadConfigPropertiesFile.getPropertyValue("server.buildpath");
System.out.println(fileName);
File tempDir = new File(filePath + user);
if (!tempDir.exists()) {
tempDir.mkdir();
}
File saveFile = new File(tempDir + "/" + fileName);
int count = 0;
while (saveFile.exists()) {
count++;
saveFile = new File(tempDir + "/" + count + "_" + fileName);
}
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(saveFile));
byte[] buff = new byte[2048];
InputStream is = bodyPart.getInputStream();
int ret = 0;
while ((ret = is.read(buff)) > 0) {
bos.write(buff, 0, ret);
}
bos.close();
is.close();
//System.out.println(bodyPart.getContentType());
}else {
//display body (message) of the attachment;
//System.out.println(bodyPart.getContent().toString());
}
}
}
The above code raises the FileNotFoundException exception at BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(saveFile)) line and this is getting raised for the attachments whose file names are non-ascii characters (something like ሰላም.pdf). Every thing else works fine.
This answer taken from comment of #semytech (OP). It was hard to find it there, so I will add it as answer for more visibility. It helped me with hebrew filenames.
MimeBodyPart attachment = new MimeBodyPart();
attachment.setFileName(MimeUtility.encodeText(filename, "UTF-8", null));
You should never need to do the encoding or decoding yourself.
There are two sets of properties you can set to tell JavaMail to do the encoding/decoding for you:
mail.mime.encodefilename/mail.mime.decodefilename
mail.mime.encodeparameters/mail.mime.decodeparameters
See the javadocs for the javax.mail.internet package for details.
The first set uses a non-standard encoding technique, similar to what you're doing yourself. This works fine with some older mailers that use this technique.
The second set uses a MIME standard encoding technique. This version works with most modern mailers.
None of this explains why you're getting FileNotFoundException, but then you didn't provide enough detail to know what you're doing when you get the exception.

Resources