Android 12(API31)前台服务中Retrofit上传空指针问题求助
解决Android 12(LifecycleService+LiveData)文件上传空指针异常
问题背景
应用需在后台以multipart方式,通过Retrofit和LiveData上传文件(上传时APP可正常导航),并根据响应发起链式网络请求。该逻辑在Android 9、10、11中通过前台服务运行正常,但在Android 12(API31)中,观察LiveData响应时触发空指针异常。
相关代码
UploadFragment.kt
class UploadFragment : BaseFragment() { .... private fun uploadFilesToServer() { val intent = Intent(requireActivity(), MyFileUploadingService::class.java) ContextCompat.startForegroundService(requireActivity(), intent) } }
FileUploadService.kt
class FileUploadService : LifecycleService() { .... private fun registerObservers() { viewModel?.uploadLiveData!!.observe(this) { response -> val dataResponse: DataUploadResponse = response.responseBody!!.data!! if (dataResponse.error == null) { .... // Repeat } else { stopSelf() } } } }
错误详情
异常触发代码行:
val dataResponse: DataUploadResponse = response.responseBody!!.data!!
错误日志:
2022-08-24 13:08:59.792 26140-26140/com.myapp.demo E/AndroidRuntime: FATAL EXCEPTION: main Process: com.myapp.demo, PID: 26140 java.lang.NullPointerException at com.myapp.demo.service.FileUploadService$registerObservers$1.onChanged(FileUploadService.kt:242) at com.myapp.demo.service.FileUploadService$registerObservers$1.onChanged(FileUploadService.kt:54) at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133) at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151) at androidx.lifecycle.LiveData.setValue(LiveData.java:309) at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50) at androidx.lifecycle.LiveData$1.run(LiveData.java:93) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7870) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
解决方案
1. 适配Android 12前台服务规则
Android 12要求调用startForegroundService后,必须在5秒内调用startForeground显示前台通知,且通知渠道需设置为IMPORTANCE_DEFAULT及以上优先级。确保服务在onCreate或onStartCommand中完成通知初始化与前台启动:
private val NOTIFICATION_ID = 1001 override fun onCreate() { super.onCreate() // 创建通知渠道(API 26+要求) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel("upload_channel", "文件上传", NotificationManager.IMPORTANCE_DEFAULT) val manager = getSystemService(NotificationManager::class.java) manager.createNotificationChannel(channel) } // 启动前台服务 val notification = NotificationCompat.Builder(this, "upload_channel") .setContentTitle("文件上传中") .setSmallIcon(R.drawable.ic_upload) .build() startForeground(NOTIFICATION_ID, notification) }
2. 移除强制非空断言,添加空安全检查
避免使用!!触发空指针,改用安全调用和空判断处理响应数据:
private fun registerObservers() { viewModel?.uploadLiveData?.observe(this) { response -> val dataResponse = response?.responseBody?.data if (dataResponse != null && dataResponse.error == null) { // 处理成功逻辑,发起链式请求 } else { // 处理空数据或错误情况 stopSelf() } } }
同时排查Android 12下的网络请求问题:比如是否开启了明文流量限制(需在AndroidManifest.xml中配置android:usesCleartextTraffic="true"),或者文件权限是否获取到位(Android 12需申请READ_MEDIA_IMAGES等权限)。
3. 确保ViewModel与LiveData初始化时机正确
在服务onCreate方法中初始化ViewModel,避免viewModel为空:
private lateinit var viewModel: UploadViewModel override fun onCreate() { super.onCreate() viewModel = ViewModelProvider(this).get(UploadViewModel::class.java) registerObservers() // 启动前台服务逻辑... }
4. 可选:改用WorkManager管理后台任务
对于无需即时交互的后台上传任务,WorkManager更适配Android 12及以上的后台限制,可自动处理任务调度与系统适配,同时支持链式任务请求。
内容的提问来源于stack exchange,提问作者Jay Halani
相关产品推荐
相关产品推荐

