Raw system file paths are dangerous to use nowadays since they are often restricted, especially when dealing with external filesystems or filesystems that might not even be on-device (e.g. Google Drive).
Therefore all usages of imageFilePath was removed and replaced with imageUri.
Code that used imageFilePath generally now accepts a Uri instead or an InputStream.
Description
readData / getPageSize
Utility methods to read data into memory. getPageSize is an optimization to read a page of memory, which is usually 4kb but Android 15 devices may be shipped with 16kb page size devices.
There is a lot of disk usage when processing images which might be necessary back in the day when RAM is limited but modern devices have plenty of RAM to deal with image content. It's far more efficient to read the data into memory once and provide several instances of in-memory data streams instead of constantly reading data from disk. (See notes on getScaledAndRotatedBitmap for more details)
ExifHelper
A new method exposed to instantiate via InputStream.
getScaledAndRotatedBitmap
No longer accepts a file path. Instead it accepts the raw binary data. It no longer opens or manages it's own stream.
It will create ByteArrayInputStream which is a stream that doesn't require to be closed, as it operates on in-memory data. It doesn't need to manage kernel objects like file descriptors.
Older code used to create several read streams and read the input source from disk several times. It also created temporary files which was deemed a requirement when dealing with "off-device" files such as Google Drive. There is some truth to this, but temporary files isn't necessary. Data can be read from in-memory instead saving the need to constantly read and write from disk. Content Resolver APIs can also obtain some data like mime type.
Therefore lots of stream management code was removed, which allowed us to remove a lot of try/catches as well. Using the exif changes, we use a ByteArrayInputStream instead virtually everywheres fileStream was previously used.
Note that this is used when sourcing an image from a gallery, it has an unrelated issue that is out of scope of this PR that causes it to not use the result of the modifications and instead returns the original image anyway.
Sourcing an image from camera and applying modifications via targetWidth or targetHeight does work as expected.
on save instance / on restore instance
the image file path key and serialization/restoration were removed.
processResultFromCamera
sourcePath was replaced with InputStream input.
croppedFilePath is still used and is wrapped by a FileInputStream. Refactoring this file path is out of scope of this particular PR, which is only applicable if allowEdit is enabled.
Otherwise imageUri is used and resolved by the content resolver.
input is then asserted for non null, and throws IOException otherwise.
The input is then read into memory and stored in sourceData which is fed into getScaledAndRotatedBitmap. See notes above.
Other Changes
I realise there's a ton of other "format" changes, which
Android Studio IDE is responsible for and I do plan on cleaning them up in another PR.
Testing
Manual testing on API 28 (for non-scoped access framework) & 34 (for scoped access framework).
Paramedic tests passes.
Checklist
[x] I've run the tests to see all new and existing tests pass
[x] I added automated test coverage as appropriate for this change
[x] Commit is prefixed with (platform) if this change only applies to one platform (e.g. (android))
Platforms affected
Android
Motivation and Context
Note this contains https://github.com/apache/cordova-plugin-camera/pull/902 will rebase after merge.
Raw system file paths are dangerous to use nowadays since they are often restricted, especially when dealing with external filesystems or filesystems that might not even be on-device (e.g. Google Drive).
Therefore all usages of
imageFilePath
was removed and replaced withimageUri
.Code that used
imageFilePath
generally now accepts aUri
instead or anInputStream
.Description
readData / getPageSize
Utility methods to read data into memory. getPageSize is an optimization to read a page of memory, which is usually 4kb but Android 15 devices may be shipped with 16kb page size devices.
There is a lot of disk usage when processing images which might be necessary back in the day when RAM is limited but modern devices have plenty of RAM to deal with image content. It's far more efficient to read the data into memory once and provide several instances of in-memory data streams instead of constantly reading data from disk. (See notes on
getScaledAndRotatedBitmap
for more details)ExifHelper
A new method exposed to instantiate via
InputStream
.getScaledAndRotatedBitmap
No longer accepts a file path. Instead it accepts the raw binary data. It no longer opens or manages it's own stream.
It will create
ByteArrayInputStream
which is a stream that doesn't require to be closed, as it operates on in-memory data. It doesn't need to manage kernel objects like file descriptors.Older code used to create several read streams and read the input source from disk several times. It also created temporary files which was deemed a requirement when dealing with "off-device" files such as Google Drive. There is some truth to this, but temporary files isn't necessary. Data can be read from in-memory instead saving the need to constantly read and write from disk. Content Resolver APIs can also obtain some data like mime type.
Therefore lots of stream management code was removed, which allowed us to remove a lot of try/catches as well. Using the exif changes, we use a
ByteArrayInputStream
instead virtually everywheresfileStream
was previously used.Note that this is used when sourcing an image from a gallery, it has an unrelated issue that is out of scope of this PR that causes it to not use the result of the modifications and instead returns the original image anyway.
Sourcing an image from camera and applying modifications via
targetWidth
ortargetHeight
does work as expected.on save instance / on restore instance
the image file path key and serialization/restoration were removed.
processResultFromCamera
sourcePath
was replaced withInputStream input
.croppedFilePath
is still used and is wrapped by aFileInputStream
. Refactoring this file path is out of scope of this particular PR, which is only applicable ifallowEdit
is enabled.Otherwise
imageUri
is used and resolved by the content resolver.input
is then asserted for non null, and throwsIOException
otherwise.The input is then read into memory and stored in
sourceData
which is fed intogetScaledAndRotatedBitmap
. See notes above.Other Changes
I realise there's a ton of other "format" changes, which Android Studio IDE is responsible for and I do plan on cleaning them up in another PR.
Testing
Manual testing on API 28 (for non-scoped access framework) & 34 (for scoped access framework). Paramedic tests passes.
Checklist
(platform)
if this change only applies to one platform (e.g.(android)
)