mvysny / photocloud-frame-slideshow

Android Digital Photo Frame
https://www.android-photo-frame.eu
14 stars 1 forks source link

Add support for Google Photos (take 2) [$50] #118

Closed mzakharo closed 4 years ago

mzakharo commented 4 years ago

Google photos no longer has any settings to toggle Drive integration and this method is not available. https://github.com/mvysny/photocloud-frame-slideshow/issues/52 solution does not work for me.

All I see under https://photos.google.com/settings is this:

Google Drive New photos and videos from Google Drive no longer sync. Existing items are still in your library. learn more

Also, Google Photos API must exist in some form, since I can browse Google Photos on my Oculus Quest VR (an Android device) through a third party (Oculus/Facebook Photos App).

Also https://stackoverflow.com/a/56611943 may help.

--- Did you fix this issue? Go claim the **[$50 bounty](https://www.bountysource.com/issues/87245508-add-support-for-google-photos-take-2?utm_campaign=plugin&utm_content=tracker%2F53303527&utm_medium=issues&utm_source=github)** on [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F53303527&utm_medium=issues&utm_source=github).
licarijd commented 4 years ago

Hi, where's the code? This project doesn't have a src directory

mvysny commented 4 years ago

Hi, yes, this project is not an open-source project unfortunately.

ImUrX commented 4 years ago

There is a google photos API since around May 9 of 2018, you can find it here with actual java, php and rest examples. If this is not what you are looking for, can you explain the problem in a better way?

mvysny commented 4 years ago

Thank you very much! I've been burned by trying to use Google APIs as can be seen at #52 . However, the Library API at https://developers.google.com/photos/library/guides/overview looks like it's something new and actually something that might work. I've registered the PhotoCloud to access the Google Photo API and I'll try to play with it a bit.

mvysny commented 4 years ago

Okay Google seriously what the fuck:

  1. There is no example for Android, only for Java server (?!?)
  2. The com.google.photos.library:google-photos-library-client:1.4.0 has shitload of dependencies:
+--- com.google.photos.library:google-photos-library-client:1.4.0
|    \--- com.google.api:gax-grpc:1.45.0
|         +--- com.google.api:gax:1.45.0
|         |    +--- com.google.guava:guava:26.0-android -> 27.1-android (*)
|         |    +--- com.google.code.findbugs:jsr305:3.0.2
|         |    +--- org.threeten:threetenbp:1.3.3
|         |    +--- com.google.auth:google-auth-library-oauth2-http:0.15.0
|         |    |    +--- com.google.auth:google-auth-library-credentials:0.15.0
|         |    |    +--- com.google.http-client:google-http-client:1.29.0 (*)
|         |    |    +--- com.google.http-client:google-http-client-jackson2:1.29.0 (*)
|         |    |    \--- com.google.guava:guava:27.1-android (*)
|         |    +--- com.google.api:api-common:1.7.0 -> 1.8.1
|         |    |    +--- com.google.code.findbugs:jsr305:3.0.2
|         |    |    +--- com.google.guava:guava:26.0-android -> 27.1-android (*)
|         |    |    \--- javax.annotation:javax.annotation-api:1.3.2
|         |    \--- io.opencensus:opencensus-api:0.21.0 (*)
|         +--- io.grpc:grpc-stub:1.21.0
|         |    \--- io.grpc:grpc-api:1.21.0
|         |         +--- io.grpc:grpc-context:1.21.0
|         |         +--- com.google.errorprone:error_prone_annotations:2.3.2
|         |         +--- com.google.code.findbugs:jsr305:3.0.2
|         |         +--- org.codehaus.mojo:animal-sniffer-annotations:1.17
|         |         \--- com.google.guava:guava:26.0-android -> 27.1-android (*)
|         +--- io.grpc:grpc-auth:1.21.0
|         |    +--- io.grpc:grpc-api:[1.21.0] -> 1.21.0 (*)
|         |    \--- com.google.auth:google-auth-library-credentials:0.13.0 -> 0.15.0
|         +--- io.grpc:grpc-protobuf:1.21.0
|         |    +--- io.grpc:grpc-api:1.21.0 (*)
|         |    +--- com.google.protobuf:protobuf-java:3.7.1
|         |    +--- com.google.guava:guava:26.0-android -> 27.1-android (*)
|         |    +--- com.google.api.grpc:proto-google-common-protos:1.12.0 -> 1.16.0
|         |    |    \--- com.google.protobuf:protobuf-java:3.7.1
|         |    \--- io.grpc:grpc-protobuf-lite:1.21.0
|         |         +--- io.grpc:grpc-api:1.21.0 (*)
|         |         \--- com.google.guava:guava:26.0-android -> 27.1-android (*)
|         +--- com.google.guava:guava:26.0-android -> 27.1-android (*)
|         +--- com.google.code.findbugs:jsr305:3.0.2
|         +--- org.threeten:threetenbp:1.3.3
|         +--- com.google.auth:google-auth-library-oauth2-http:0.15.0 (*)
|         +--- com.google.auth:google-auth-library-credentials:0.15.0
|         +--- com.google.api.grpc:proto-google-common-protos:1.14.0 -> 1.16.0 (*)
|         +--- com.google.api:api-common:1.7.0 -> 1.8.1 (*)
|         +--- io.grpc:grpc-netty-shaded:1.21.0
|         \--- io.grpc:grpc-alts:1.21.0
|              +--- io.grpc:grpc-grpclb:1.21.0
|              |    +--- io.grpc:grpc-core:[1.21.0] -> 1.21.0
|              |    |    +--- io.opencensus:opencensus-api:0.21.0 (*)
|              |    |    +--- io.grpc:grpc-api:[1.21.0] -> 1.21.0 (*)
|              |    |    +--- com.google.code.gson:gson:2.7 -> 2.8.5
|              |    |    +--- com.google.android:annotations:4.1.1.4
|              |    |    \--- io.opencensus:opencensus-contrib-grpc-metrics:0.21.0
|              |    |         \--- io.opencensus:opencensus-api:0.21.0 (*)
|              |    +--- io.grpc:grpc-protobuf:1.21.0 (*)
|              |    +--- io.grpc:grpc-stub:1.21.0 (*)
|              |    +--- com.google.protobuf:protobuf-java:3.7.1
|              |    \--- com.google.protobuf:protobuf-java-util:3.7.1
|              |         +--- com.google.protobuf:protobuf-java:3.7.1
|              |         +--- com.google.errorprone:error_prone_annotations:2.3.2
|              |         \--- com.google.code.gson:gson:2.7 -> 2.8.5
|              +--- io.grpc:grpc-auth:1.21.0 (*)
|              +--- io.grpc:grpc-core:[1.21.0] -> 1.21.0 (*)
|              +--- io.grpc:grpc-netty-shaded:[1.21.0] -> 1.21.0
|              +--- io.grpc:grpc-protobuf:1.21.0 (*)
|              +--- io.grpc:grpc-stub:1.21.0 (*)
|              +--- org.apache.commons:commons-lang3:3.5
|              +--- com.google.protobuf:protobuf-java:3.7.1
|              \--- com.google.auth:google-auth-library-oauth2-http:0.13.0 -> 0.15.0 (*)

Netty? gRPC? Protobuf? Guava? And whatever the hell threeten:threetenbp is?

sigh Typical Google crap. Oh Google, how far you've fallen.

So "Getting Started With Java" is not the way to go. "Getting Started With PHP" is definitely not the way to go. So all that's left is "Getting Started With REST".

mvysny commented 4 years ago

Found an example app, hopefully there could be something usable there: https://codelabs.developers.google.com/codelabs/google-photos-sharing/#0

OH GREAT that example app is implemented in Dart using some Flutter crap.

mvysny commented 4 years ago

The Example app is useless since it uses some weird-shit Dart APIs: https://stackoverflow.com/questions/52238775/how-do-i-authenticate-with-googles-rest-services-using-a-googlesigninaccount/59892742#59892742

I swear I'll pay $100 to the poor soul which manages to get this shit running.

mzakharo commented 4 years ago

Not sure I understand the issue you raise with com.google.photos.library:google-photos-library-client:1.4.0

Does it not work or you are simply opposed to the philosophy of corporately managed projects?

I have seen the same thing with their python library (it has protobufs, gRPC and about 100+ dependencies), however, it all works in the end, and who could care less about it?

threeten:threetenbp according to google is a backport of some java 8 features to 7 and 6. Makes sense, google is bleeding edge and code needs to run on android 2.0-10, or whatever the real reason is.

mvysny commented 4 years ago

I generally like the idea of gradle managing transitive dependencies, and I'm definitely not opposed to a library having a reasonable amount of dependencies. That being said:

  1. The amount of dependencies of google-photos-library-client simply is not reasonable, the term is "ridiculous"
  2. Adding google-photos-library-client fails to build, at least because of conflicting guava versions

who could care less about it?

Please remember: this is an Android app, not a server-side Python stuff (where I'm completely fine with lots of dependencies). Adding 20mb of jars to an Android app is a big no-no. Also, additional problem is that there already are lots of client libraries for lots of backends, with their respective transitive deps. Adding another sometimes feels like adding a domino piece.

ImUrX commented 4 years ago

well from what i just see google/java-photoslibrary#2 (sorry for not finding this before posting what i sent), there are some ways of doing this i havent read the repo that is mentioned in there, and the other way is just doing REST, I can give some piece of code on how to the the REST part, im very accostumed in doing so. the last comment on the issue suggests using retrofit for example but maybe you already have a lib for taking care of this kind of stuff? and from what im seeing, the second comment is how someone actually used the api through retrofit in android

mvysny commented 4 years ago

Thank you. Unfortunately, the problem is with Google Auth:

  1. how to register the app - should I register as Android, Web Server or Web Client? :man_facepalming:
  2. How to obtain the access token from the username/password? (Access Token needs to be passed to every REST call)

Doing the REST call itself is very easy.

ImUrX commented 4 years ago

ok i think number 1 is answered in here and number 2 is told in here

ImUrX commented 4 years ago

Sorry if I'm not of much help ;-; we could talk faster by discord (Uriel#2500) or twitter (@urielfontan), github issues are better at proposals and issues with a lot of info imo.

On Monday, January 27, 2020, Martin Vysny notifications@github.com wrote:

Thank you. Unfortunately, the problem is with Google Auth:

  1. how to register the app - should I register as Android, Web Server or Web Client? 🤦‍♂
  2. How to obtain the access token from the username/password? (Access Token needs to be passed to every REST call)

Doing the REST call itself is very easy.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mvysny/photocloud-frame-slideshow/issues/118?email_source=notifications&email_token=AA4G4PIBQD4X55OJNENVPB3Q7ZYVNA5CNFSM4KI542BKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJ6L5YY#issuecomment-578600675, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA4G4PMHGKKDAV2W43F22BLQ7ZYVNANCNFSM4KI542BA .

mvysny commented 4 years ago

Hi, thank you for the links, unfortunately I just recently wandered dangerously close to a burnout, so at current time I'm trying to avoid computers (with the exception of my job) :( Please be patient, I'll try to take a look at the links at some point during the week.

ImUrX commented 4 years ago

Ah, I understand now, I thought you were kind of angry at me. Sorry EDIT: And good luck with everything

mvysny commented 4 years ago

I'm very sorry, I did not mean to harm your feelings in any way :( I apologize. I hope I did no harm.

It's actually the Google documentation which drives me mad - it's bloated, obsolete, contradicting and usually very hard to find anything usable there :( Yet let me take a look at the links you posted at some point this week.

ImUrX commented 4 years ago

Don't worry, I'm the one who is trying to get your money so I really think you should say when I'm not being helpful :P, I will wait until you get your time to see the links, dont worry, and very thanks for answering all my offtopic comments :)

mvysny commented 4 years ago

The first link shows the problem with Google documentation: it starts with creating an Android app and then suddenly I'm creating credentials for backend server / web application? Totally confusing. However, this could be the correct way forward since the client ID looks usable:

Pass this client ID to the requestIdToken or requestServerAuthCode method when you create the GoogleSignInOptions object.

I can try to create an Authorized redirect URIs to which only my app will respond. Let me try.

mvysny commented 4 years ago

Too bad. Usually Android apps capture links such as photoframecloude3f4295e497e11ea920fb7061c4694fe://foo.local for back OAuth2 redirect. However, unfortunately Google only accepts https:// and the domain must exist. I've submitted https://www.android-photo-frame.eu/ for verification, perhaps I can capture the browser as it is returning from OAuth to https://www.android-photo-frame.eu/ . However that sounds like a security issue lurking (an app catching all navigations to https://www.android-photo-frame.eu/ )... I don't think it's the correct way of doing things.

Apparently the REST client is supposed to only be used from a web server; Android clients are probably supposed to use Android-based libraries created for that very purpose... Or not? (the Dart+Flutter crap apparently is able to use REST from Android - or is it actually an Android app? Flutter is some kind of abstraction thing, perhaps it's a web server after all).

Unfortunately this is The Current Google Experience - going in circles, swarmed with useless stuff.

mvysny commented 4 years ago

However, MAYBE I can disassemble the Google Drive client (since it's apparently capable of performing REST calls as well) and retrieve the token from it. The GoogleAccountCredential is able to get token and pass it as a https header "bearer " + token... Hmmmmmmmmm.... What if I tried to obtain GoogleAccountCredential but for the Picassa scope, get the token and do REST? Worth a try!

mvysny commented 4 years ago

Apparently GoogleAccountCredential uses https://github.com/googleapis/google-http-java-client and of course there is no quickstart page in the official documentation on how to use that piece of shit. Luckily there are some examples at https://www.baeldung.com/google-http-client

ImUrX commented 4 years ago

the backend part says If your app authenticates with a backend server or accesses Google APIs from your backend server, so you shouldnt do it and then the next section gives https://developers.google.com/identity/sign-in/android/sign-in dont know if this helps EDIT: this is obviously using https://developers.google.com/identity/sign-in/android/start-integrating#add_google_play_services

mvysny commented 4 years ago

the backend part says If your app authenticates with a backend server or accesses Google APIs from your backend server, so you shouldnt do it

That piece of info shouldn't be there in the first place, since the document deals with Android apps. Documenting backend app in an Android app article is confusing.

Unfortunately, there is nothing obvious at Google documentation (at least for me the documentation is full of unobvious dead ends). Luckily, now I feel I'm getting somewhere with this Sign-in via play-services-auth. I already have Google Drive code which uses the same thing already; I'll copy the code and modify it to login to Photos instead, then I'll try to obtain the token and call the REST and let's see where that will lead.

mvysny commented 4 years ago

Breakthrough! I was able to successfully copy my Google Drive code and wire GoogleAccountCredential into HttpTransport and GET https://photoslibrary.googleapis.com/v1/albums . Now I need to get the photos via REST, which is definitely doable.

mvysny commented 4 years ago

Implemented in 1.13.13

ImUrX commented 4 years ago

lel the bountysource was for code not help xd, np

mzakharo commented 4 years ago

Not working for me. I get "Google photos is not supported on your HTC Nexus 9". Official app has no problem working. So unfortunately no bounty until resolved.

mvysny commented 4 years ago

This is displayed when there was an exception during Google Photos login. Unfortunately the exception has not yet been transferred to my console. Would you be interested in connecting your phone via dev mode to USB and getting the exception for me please?

As a temporary workaround, could you please try reinstalling PhotoCloud and trying again?

mzakharo commented 4 years ago

Reinstalling the app did not help. What adb commands do I run to get you the trace?

mvysny commented 4 years ago

The adb logcat should do the trick - it will start printing the log from your device. Afterwards, try to reproduce the "Google photos is not supported..." message - a stack-trace should be shown in the log which will looks like this: http://aedict.eu/faq.html section Aedict 3 log.

mvysny commented 4 years ago

I've received a couple of Google Photos-related crashes and I've fixed a couple of things. Could you please try update to 1.13.14 and let me know?

mvysny commented 4 years ago

I've received a couple of additional bug reports and I've pushed out 1.13.15. Please feel free to update and reopen this issue if Google Photos still don't work for you.

mzakharo commented 4 years ago

Just tried it and it connects and plays a few photos, however, it seems to be always picking a very small set of recent photos at the start. In my Photos account, I have many of folders full of 1000+s of photos, and yet, I have 'Random' selected in the App settings, but the slideshow always starts with a few most recent photos, and randomizes between them. It does not seem to be working to the same capacity as compared to 'Gallery' source that I have been using previously.

mvysny commented 4 years ago

That is unfortunately correct. The Google photos API doesn't support retrieving of the photos in random fashion. It will enumerate all photos, but always newest first. I'll try to revisit the whole API to search for such option, or devise a workaround.

mzakharo commented 4 years ago

The slideshow does progress further and further back in time, which is pretty sweet. However, if it is interrupted (stop and restart dream mode), it resumes back from the beginning. Even if it is difficult to make it truly random, maybe it would be possible to 'resume' the slideshow where it was showing last?

mvysny commented 4 years ago

Unfortunately the resume is not possible - the paging is done by the means of the page token, which typically expires immediately when used, or early (in a couple of minutes or hours) if unused.

However, what I can do is that I can quickly load the list of albums, randomize it, then slowly load the list of photos from every album, randomizing on the go. That can actually be done quite simply, however in order for this to work you have to have your photos assigned to lots of albums. Is it the case for you?

mzakharo commented 4 years ago

That would work for me. Can you allow selecting which albums are part of the mix?

On Mon., Feb. 24, 2020, 13:05 Martin Vysny, notifications@github.com wrote:

Unfortunately the resume is not possible - the paging is done by the means of the page token, which typically expires immediately when used, or early (in a couple of minutes or hours) if unused.

However, what I can do is that I can quickly load the list of albums, randomize it, then slowly load the list of photos from every album, randomizing on the go. That can actually be done quite simply, however in order for this to work you have to have your photos assigned to lots of albums. Is it the case for you?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mvysny/photocloud-frame-slideshow/issues/118?email_source=notifications&email_token=AAEKUOZQ7CMGYH3NNJOIAF3REQD7RA5CNFSM4KI542BKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEMY5T6A#issuecomment-590469624, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEKUO4WSZETNA7ZPEP74CDREQD7RANCNFSM4KI542BA .

mvysny commented 4 years ago

Yes, and you can do that right away. Just browse the Google Photos filesystem, long-touch an album and select "Root stream here". Only the photos from that album will now be played in the slideshow. Do that for all of the albums which you wish to be present in the mix.

mzakharo commented 4 years ago

Does that work for dream mode screensaver?

On Mon., Feb. 24, 2020, 13:11 Martin Vysny, notifications@github.com wrote:

Yes, and you can do that right away. Just browse the Google Photos filesystem, long-touch an album and select "Root stream here". Only the photos from that album will now be played in the slideshow. Do that for all of the albums which you wish to be present in the mix.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mvysny/photocloud-frame-slideshow/issues/118?email_source=notifications&email_token=AAEKUO5NMHOX7XBNBAUCZJLREQEVJA5CNFSM4KI542BKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEMY6HHQ#issuecomment-590472094, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEKUO2G5LC4GJSODHGOHYDREQEVJANCNFSM4KI542BA .

mvysny commented 4 years ago

Does that work for dream mode screensaver?

Yes. If not, it's a bug. The Dreaming Screensaver will take the global stream settings including the Root List configuration.

mzakharo commented 4 years ago

That root feature works for me. Thank you. You can request the bounty source again

On Tue., Feb. 25, 2020, 00:55 Martin Vysny, notifications@github.com wrote:

Does that work for dream mode screensaver?

Yes. If not, it's a bug. The Dreaming Screensaver will take the global stream settings including the Root List configuration.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mvysny/photocloud-frame-slideshow/issues/118?email_source=notifications&email_token=AAEKUO3NKIFAS4CY64Z2FRTRESXETA5CNFSM4KI542BKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEM2VH5A#issuecomment-590697460, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEKUO22NHINAGFPDPBPJLLRESXETANCNFSM4KI542BA .

mvysny commented 4 years ago

Thank you. Closing the bug since the original request has been implemented and the randomization is not possible with the official API (the workaround of loading a list of albums may not work if there are no albums and will miss photos not present in any albums, that's why I decided to not to implement it for now).