Android真机上传图片报SocketTimeoutException问题求助
解决Android 33真机SocketTimeoutException问题的步骤
1. 移除非主线程执行网络请求
Android 9(API 28)及以上严格禁止在主线程执行同步网络请求,模拟器可能未严格校验,但Android 33真机的系统限制会直接导致请求超时或异常。你的代码使用了execute()同步请求,必须将其移到子线程执行,比如用协程实现:
// 在Activity/ViewModel中启动IO线程执行请求 lifecycleScope.launch(Dispatchers.IO) { val client = OkHttpClient.Builder() .callTimeout(60, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS) .build() val body = MultipartBody.Builder().setType(MultipartBody.FORM) .addFormDataPart("image","", File(filePath).asRequestBody("application/octet-stream".toMediaType())) .build() val request = Request.Builder() .url("你的服务器地址") .post(body) .build() try { val response = client.newCall(request).execute() // 需切回主线程更新UI withContext(Dispatchers.Main) { if (response.isSuccessful) { response.body?.let { println("Response: ${it.string()}") } } else { println("Request failed: ${response.code}") } } } catch (e: Exception) { e.printStackTrace() } }
2. 调整OkHttp超时参数
4MB图片上传需要足够的超时窗口,免费服务器(如000webhost)带宽有限,当前30秒总超时可能不足。建议延长超时并新增写入超时(上传文件的关键配置):
val client = OkHttpClient.Builder() .callTimeout(60, TimeUnit.SECONDS) // 总请求超时延长至60秒 .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS) // 新增写入超时,适配大文件上传 .build()
3. 检查服务器上传限制
000webhost免费版默认上传文件大小限制为2MB,你的4MB图片已超限,会导致服务器无响应最终触发客户端超时。解决方式:
- 压缩图片:将图片压缩至2MB以内再上传,示例代码:
fun compressImage(filePath: String, context: Context): File { val bitmap = BitmapFactory.decodeFile(filePath) val outputStream = ByteArrayOutputStream() // 调整quality值(0-100)控制压缩比例 bitmap.compress(Bitmap.CompressFormat.JPEG, 60, outputStream) val compressedFile = File(context.getExternalFilesDir(null), "compressed_img.jpg") FileOutputStream(compressedFile).use { it.write(outputStream.toByteArray()) } return compressedFile }
- 修改服务器配置:登录000webhost后台,调整
php.ini中的upload_max_filesize和post_max_size参数至4MB以上。
4. 验证网络权限与HTTPS配置
- 确保
AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- 添加OkHttp日志拦截器,排查请求详情:
val loggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } val client = OkHttpClient.Builder() // 其他配置... .addInterceptor(loggingInterceptor) .build()
通过日志可查看服务器返回的具体错误(如413 Request Entity Too Large),定位问题根源。
内容的提问来源于stack exchange,提问作者Danny Z Baqtar
相关产品推荐
相关产品推荐

