Comments (28)
On iOS, this plugin work great. But on Android, there are plenty problems.
For everyone who got stuck on this and are in rush, you can use capacitor-mediastore as a workaround for Android. I'v tested on almost all version of Android and it work just fine.
Changing native code is also good but it's also have some bugs inside is cause your app to crash on some Android version, sadly atm I don't have enough time to dig in this plugin code.
from media.
Just to sum up, there are 2 different issues here:
-
On android 10+, the app crashes with the stack trace exposed by @axis7818 (Invalid column DISTINCT)
I'm not into java but after some research, it looks like "DISTINCT" can't be use anymore so I tried to replace this line
String[] projection = new String[]{"DISTINCT " + MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME};
with
String[] projection = new String[] {MediaStore.Images.Media._ID, MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.Images.Media.DATE_TAKEN };
(I think it should be optimised by a name grouping or something)
And it did work on android 10 and still working on android 8. -
The second issue is when the plugin tries to create an album
Album already exists
.
I have no clue on this one but the fact that it does work when the user manually creates the album first. However I forgot to mention that even in that case, the plugin is creating a new album under the "More albums" section of the default photo app instead of using the manually created album.
from media.
Hi @createdbyconnor
Actually I directly changed the code inside my android project MediaPlugin.java
.
Not the best way to do it, but it's a quick fix waiting for a definitive solution.
You just need to change the DISTINCT
line as I mentioned here.
from media.
@dhwalin Yes, check my older replies here
from media.
just to add context, another workaround would be something like this:
just ignore the getAlbums
method, try to createAlbum
every time with a catch
and life goes on. tested on androids 11 and 13.
from media.
Solution one out in v5.0, testable with example app.
from media.
I just tried on an emulator (Pixel 3 API 29) to see if a newer android version would work, and the app crashed during the first getAlbums() call. Here is the stack trace:
2020-06-28 12:05:30.588 13491-13491/com.worldspinner.portraits I/Capacitor/Console: File: http://localhost/App.js - Line 161953 - Msg: �[34mdebug�[39m: Getting album
2020-06-28 12:05:30.588 13491-13585/com.worldspinner.portraits V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 19483038, pluginId: MediaPlugin, methodName: getAlbums
2020-06-28 12:05:30.588 13491-13585/com.worldspinner.portraits V/Capacitor: callback: 19483038, pluginId: MediaPlugin, methodName: getAlbums, methodData: {}
2020-06-28 12:05:30.588 13491-13567/com.worldspinner.portraits D/DEBUG LOG: GET ALBUMS
2020-06-28 12:05:30.589 13491-13567/com.worldspinner.portraits D/DEBUG LOG: HAS PERMISSION
2020-06-28 12:05:30.590 13491-13567/com.worldspinner.portraits D/DEBUG LOG: ___GET ALBUMS
2020-06-28 12:05:30.595 13491-13571/com.worldspinner.portraits D/eglCodecCommon: setVertexArrayObject: set vao to 1 (1) 17 6
2020-06-28 12:05:30.596 13491-13571/com.worldspinner.portraits D/eglCodecCommon: setVertexArrayObject: set vao to 3 (3) 32 0
2020-06-28 12:05:30.608 13491-13525/com.worldspinner.portraits D/eglCodecCommon: setVertexArrayObject: set vao to 1 (1) 7 4
2020-06-28 12:05:30.609 13491-13525/com.worldspinner.portraits D/eglCodecCommon: setVertexArrayObject: set vao to 0 (0) 7 8
2020-06-28 12:05:30.622 13491-13571/com.worldspinner.portraits D/eglCodecCommon: setVertexArrayObject: set vao to 1 (1) 17 6
2020-06-28 12:05:30.624 13491-13571/com.worldspinner.portraits D/eglCodecCommon: setVertexArrayObject: set vao to 3 (3) 32 0
2020-06-28 12:05:30.642 13491-13525/com.worldspinner.portraits D/eglCodecCommon: setVertexArrayObject: set vao to 1 (1) 7 4
2020-06-28 12:05:30.644 13491-13525/com.worldspinner.portraits D/eglCodecCommon: setVertexArrayObject: set vao to 0 (0) 7 8
2020-06-28 12:05:30.646 13491-13571/com.worldspinner.portraits D/eglCodecCommon: setVertexArrayObject: set vao to 1 (1) 17 6
2020-06-28 12:05:30.646 13491-13567/com.worldspinner.portraits E/Capacitor: Serious error executing plugin
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:99)
at com.getcapacitor.Bridge$1.run(Bridge.java:515)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: java.lang.IllegalArgumentException: Invalid column DISTINCT bucket_display_name
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:423)
at android.content.ContentResolver.query(ContentResolver.java:944)
at android.content.ContentResolver.query(ContentResolver.java:880)
at android.content.ContentResolver.query(ContentResolver.java:836)
at io.stewan.capacitor.media.MediaPlugin._getAlbums(MediaPlugin.java:62)
at io.stewan.capacitor.media.MediaPlugin.getAlbums(MediaPlugin.java:46)
at java.lang.reflect.Method.invoke(Native Method)
at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:99)
at com.getcapacitor.Bridge$1.run(Bridge.java:515)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.os.HandlerThread.run(HandlerThread.java:67)
from media.
hey @axis7818
can you check from latest ? 1.0.1
also check out changelog for a breaking change on java import
from media.
Hi @stewwan, thanks for the reply!
I just updated to the new version (and modified MainActivity.java appropriately). Unfortunately, I am still seeing the same behavior described above.
from media.
Hello,
I also have the same error using the latest version.
If you manually create the album tho, this error disappears (don't know if that can help you).
Here is the album directory path printed by the plugin when I create the album myself :
D/ENV LOG - ALBUM DIR: /storage/emulated/0/Pictures/Album Name
.
But when I don't create the album myself, here is the path printed before the error occurs :
D/ENV STORAGE: /storage/emulated/0/Album Name
from media.
are you able to reproduce it using this example?
from media.
@stewwan, That example is working on my physical device, but I am seeing the same stack trace when running on the emulator. I think the difference in behavior might be related to this check.
I should have specified before, but the devices I am using are test devices that did not have any albums. If I create one manually, it is returned just like @amakh said. However, I cannot properly create albums with the plugin.
from media.
@stewwan, is there any update on this? Or is there a suggested workaround?
from media.
I'm also interested on an update regarding this. Thank's!
from media.
Workaround for anyone trying to ignore Album already exists
:
Replace this line with call.success();
This isn't the real issue, the problem is certainly coming from the fact that the creation path of the folder is different than the reading path's one but the little fix isn't affecting anything.
Just to sum up, there are 2 different issues here:
- On android 10+, the app crashes with the stack trace exposed by @axis7818 (Invalid column DISTINCT)
I'm not into java but after some research, it looks like "DISTINCT" can't be use anymore so I tried to replace this line
String[] projection = new String[]{"DISTINCT " + MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME};
with
String[] projection = new String[] {MediaStore.Images.Media._ID, MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.Images.Media.DATE_TAKEN };
(I think it should be optimised by a name grouping or something)
And it did work on android 10 and still working on android 8.- The second issue is when the plugin tries to create an album
Album already exists
.
I have no clue on this one but the fact that it does work when the user manually creates the album first. However I forgot to mention that even in that case, the plugin is creating a new album under the "More albums" section of the default photo app instead of using the manually created album.
from media.
Hey @amakh - I just raised #10 before I saw your comment above.
I'm not too familiar with Java, but removing DISTINCT stops my app from crashing. I need to get an update out ASAP to fix this for my users... How have you done this, have you forked the project?
Thanks!
from media.
I removed DISTINCT & it started working. But follow this to create my issue:
Go to Gallery & Delete album created Album. As per this example: "My Album"
Now, try to save the image, it will display the error that "Album is already exist" which is not.
& it will not work.
Now go to Gallery & make "My Album" manually & Save image code will start again but this time, it will also create another blank "My Album". So two "My Album" in gallery you will see.
Is there any workaround for this?
from media.
@stewones do you know when this issue might be sorted as this is a great plugin
from media.
can someone try with latest plugin v3 and let me know?
from media.
I am looking at this now with v3 and see the same issue - it looks like all the albums get returned by getAlbums (and I can see none are the one I'm about to try and create). Then when I call createAlbum I get "Album already exists" error.
from media.
@stewones - i've encountered the same issue in v3
from media.
got a new androidy now I can debug this issue, looking into it right now.
from media.
I'm having a hard time fixing this one.
as a workaround you can just use the Capacitor Filesystem
API
Filesystem.writeFile({
recursive: true,
data: base64 as string,
path: `MY_ALBUM_NAME/my_image.png`,
directory: Directory.Documents,
});
The result expected would be stored on "Documents/MY_ALBUM_NAME/my_image.png".
It's seen inside "Other Albums" on the Camera app, and users have access to those media through document apps also
Tested on API 29+
from media.
@stewones or anyone else, is this still an issue? I'm unable to reproduce on my android device. You can try reproducing with the new example app; should be easy to use.
from media.
@nkalupahana I upgraded to the latest version (capacitor 4 + this plugin) and Album already exists
is still an issue.
However my dirty fix previously mentioned is still working:
Replace this line by call.success(); or call.resolve();
from media.
@amakh Okay, I think I have an idea of what the problem is. When the plugin creates an "album", all that's doing is creating a folder in the filesystem. This won't show up in getAlbums
, because there are no images in it (thanks, Android, that makes so much sense). However, when an image is put in that folder using the plugin, then the album shows up in all apps, and it'll come up in getAlbums
.
Let me know if this logic makes sense, or if there's something you know that might dispute this. (You can look for these folders yourself in your filesystem.) If so, some solutions; let me know what might make the most sense:
- Modify
getAlbums
in some way to also scan for empty folders (I think this is the best idea, but I'm not sure how consistent it'll be) - Allow
createAlbum
to not reject if the album folder to create is empty
from media.
That is indeed what's happening because I remember trying to manually create an album (directly from the gallery app) and it wasn't in the same folder than the one created by the plugin.
I agree that solution 1 looks better but tbh I don't have a big scope on android development.
from media.
Alright, I'm on it. Will try to do solution 1, and we'll see how it goes.
from media.
Related Issues (20)
- 199131008-c2327514-8987-4535-b377-41dbed6a8e52.png (1302×540)https://github.com/orgs/community/discussions/35791
- Type in your language with Gboard
- Error while copying media file HOT 10
- Media.savePhoto's Promise<PhotoResponse> returns 'undefined' on iOS HOT 2
- Read file path from platform-specific identifier on iOS HOT 1
- docs(android): make it clear that file return on savePhoto is only available on Android
- App crash after downloading an image HOT 8
- App is crashed on Android due to EACCES (Permission denied) HOT 11
- Is there any method to retrieve more photos like using offset in query? HOT 1
- feat(android): add getAlbumsPath() function to get where albums are stored on filesystem
- Error: RuntimeException occurred : In SaveVideo method HOT 1
- READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE are still required in Android 13 HOT 5
- RuntimeException occurred / EACCES (Permission denied) when trying to save a photo/gif/video on android < 13 HOT 12
- When wanting to save photo to Album with identifier, getting identifier doesnt exist even tho Album exist HOT 3
- feat(ios): support jpeg files instead of png HOT 3
- Camera plugin is not implement on Android (Capacitor Camera) when pairing with Capacitor-Community/Media HOT 2
- savePhoto is not working in android 8.1.0 Samsung SM-T580 tablet HOT 1
- MediaFetchOptions support individual photo for high resolution HOT 2
- feat(ios): get specific media by identifier HOT 9
- feat: has access right / error codes for all errors HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from media.