Android生产环境APP调用忘记密码API出现NullPointerException求助
问题原因分析
- 核心原因:生产环境开启了ProGuard/R8代码混淆,而你用于接口序列化的
RetroResponse、内部Data等实体类没有配置混淆白名单,导致JSON解析时无法对应字段名,最终返回的response.body()、body.getData()或user_id中某一环为null,你的代码直接用链式调用没有判空,触发NullPointerException。debug包默认关闭混淆,所以不会出现该问题。 - 次要原因:代码中没有做逐层空校验,直接执行
response.body().getData().getUser_id()链式调用,只要任意一步返回null就会触发空指针。即使没有混淆问题,若接口返回异常数据也会触发崩溃。 - 辅助验证:混淆后的生产包堆栈是被重命名的类名(
c.e.a.e.a.b.m1.a),没有对应代码行,也符合混淆导致的特征。
解决方案
1. 配置混淆规则
在项目的proguard-rules.pro文件中添加如下规则,避免序列化相关的类被混淆:
# 保留API实体类不被混淆,替换为你自己项目中RetroResponse所在的包路径 -keep class com.yourpackagename.bean.** { *; } # Gson 通用混淆规则 -keepattributes Signature -keepattributes *Annotation* -keep class com.google.gson.stream.** { *; } -keep class * implements com.google.gson.TypeAdapterFactory -keep class * implements com.google.gson.JsonSerializer -keep class * implements com.google.gson.JsonDeserializer # Retrofit 通用混淆规则 -keep class retrofit2.** { *; } -keepattributes Exceptions
2. 补充代码空校验
修改接口回调中的代码,逐层做非空判断,避免链式调用空指针:
@Override public void onResponse(@NotNull Call<RetroResponse> call, Response<RetroResponse> response) { CommonMethods.dismissLoading(); Log.e("USER FORGOT PASSWORD","INSIDE onResponse BLOCK "); try { if (response.code() == 200) { // 逐层判空 if (response.body() == null) { Util.ShowToastMessage(context, "返回数据为空"); return; } if (response.body().getData() == null) { Util.ShowToastMessage(context, "用户信息为空"); return; } String user_id = response.body().getData().getUser_id(); if (TextUtils.isEmpty(user_id)) { Util.ShowToastMessage(context, "用户ID获取失败"); return; } startActivity(new Intent(UserForgotPasswordActivity.this, ForgotOtpVerifyActivity.class) .putExtra(Constants.USER_ID, user_id)); } else if (response.code() == 400) { Log.e("USER FORGOT PASSWORD","INSIDE 400 BLOCK "); Util.ShowToastMessage(context, R.string.user_not_registered); } else { // 这里也要判空 if (response.body() != null && response.body().getStatus() == 401) { Util.ShowToastMessage(context, "Something went wrong"); } } } catch (Exception e) { e.printStackTrace(); // 异常捕获后可以加兜底提示 Util.ShowToastMessage(context, "操作失败,请稍后重试"); } }
3. 生产问题定位优化
后续打包时开启mapping文件保存,每次发版都留存对应版本的mapping.txt文件,当线上出现混淆后的异常堆栈时,可以用Android SDK自带的retrace工具还原出真实的代码行,快速定位问题。
内容的提问来源于stack exchange,提问作者Umang Upadhyay
相关产品推荐
相关产品推荐

