androidgoogle-apigoogle-api-clientandroid-youtube-api

Android - problem with Google API and Youtube Data v3


I am facing an issue with Youtube API v3, in particolar with Google API (gapi for short). My final goal is to call the Youtube Data API videos/list to obtain all the info about a specific video.

As per documentation, i followed the recommended steps until step 5 (the example there is a bit outdated) but without success.
Android quickstart doc: https://developers.google.com/youtube/v3/quickstart/android

So, i checked their API docs on how to compose said request here, and i tried composing the request with the parameters part: "snippet" and id: "o-YBDTqX_ZU" (or any other id). There you can see their implementation: uncheck OAuth 2.0 and leave only API Key, then Execute / Show code / Java. I tried to readjust their code to my needs.
https://developers.google.com/youtube/v3/docs/videos/list?hl=en
https://developers.google.com/explorer-help/guides/code_samples#java

Here's my app-level build.gradle

plugins {
  id 'com.android.application'
  id 'kotlin-android'
}

android {
  compileSdk 30

  defaultConfig {
    applicationId "com.example.testyoutubeapi"
    minSdk 23
    targetSdk 30
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
  }

  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
  kotlinOptions {
    jvmTarget = '1.8'
  }
}

dependencies {

  implementation 'androidx.core:core-ktx:1.6.0'
  implementation 'androidx.appcompat:appcompat:1.3.1'
  implementation 'com.google.android.material:material:1.4.0'
  implementation 'androidx.constraintlayout:constraintlayout:2.1.0'

  implementation 'com.google.android.gms:play-services-auth:19.2.0'
  implementation 'pub.devrel:easypermissions:0.3.0'

  implementation 'com.google.api-client:google-api-client:1.23.0'
  implementation 'com.google.oauth-client:google-oauth-client-jetty:1.23.0'
  implementation 'com.google.apis:google-api-services-youtube:v3-rev192-1.23.0'
  implementation 'com.google.api-client:google-api-client-android:1.23.0' exclude module: 'httpclient'

  implementation 'com.google.apis:google-api-services-tasks:v1-rev48-1.23.0' exclude module: 'httpclient'
  implementation 'com.google.http-client:google-http-client-gson:1.23.0' exclude module: 'httpclient'

  testImplementation 'junit:junit:4.13.2'

  androidTestImplementation 'androidx.test.ext:junit:1.1.3'
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

}

And here is my YoutubeAPI class

class YoutubeAPI() {

    companion object {
        const val DEVELOPER_KEY = "AIzaS......" // API key
        const val APPLICATION_NAME = "API code samples"
        private val JSON_FACTORY: JsonFactory = JacksonFactory.getDefaultInstance()
    }

    private fun getService(): YouTube {
        val httpTransport: HttpTransport = AndroidHttp.newCompatibleTransport() //GoogleNetHttpTransport.newTrustedTransport();
        return YouTube.Builder(httpTransport, JSON_FACTORY, null)
            .setApplicationName(APPLICATION_NAME)
            .build();
    }

    fun start(): VideoListResponse {
        val youtubeService = getService()
        val request: YouTube.Videos.List = youtubeService.videos()
            .list("snippet")
            .setKey(DEVELOPER_KEY)
            .setId("o-YBDTqX_ZU")

        return request.execute()
    }
}

Here, when calling AuthorizationCodeInstalledApp(flow, LocalServerReceiver()).authorize("user") an error is thrown, saying that the operation is not permitted

E/AndroidRuntime: FATAL EXCEPTION: Thread-2
    Process: com.example.testyoutubeapi, PID: 2209
    java.net.SocketException: socket failed: EPERM (Operation not permitted)
        at java.net.Socket.createImpl(Socket.java:492)
        at java.net.Socket.getImpl(Socket.java:552)
        at java.net.Socket.setSoTimeout(Socket.java:1180)
        at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:143)
        at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
        at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
        at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
        at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)
        at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:90)
        at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:30)
        at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:104)
        at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
        at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
        at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
        at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
        at com.example.testyoutubeapi.YoutubeAPI.start(YoutubeAPI.kt:47)
        at com.example.testyoutubeapi.MainActivity.onCreate$lambda-1$lambda-0(MainActivity.kt:23)
        at com.example.testyoutubeapi.MainActivity.$r8$lambda$6AdxmbUe_rlaFrgzSeLUApTyS2A(Unknown Source:0)
        at com.example.testyoutubeapi.MainActivity$$ExternalSyntheticLambda1.run(Unknown Source:4)
        at java.lang.Thread.run(Thread.java:919)

Solution

  • The problem here is that Google disable api calls after 90 days of inactivity. Maybe create a request that fires every X days (or ask your backend dev to do it).

    If that's not the case, this is a permnission-related problem. Please be sure to have the following permissions in your manifest file

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    

    Then, simply uninstall the app on the emulator, then

    Run your app again and it should work!