title: AuthorizationCodeInstalledApp - Android Alternative
body: <p>I'm trying to Authenticate into Google Oauth with Android, I successfully authenticate, store my credentials and auth token but then there's one particular piece of code that I am falling over at; returning an instance of <code>AuthorizationCodeInstalledApp</code>. The problem seems to be that this API is made for Java desktop applications and is trying to load a browser instance. Here is my <code>GoogleCredentialsUtilityModule</code>, a slightly refactored version of the code that is shown in the Android developer docs: </p>
  
  <pre><code>
  import android.content.Context
  import android.os.AsyncTask
  import com.example.bluelightlite.constants.CREDENTIALS_FILE_PATH
  import com.example.bluelightlite.constants.JSON_FACTORY
  import com.example.bluelightlite.constants.SCOPES
  import com.example.bluelightlite.constants.TOKENS_DIRECTORY_PATH
  import com.google.api.client.auth.oauth2.Credential
  import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp
  import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver
  import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow
  import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets
  import com.google.api.client.http.javanet.NetHttpTransport
  import com.google.api.client.util.store.FileDataStoreFactory
  import java.io.File
  import java.io.FileNotFoundException
  import java.io.InputStream
  import java.io.InputStreamReader
  
  
  class GoogleCredentialsUtilityModule constructor(private val context: Context): AsyncTask&lt;NetHttpTransport, Void, Credential&gt;() {
  
      /**
       * Starts getting credentials on a different thread by implementing
       * AsyncTask&lt;&gt;()
       * @param params: a list of parameters
       * @return Google Credentials that come from this.getCredentials()
       */
      override fun doInBackground(vararg params: NetHttpTransport): Credential {
          return this.getCredentials(params[0])
      }
  
      /**
       * Creates an authorized Credential object.
       * @param HTTP_TRANSPORT The network HTTP Transport.
       * @return An authorized Credential object.
       * @throws java.io.IOException If the credentials.json file cannot be found.
       */
      private fun getCredentials(HTTP_TRANSPORT: NetHttpTransport): Credential {
  
          val inputStream: InputStream = getCredentialsAsInputStream()
          val clientSecrets: GoogleClientSecrets = GoogleClientSecrets.load(JSON_FACTORY, InputStreamReader(inputStream))
  
          createTokenFolderIfMissing()
  
          val authorisationFlow: GoogleAuthorizationCodeFlow = getAuthorisationFlow(HTTP_TRANSPORT, clientSecrets)
          val receiver: LocalServerReceiver = LocalServerReceiver.Builder()
              .setPort(8888)
              .build()
  
          return AuthorizationCodeInstalledApp(authorisationFlow, receiver).authorize("user") //falls over here
      }
  
      /**
       * Gets the /credentials.json file
       * @return InputStream
       */
      private fun getCredentialsAsInputStream(): InputStream {
          return this.javaClass.getResourceAsStream(CREDENTIALS_FILE_PATH)
              ?: throw FileNotFoundException("Resource Not found: $CREDENTIALS_FILE_PATH")
      }
  
      /**
       * Creates the Tokens Folder for Google Authentication
       * Uses the current context for the folder path from
       * Context.getExternalFilesDir()
       */
      private fun createTokenFolderIfMissing() {
          val tokenFolder = getTokenFolder()
          if (!tokenFolder.exists()) {
              tokenFolder.mkdir()
          }
      }
  
      /**
       * gets External storage directory from the
       * current context
       * @return File
       */
      private fun getTokenFolder(): File {
          return File(this.context.getExternalFilesDir("")?.absolutePath + TOKENS_DIRECTORY_PATH)
      }
  
      /**
       * Gets authorisation flow so that the application can authenticate into Google Calendars
       * @param HTTP_TRANSPORT allows the app to use HTTP connections
       * @param clientSecrets secrets for authentication into Google
       * @return GoogleAuthorizationCodeFlow
       */
      private fun getAuthorisationFlow(HTTP_TRANSPORT: NetHttpTransport, clientSecrets: GoogleClientSecrets): GoogleAuthorizationCodeFlow {
          return GoogleAuthorizationCodeFlow.Builder(
              HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
              .setDataStoreFactory(FileDataStoreFactory(getTokenFolder()))
              .setAccessType("offline")
              .build()
      }
  }
  </code></pre>
  
  <p>Here is my error message:</p>
  
  <pre><code>02/21 20:04:33: Launching 'app' on Pixel 3 XL API 29.
  $ adb shell am start -n "com.example.bluelightlite/com.example.bluelightlite.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
  Connected to process 9795 on device 'Pixel_3_XL_API_29 [emulator-5554]'.
  Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
  D/libEGL: Emulator has host GPU support, qemu.gles is set to 1.
  W/RenderThread: type=1400 audit(0.0:48): avc: denied { write } for name="property_service" dev="tmpfs" ino=6831 scontext=u:r:untrusted_app:s0:c133,c256,c512,c768 tcontext=u:object_r:property_socket:s0 tclass=sock_file permissive=0 app=com.example.bluelightlite
  W/libc: Unable to set property "qemu.gles" to "1": connection failed; errno=13 (Permission denied)
  D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so
  D/libEGL: loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
  D/libEGL: loaded /vendor/lib/egl/libGLESv2_emulation.so
  W/System.err: 2020-02-21 20:04:39.683:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
      2020-02-21 20:04:39.684:INFO::jetty-0.0
  W/System.err: 2020-02-21 20:04:39.805:INFO::Started SocketConnector@localhost:8888
  I/System.out: Please open the following address in your browser:
        https://accounts.google.com/o/oauth2/auth?access_type=offline&amp;client_id=475059597551-bugt3i0nnfe7unsoqt8ghu2ovm7dfrqg.apps.googleusercontent.com&amp;redirect_uri=http://localhost:8888/Callback&amp;response_type=code&amp;scope=https://www.googleapis.com/auth/calendar.readonly
  W/System.err: 2020-02-21 20:04:39.823:INFO::Stopped SocketConnector@localhost:8888
  D/AndroidRuntime: Shutting down VM
  E/AndroidRuntime: FATAL EXCEPTION: main
      Process: com.example.bluelightlite, PID: 9795
      java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bluelightlite/com.example.bluelightlite.MainActivity}: java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/Desktop;
          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
          at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
          at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
          at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
          at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
          at android.os.Handler.dispatchMessage(Handler.java:107)
          at android.os.Looper.loop(Looper.java:214)
          at android.app.ActivityThread.main(ActivityThread.java:7356)
          at java.lang.reflect.Method.invoke(Native Method)
          at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
       Caused by: java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/Desktop;
          at java.util.concurrent.FutureTask.report(FutureTask.java:123)
          at java.util.concurrent.FutureTask.get(FutureTask.java:193)
          at android.os.AsyncTask.get(AsyncTask.java:602)
          at com.example.bluelightlite.models.GoogleCalenderCredentials.&lt;init&gt;(GoogleCalanderCredentials.kt:15)
          at com.example.bluelightlite.modules.GoogleCalendarsServiceModule.&lt;init&gt;(GoogleCalendarsServiceModule.kt:11)
          at com.example.bluelightlite.MainActivity.onCreate(MainActivity.kt:25)
          at android.app.Activity.performCreate(Activity.java:7802)
          at android.app.Activity.performCreate(Activity.java:7791)
          at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
          at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
          at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
          at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
          at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
          at android.os.Handler.dispatchMessage(Handler.java:107) 
          at android.os.Looper.loop(Looper.java:214) 
          at android.app.ActivityThread.main(ActivityThread.java:7356) 
          at java.lang.reflect.Method.invoke(Native Method) 
          at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
       Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/Desktop;
          at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.browse(AuthorizationCodeInstalledApp.java:129)
          at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.onAuthorization(AuthorizationCodeInstalledApp.java:113)
          at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.authorize(AuthorizationCodeInstalledApp.java:81)
          at com.example.bluelightlite.modules.GoogleCredentialsUtilityModule.getCredentials(GoogleCredentialsUtilityModule.kt:52)
          at com.example.bluelightlite.modules.GoogleCredentialsUtilityModule.doInBackground(GoogleCredentialsUtilityModule.kt:31)
          at com.example.bluelightlite.modules.GoogleCredentialsUtilityModule.doInBackground(GoogleCredentialsUtilityModule.kt:22)
          at android.os.AsyncTask$3.call(AsyncTask.java:378)
          at java.util.concurrent.FutureTask.run(FutureTask.java:266)
          at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
          at java.lang.Thread.run(Thread.java:919)
       Caused by: java.lang.ClassNotFoundException: Didn't find class "java.awt.Desktop" on path: DexPathList[[zip file "/data/app/com.example.bluelightlite-6neG3BDx7D1LEKBl_6YMYg==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.bluelightlite-6neG3BDx7D1LEKBl_6YMYg==/lib/x86, /system/lib, /system/product/lib]]
          at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196)
          at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
          at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
          at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.browse(AuthorizationCodeInstalledApp.java:129) 
          at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.onAuthorization(AuthorizationCodeInstalledApp.java:113) 
          at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.authorize(AuthorizationCodeInstalledApp.java:81) 
          at com.example.bluelightlite.modules.GoogleCredentialsUtilityModule.getCredentials(GoogleCredentialsUtilityModule.kt:52) 
          at com.example.bluelightlite.modules.GoogleCredentialsUtilityModule.doInBackground(GoogleCredentialsUtilityModule.kt:31) 
          at com.example.bluelightlite.modules.GoogleCredentialsUtilityModule.doInBackground(GoogleCredentialsUtilityModule.kt:22) 
          at android.os.AsyncTask$3.call(AsyncTask.java:378) 
          at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
          at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289) 
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
          at java.lang.Thread.run(Thread.java:919) 
  I/Process: Sending signal. PID: 9795 SIG: 9
  </code></pre>
  
  <p>I can't seem to find any alternative to <code>AuthorizationCodeInstalledApp</code>. Any advice? Should I write my own Authentication code? Is there an Android version of AuthorizationCodeInstalledApp that I can use? I'm finding the documentation so vague and hard to read. </p>
  
  <p>Developing on API 29 using a Google Pixel 3 XL. </p>