Java AuthorizationCodeInstalledApp-Android替代方案
我正试图用Android验证GoogleOAuth,我成功地验证、存储了我的凭证和身份验证令牌,但有一段特殊的代码让我陷入困境;返回Java AuthorizationCodeInstalledApp-Android替代方案,java,android,kotlin,oauth-2.0,Java,Android,Kotlin,Oauth 2.0,我正试图用Android验证GoogleOAuth,我成功地验证、存储了我的凭证和身份验证令牌,但有一段特殊的代码让我陷入困境;返回AuthorizationCodeInstalledApp的实例。问题似乎在于,该API是为Java桌面应用程序设计的,并且正在尝试加载浏览器实例。这是我的googlecredentialsutilitypodule,Android开发者文档中显示的代码的稍微重构版本: import android.content.Context import android.o
AuthorizationCodeInstalledApp
的实例。问题似乎在于,该API是为Java桌面应用程序设计的,并且正在尝试加载浏览器实例。这是我的googlecredentialsutilitypodule
,Android开发者文档中显示的代码的稍微重构版本:
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<NetHttpTransport, Void, Credential>() {
/**
* Starts getting credentials on a different thread by implementing
* AsyncTask<>()
* @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()
}
}
导入android.content.Context
导入android.os.AsyncTask
导入com.example.bluelightlite.constants.CREDENTIALS\u文件\u路径
导入com.example.bluelightlite.constants.JSON_工厂
导入com.example.bluelightlite.constants.SCOPES
导入com.example.bluelightlite.constants.TOKENS\u目录\u路径
导入com.google.api.client.auth.oauth2.Credential
导入com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp
导入com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver
导入com.google.api.client.googleapis.auth.oauth2.googleaauthorizationcodeflow
导入com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets
导入com.google.api.client.http.javanet.NetHttpTransport
导入com.google.api.client.util.store.FileDataStoreFactory
导入java.io.xml文件
导入java.io.FileNotFoundException
导入java.io.InputStream
导入java.io.InputStreamReader
类GoogleCredentialsUtilityModule构造函数(私有val上下文:上下文):AsyncTask(){
/**
*开始通过实现在不同线程上获取凭据
*AsyncTask()
*@param params:参数列表
*@返回来自此的Google凭据。getCredentials()
*/
覆盖fun doInBackground(vararg参数:NetHttpTransport):凭证{
返回此.getCredentials(参数[0])
}
/**
*创建授权凭据对象。
*@param HTTP_传输网络HTTP传输。
*@返回授权凭证对象。
*如果找不到credentials.json文件,@将抛出java.io.IOException。
*/
私有凭据(HTTP_传输:NetHttpTransport):凭据{
val inputStream:inputStream=getCredentialsAsInputStream()
val clientSecrets:GoogleClientSecrets=GoogleClientSecrets.load(JSON_工厂,InputStreamReader(inputStream))
createTokenFolderInfmissing()
val授权流:GoogleAuthorizationCodeFlow=GetAuthorizationFlow(HTTP_传输,客户端机密)
val receiver:LocalServerReceiver=LocalServerReceiver.Builder()
.设置端口(8888)
.build()
返回AuthorizationCodeInstalledApp(authorizationFlow,receiver)。authorization(“用户”)//在这里
}
/**
*获取/credentials.json文件
*@returninputstream
*/
private fun getCredentialsAsInputStream():InputStream{
返回此.javaClass.getResourceAsStream(凭证\u文件\u路径)
?:抛出FileNotFoundException(“未找到资源:$CREDENTIALS\u FILE\u PATH”)
}
/**
*为Google身份验证创建Tokens文件夹
*使用来自的文件夹路径的当前上下文
*Context.getExternalFilesDir()
*/
私人娱乐CreateTokeFolderIfmissing(){
val tokenFolder=getTokenFolder()
如果(!tokenFolder.exists()){
tokenFolder.mkdir()
}
}
/**
*从中获取外部存储目录
*当前上下文
*@return文件
*/
private fun getTokenFolder():文件{
返回文件(this.context.getExternalFilesDir(“”?.absolutePath+TOKENS\u目录\u路径)
}
/**
*获取授权流,以便应用程序可以在Google日历中进行身份验证
*@param HTTP_TRANSPORT允许应用程序使用HTTP连接
*@param clientSecrets用于谷歌认证的机密
*@return GoogleAuthorizationCodeFlow
*/
private fun GetAuthorizationFlow(HTTP_TRANSPORT:NetHttpTransport,clientSecrets:GoogleClientSecrets):GoogleAuthorizationCodeFlow{
返回GoogleAuthorizationCodeFlow.Builder(
HTTP_传输、JSON_工厂、客户端机密、作用域)
.setDataStoreFactory(FileDataStoreFactory(getTokenFolder()))
.setAccessType(“脱机”)
.build()
}
}
以下是我的错误消息:
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&client_id=475059597551-bugt3i0nnfe7unsoqt8ghu2ovm7dfrqg.apps.googleusercontent.com&redirect_uri=http://localhost:8888/Callback&response_type=code&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.<init>(GoogleCalanderCredentials.kt:15)
at com.example.bluelightlite.modules.GoogleCalendarsServiceModule.<init>(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
02/21 20:04:33:在Pixel 3 XL API 29上启动“应用程序”。
$adb shell am start-n“com.example.bluelightlite/com.example.bluelightlite.MainActivity”-一个android.intent.action.MAIN-c android.intent.category.LAUNCHER
已连接到设备“Pixel_3_XL_API_29[emulator-5554]”上的进程9795。
从应用程序捕获和显示logcat消息。可以在“调试器”设置页面的“Logcat输出”部分禁用此行为。
D/libEGL:Emulator具有主机GPU支持,qemu.gles设置为1。
W/RenderThread:type=1400 audit(0.0:48):avc:denied{write}for name=“property\u service”dev=“tmpfs”ino=6831 scontext=u:r:untrusted\u app:s0:c133、c256、c512、c768 tcontext=u:object\r:property\u socket:s0 tclass=sock\u file permissive=0 app=com.example.bluelightlite
W/libc:无法将属性“qemu.gles”设置为“1”:连接失败;errno=13(权限被拒绝)
D/libEGL:load/vendor/lib/egl/libEGL_.so
D/libEGL:load/vendor/lib/egl/libGLESv1_CM_emulation.so
D/libEGL:load/vendor/lib/egl/libGLESv2_emulation.so
W/System.err:2020-02-21 20:04:39.683:INFO::通过org.mortbay.log.StdErrLog登录到STDERR
2020-02-21 20:04:39.684:信息::jetty-0.0
W/System.err:2020-02-21 20:04:39.805:INFO::StartedSocketConnector@localhost:8888
I/System.out:请在浏览器中打开以下地址:
https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=475059597551-bugt3i0nnfe7unsoqt8ghu2ovm7dfrqg.apps.googleusercontent.com&重定向uri=http://localhost:8888/Callback&response_
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 ab: AuthorizationCodeInstalledApp =
object : AuthorizationCodeInstalledApp(authorisationFlow, LocalServerReceiver()) {
@Throws(IOException::class)
override fun onAuthorization(authorizationUrl: AuthorizationCodeRequestUrl) {
val url = authorizationUrl.build()
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
context.startActivity(browserIntent)
}
}
return ab.authorize("user").setAccessToken("user")