0

I have an app to create collages with a feature to apply filters on individual photos. To keep the app memory efficient and fast while applying filters, I simply store a copy of original photo(cropped version) in the Context, using Context.OpenFileOutput() which is used to apply filters realtime.

So, every time a filter is applied to a photo, I simply rewrite the mutable bitmap with the one saved in Context using OpenFileInput() and then apply the filter on it. This saves me from keeping two copies of same bitmap in memory.

Here's the problem I am facing which does not occur in debug mode on my devices (Nexus 5 and Samsung Galaxy Grand) but I have many crashes(caught ones) in the crashlytics.

According to the logs in crashlytics, the file does not exist in the Context, but actually it does exist.

Here's my code:

public static Bitmap decodeFileToBitmap(Context context,
        String filename,Bitmap bmp) 
                throws IOException{
    try {
        FileInputStream fis = context.getApplicationContext().openFileInput(filename);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inMutable = true;
        options.inSampleSize = 1;
        options.inBitmap = bmp;
        Bitmap bitmap = BitmapFactory.decodeStream(fis, null, options);
        fis.close();
        return bitmap;
    }catch (Exception ex){
        return null;
    }
}


public static void deleteFileWithName(Context context, String filename){
    try {
        context.deleteFile(filename);
    }catch (Exception ex){}
}

/**/
public static void saveFileInternally(Context context,
        String filename,Bitmap bmp) throws IOException{
    FileOutputStream fos = context.getApplicationContext().openFileOutput(filename,Context.MODE_PRIVATE);
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
    fos.close();
}

Here's the raw log:

Non-fatal Exception: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
   at libcore.io.Posix.open(Posix.java)
   at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
   at libcore.io.IoBridge.open(IoBridge.java:393)
   at java.io.FileInputStream.<init>(FileInputStream.java:78)
   at android.app.ContextImpl.openFileInput(ContextImpl.java:959)
   at android.content.ContextWrapper.openFileInput(ContextWrapper.java:186)
   at com.photos.storage.SnapAuraExternalStorage.decodeFileToBitmap(SnapAuraExternalStorage.java:38)
   at com.instacollage.managers.PhotoFilterManager$1.run(PhotoFilterManager.java:70)
   at java.lang.Thread.run(Thread.java:841)

Well, I didn't see any Non-Fatals or Exceptions while calling Context.openFileOutput().

The Coder
  • 121
  • 1
  • 7
  • 1
    You'll need to provide the relevant code and the path where you are trying to create the file. The APIs are reliable, but the path of the file is definitely of concern in Android. – Larry Schiefer Feb 01 '16 at 22:20
  • @LarrySchiefer: I have added suitable information. – The Coder Feb 01 '16 at 22:23
  • APIs are reliable, chances are that the filenames you are passing either are incorrect, or a racing condition might be causing the problem, maybe reading while the file was already deleted? – Martin Cazares Feb 01 '16 at 22:25
  • @MartinCazares: No racing condition and even no such condition exists where file is accessed even if deleted. I know that API's are reliable as Context.OpenFileOutput() does work but I worry that file is automatically deleted from the Context while os was trying to reclaim the memory. I am not sure of this. – The Coder Feb 01 '16 at 22:28
  • @TheCoder the provided code doesn't show the actual filename in use. Note that the `OpenFileOutput()` and `OpenFileInput()` APIs cannot have paths in them (including subdirectories!) They are expected to just have the file name. – Larry Schiefer Feb 01 '16 at 22:34
  • @TheCoder the files do persist even after power off, you can verify that to help your self narrowing down the problem... – Martin Cazares Feb 01 '16 at 22:39
  • Also, note that the `Context` object is a Java object representing your app or app component context. It doesn't actually store the file contents in the object. The `OpenFile*()` APIs are just convenience APIs to give you direct access to your app's private filesystem space. Any write/read you do is actually happening on the underlying (flash) filesystem. – Larry Schiefer Feb 01 '16 at 22:45
  • @LarrySchiefer - The filename used is normal filename (Ex: "cache_128"). There's no separator used, else I would have got exception every time and also, while storing the file on disk. So, i send exceptions in both cases - while storing file and while retrieving file. I have errors only in the latter case. If the files are written on the filesystem(or disk), that means they won't be deleted unless explicitly done by me. And how about the case if the user has no external storage or if it is unmounted? – The Coder Feb 02 '16 at 18:00
  • @MartinCazares: Thanks – The Coder Feb 02 '16 at 18:01
  • External storage wouldn't come into play on this, unless you are specifically trying to use it via path or one of the external storage APIs within the `Context` object. It could be possible that the file you have written has not been flushed or actually written to disk if the "writer" didn't do a close on it (though it's not very likely.) I would double check the file name used to write and the one attempting to be open for read, make sure there are no subtle name differences. – Larry Schiefer Feb 02 '16 at 18:42
  • @LarrySchiefer: filename is not an issue, as i am not using any separators in any case. Well, I while recheck on my side and will be putting some logs to send to Crashlytics and track the error reason properly. – The Coder Feb 03 '16 at 01:37
  • @LarrySchiefer: In response to the issue I am facing, if the file does not exist, then it should give me FileNotFoundException but I am getting exception : libcore.io.ErrnoException which is Exception given if OS fails. – The Coder Feb 07 '16 at 16:00
  • Why you are calling context.getApplicationContext().openFileInput , shouldn't it be context.openFileInput – Rahul Jul 16 '17 at 07:33

0 Answers0