google / java-photoslibrary

Java client library for the Google Photos Library API
http://developers.google.com/photos
Apache License 2.0
108 stars 59 forks source link

java.lang.NoClassDefFoundError when attempting to create the PhotosLibraryClient #45

Closed GambitDev closed 2 years ago

GambitDev commented 2 years ago

Hi I have encountered a very strange crash while using this library, trying to create a client using PhotosLibraryClient.initialize(clientSettings) crashes the app with the following stack (I have removed paths mentioned in it and changed my package name)

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.my.package, PID: 6210
    java.lang.NoClassDefFoundError: Failed resolution of: Lio/grpc/CallCredentials2;
        at io.grpc.auth.MoreCallCredentials.from(MoreCallCredentials.java:35)
        at com.google.api.gax.grpc.GrpcCallContext.withCredentials(GrpcCallContext.java:131)
        at com.google.api.gax.grpc.GrpcCallContext.withCredentials(GrpcCallContext.java:64)
        at com.google.api.gax.rpc.ClientContext.create(ClientContext.java:174)
        at com.google.photos.library.v1.internal.stub.GrpcPhotosLibraryStub.create(GrpcPhotosLibraryStub.java:306)
        at com.google.photos.library.v1.internal.stub.PhotosLibraryStubSettings.createStub(PhotosLibraryStubSettings.java:283)
        at com.google.photos.library.v1.internal.InternalPhotosLibraryClient.<init>(InternalPhotosLibraryClient.java:183)
        at com.google.photos.library.v1.PhotosLibraryClient.<init>(PhotosLibraryClient.java:103)
        at com.google.photos.library.v1.PhotosLibraryClient.initialize(PhotosLibraryClient.java:116)
        at com.my.package.managers.data.PhotosDataManager.<init>(PhotosDataManager.kt:32)
        at com.my.package.managers.data.DataManager.<init>(DataManager.kt:17)
        at com.my.package.data.dagger.DependencyProvider.provideDataManager(DependencyProvider.kt:39)
        at com.my.package.data.dagger.DependencyProvider_ProvideDataManagerFactory.provideDataManager(DependencyProvider_ProvideDataManagerFactory.java:42)
        at com.my.package.DaggerLookApp_HiltComponents_SingletonC.dataManager(DaggerLookApp_HiltComponents_SingletonC.java:128)
        at com.my.package.DaggerLookApp_HiltComponents_SingletonC.access$2600(DaggerLookApp_HiltComponents_SingletonC.java:67)
        at com.my.package.DaggerLookApp_HiltComponents_SingletonC$SwitchingProvider.get(DaggerLookApp_HiltComponents_SingletonC.java:630)
        at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
        at com.my.package.DaggerLookApp_HiltComponents_SingletonC.imageViewModel(DaggerLookApp_HiltComponents_SingletonC.java:132)
        at com.my.package.DaggerLookApp_HiltComponents_SingletonC.access$1200(DaggerLookApp_HiltComponents_SingletonC.java:67)
        at com.my.package.DaggerLookApp_HiltComponents_SingletonC$FragmentCImpl.injectLookGuidedStepSupportFragment2(DaggerLookApp_HiltComponents_SingletonC.java:428)
        at com.my.package.DaggerLookApp_HiltComponents_SingletonC$FragmentCImpl.injectLookGuidedStepSupportFragment(DaggerLookApp_HiltComponents_SingletonC.java:412)
        at com.my.package.ui.source_picker.Hilt_LookGuidedStepSupportFragment.inject(Hilt_LookGuidedStepSupportFragment.java:100)
        at com.my.package.ui.source_picker.Hilt_LookGuidedStepSupportFragment.onAttach(Hilt_LookGuidedStepSupportFragment.java:51)
        at androidx.fragment.app.Fragment.onAttach(Fragment.java:1783)
        at com.my.package.ui.source_picker.Hilt_LookGuidedStepSupportFragment.onAttach(Hilt_LookGuidedStepSupportFragment.java:39)
        at androidx.fragment.app.Fragment.performAttach(Fragment.java:2922)
        at androidx.fragment.app.FragmentStateManager.attach(FragmentStateManager.java:464)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:275)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3138)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:502)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1391)
E/AndroidRuntime:     at android.app.Activity.performStart(Activity.java:7165)
        at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2938)
        at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
        at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6680)
        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.ClassNotFoundException: Didn't find class "io.grpc.CallCredentials2" on path: DexPathList[[zip file "my-path"],nativeLibraryDirectories=[some-more-paths]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
            ... 50 more

After digging a bit into it, it seems that the CallCredentials2 class does not exists. From the source code:

// TODO(zhangkun83): remove the suppression after we change the base class to CallCredential
@SuppressWarnings("deprecation")
final class GoogleAuthLibraryCallCredentials extends io.grpc.CallCredentials2 {
... rest of the class ...

After a quick google search of this missing class I found this link to it's docs: https://www.javadoc.io/static/io.grpc/grpc-api/1.25.0/io/grpc/CallCredentials2.html where it is stated that THIS CLASS NAME IS TEMPORARY and is part of a migration. This class will BE DELETED as it replaces CallCredentials in short-term. THIS CLASS IS ONLY REFERENCED BY IMPLEMENTIONS. All consumers should be always referencing CallCredentials.

Is it possible that this actually happened? that CallCredentials2 does not exist anymore and the photo library is still attempting to use it?

I'm using version 1.7.1 of the photos library, and this is the way I attempt to create the client:

private val service: PhotosLibraryClient

    init {
        val token = sharedPrefManager.getPhotosTokenFromPref()
        val accessToken = AccessToken(token, null)
        val clientSettings = PhotosLibrarySettings.newBuilder()
            .setCredentialsProvider(
                FixedCredentialsProvider.create(
                    UserCredentials.newBuilder()
                        .setClientId("id")
                        .setClientSecret("secret")
                        .setAccessToken(accessToken)
                        .build()
                )
            ).build()
        service = PhotosLibraryClient.initialize(clientSettings)
        Log.d(TAG, "PhotosLibraryClient initialized!")
    }

this is the part I think is relevant from my app's build dependency block:

    implementation ('com.google.apis:google-api-services-drive:v3-rev110-1.23.0') {
        exclude group: 'com.google.guava'
    }
    implementation ('com.google.api-client:google-api-client-android:1.20.0') {
        exclude group: 'com.google.guava'
    }

    implementation 'com.google.android.gms:play-services-auth:19.2.0'
    implementation 'com.google.photos.library:google-photos-library-client:1.7.1'

    // hilt
    implementation "com.google.dagger:hilt-android:2.38.1"
    kapt "com.google.dagger:hilt-compiler:2.38.1"

    // grpc
    implementation 'io.grpc:grpc-okhttp:1.43.0'
    implementation 'io.grpc:grpc-stub:1.43.0'
    implementation 'io.grpc:grpc-netty:1.21.1'
    implementation 'io.grpc:grpc-protobuf:1.37.0'

Could it be something else? How can I go about fixing this issue? I would be happy to share more code or information if needed

Thanks

gavingt commented 2 years ago

@GambitDev Did you figure out a workaround for this?

GambitDev commented 2 years ago

@gavingt Yeah there is definitely a bug in this library Apparently as I thought this class was removed from the grpc libraries So we have to use an older version for this class to exist.. Changing this:

implementation 'io.grpc:grpc-okhttp:1.43.0'
implementation 'io.grpc:grpc-stub:1.43.0'

to this:

implementation 'io.grpc:grpc-okhttp:1.41.0'
implementation 'io.grpc:grpc-stub:1.41.0'

Solved it for me I have to note that it is extremely discouraging to find a bug like this in an official google library, Especially when I get no replies for nearly 2 months on such a critical issue

gavingt commented 2 years ago

I came to the same conclusion. Actually, 1.42.2 seems to be the most recent working version.

EDIT: For some reason, 1.42.2 no longer works for me. 1.41.0 is indeed the way to go.

jfschmakeit commented 2 years ago

This issue is actually related to some underlying dependencies and the GRPC-java API library we use - there have been some changes in the grpc and gax libraries that caused this to break.

For now, please use the io.grpc dependencies and versions as specified for this library.

We already have an update in the works that will address this and some other related issues shortly. Thank you for your patience!

jfschmakeit commented 2 years ago

This has been addressed in c3a35d77cdc9eb1c8f175a67588b73197a273f03 - we are aiming to roll this into a new release shortly.

If you are using the Java Google OAuth Library with HTTP features to obtain credentials, you will also need to specify this now explicitly as a dependency in your project.

jfschmakeit commented 2 years ago

We have released version 1.7.2, which includes a fix for this issue and updated dependencies.

Please reopen this issue if you are still seeing this error after upgrading your dependency. Thanks!