You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GoogleCredentials创建Google Drive文件夹时应用崩溃求助

解决Android中Google Drive创建文件夹时的NetworkOnMainThreadException异常

在Android项目中用Kotlin实现了GoogleCredentials授权并在Google Drive创建文件夹的功能,已添加所需依赖和INTERNET权限,但点击按钮调用signIn函数时,执行googleDriveService.files().create(folderMetadata).execute()导致应用崩溃,错误日志显示android.os.NetworkOnMainThreadException。

依赖配置

implementation("com.google.android.gms:play-services-auth:21.2.0")
implementation("com.google.api-client:google-api-client:2.5.0")
implementation("com.google.apis:google-api-services-drive:v3-rev20240521-2.0.0")

implementation("com.google.http-client:google-http-client-android:1.26.0")

相关代码

// Google Sign in
fun signIn(context: Context) {

    val authorizationRequest = AuthorizationRequest.builder().setRequestedScopes(SCOPES).build()

    Identity.getAuthorizationClient(context as Activity).authorize(authorizationRequest)
        .addOnSuccessListener { authorizationResult ->

            if (authorizationResult.hasResolution()) {

                // 需要用户授权
                val pendingIntent = authorizationResult.pendingIntent
                try {
                    startIntentSenderForResult(
                        context, pendingIntent!!.intentSender, 999, null, 0, 0, 0, null
                    )
                } catch (e: IntentSender.SendIntentException) {
                    Log.i("@@@", "Authorization failed: " + e.message)
                }

            } else {

                // 授权成功,执行操作
                Log.i("@@@", "Access granted")

                val token = authorizationResult.accessToken
                val credentials = GoogleCredentials.create(AccessToken(token, null))
                val requestInitializer = HttpCredentialsAdapter(credentials)

                val googleDriveService = Drive.Builder(
                    AndroidHttp.newCompatibleTransport(),
                    GsonFactory(), requestInitializer
                )
                    .setApplicationName(context.getString(R.string.app_name))
                    .build()

                Log.i("@@@", googleDriveService.toString())

                try {
                    // 创建Google Drive文件夹
                    // 文件夹元数据
                    val folderMetadata =
                        File().setMimeType("application/vnd.google-apps.folder")
                            .setParents(listOf(ROOT))
                            .setName(FOLDER_NAME).setStarred(true)
                            .setFolderColorRgb("#FF0000")       // 红色

                    // 创建文件夹(此处崩溃,错误信息:null)
                    googleDriveService.files().create(folderMetadata).execute()

                } catch (e: Exception) {
                    Log.e("@@@", e.message.toString())
                }
            }
        }.addOnFailureListener { e -> Log.e("@@@", "Failed to authorize", e) }
}

完整异常日志

null
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1675)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:115)
at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
at java.net.InetAddress.getAllByName(InetAddress.java:1152)
at com.android.okhttp.Dns$1.lookup(Dns.java:41)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:178)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:144)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:86)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:176)
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.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:262)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:219)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:30)
at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:113)
at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:84)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1012)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:565)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:506)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:616)
at mdc.auMenu.ui.account.GDriveKt.signIn$lambda$0(GDrive.kt:98)
at mdc.auMenu.ui.account.GDriveKt.$r8$lambda$p_pBQS_xClgWTOPLtc5ZI1mWzwo(Unknown Source:0)
at mdc.auMenu.ui.account.GDriveKt$$ExternalSyntheticLambda0.invoke(D8$$SyntheticClass:0)
at mdc.auMenu.ui.account.GDriveKt.signIn$lambda$1(GDrive.kt:54)
at mdc.auMenu.ui.account.GDriveKt.$r8$lambda$z9STuCnUdP6vzHpOxi9Ibd4ex84(Unknown Source:0)
at mdc.auMenu.ui.account.GDriveKt$$ExternalSyntheticLambda1.onSuccess(D8$$SyntheticClass:0)
at com.google.android.gms.tasks.zzm.run(com.google.android.gms:play-services-tasks@@18.1.0:1)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

解决方案

NetworkOnMainThreadException是因为Android禁止在主线程执行耗时网络操作,会导致界面卡顿甚至ANR。解决核心是把创建文件夹的网络请求放到后台线程执行,以下是三种常用方案:

方案1:使用AsyncTask(简单场景适用,Android 11后标记废弃但仍可使用)

替换原代码中创建文件夹的try-catch块:

AsyncTask.execute {
    try {
        val folderMetadata = File().setMimeType("application/vnd.google-apps.folder")
            .setParents(listOf(ROOT))
            .setName(FOLDER_NAME).setStarred(true)
            .setFolderColorRgb("#FF0000")

        googleDriveService.files().create(folderMetadata).execute()
        // 操作成功后回到主线程更新UI
        (context as Activity).runOnUiThread {
            Toast.makeText(context, "文件夹创建成功", Toast.LENGTH_SHORT).show()
        }
    } catch (e: Exception) {
        Log.e("@@@", e.message ?: "未知错误")
        (context as Activity).runOnUiThread {
            Toast.makeText(context, "创建失败:${e.message}", Toast.LENGTH_SHORT).show()
        }
    }
}

方案2:使用Kotlin协程(推荐方案,更简洁)

先确保添加协程依赖(未添加则加入):

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")

再替换创建文件夹的代码:

CoroutineScope(Dispatchers.IO).launch {
    try {
        val folderMetadata = File().setMimeType("application/vnd.google-apps.folder")
            .setParents(listOf(ROOT))
            .setName(FOLDER_NAME).setStarred(true)
            .setFolderColorRgb("#FF0000")

        googleDriveService.files().create(folderMetadata).execute()
        // 切换到主线程更新UI
        withContext(Dispatchers.Main) {
            Toast.makeText(context, "文件夹创建成功", Toast.LENGTH_SHORT).show()
        }
    } catch (e: Exception) {
        Log.e("@@@", e.message ?: "未知错误")
        withContext(Dispatchers.Main) {
            Toast.makeText(context, "创建失败:${e.message}", Toast.LENGTH_SHORT).show()
        }
    }
}

方案3:手动创建Thread

直接创建后台线程执行网络请求:

Thread {
    try {
        val folderMetadata = File().setMimeType("application/vnd.google-apps.folder")
            .setParents(listOf(ROOT))
            .setName(FOLDER_NAME).setStarred(true)
            .setFolderColorRgb("#FF0000")

        googleDriveService.files().create(folderMetadata).execute()
        // 回到主线程处理结果
        (context as Activity).runOnUiThread {
            Toast.makeText(context, "文件夹创建成功", Toast.LENGTH_SHORT).show()
        }
    } catch (e: Exception) {
        Log.e("@@@", e.message ?: "未知错误")
        (context as Activity).runOnUiThread {
            Toast.makeText(context, "创建失败:${e.message}", Toast.LENGTH_SHORT).show()
        }
    }
}.start()

内容的提问来源于stack exchange,提问作者user26453386

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:57:00