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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:57:03