启用ProGuard后JSON解析异常:物理设备数据显示为0
问题描述
启用ProGuard后出现JSON解析异常:原本tx1控件应显示数字9,但物理Android设备上显示0,而AVD(安卓虚拟设备)开启ProGuard仍能正常显示9。
相关代码
MainActivity.java
package com.alamart; import android.content.Context; import android.os.Bundle; import android.widget.TextView; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; public class MainActivity extends AppCompatActivity { private TextView tx1; private TextView tx2; private String json; private ArrayList<HashMap<String, Object>> map = new ArrayList<>(); public ArrayList<HashMap<String, Object>> jumlahBarang = new ArrayList<>(); private GetSize getSize; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); try { InputStream is = MainActivity.this.getAssets().open("1.json"); int size = is.available(); byte[] buffer = new byte[size]; is.read(buffer); is.close(); json = new String(buffer, "UTF-8"); map = new Gson().fromJson(json, new TypeToken<ArrayList<HashMap<String, Object>>>() { }.getType()); for (HashMap<String, Object> item : map) { HashMap<String, Object> newItem = new HashMap<>(); newItem.put("coklat", item.get("coklat")); jumlahBarang.add(newItem); } } catch (Exception e) { e.printStackTrace(); } tx1 = findViewById(R.id.tx1); tx1.setText(String.valueOf(jumlahBarang.size())); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); } }
build.gradle中的buildTypes配置
buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }
原因分析
- ProGuard激进优化破坏Gson解析:你使用的
proguard-android-optimize.txt包含更严格的代码优化规则,物理设备上ProGuard可能对HashMap、TypeToken相关代码进行了过度混淆/优化,导致Gson无法识别泛型类型,JSON解析失败,最终jumlahBarang为空列表,显示0。 - AVD与物理设备的编译差异:AVD的运行环境可能默认跳过了部分ProGuard优化,或者JIT编译逻辑不同,使得优化后的代码仍能正常执行;而物理设备的AOT编译会应用完整优化规则,触发了解析异常。
- 异常被静默处理:代码中用
catch (Exception e)捕获所有异常但仅打印堆栈,没有暴露解析失败的具体问题,增加了排查难度。
解决方法
1. 添加Gson专属ProGuard规则
在proguard-rules.pro文件中添加以下规则,防止Gson相关类和泛型解析逻辑被破坏:
# 保留Gson核心类与特性 -keepattributes Signature -keepattributes *Annotation* -keep class com.google.gson.** { *; } -keep class com.google.gson.stream.** { *; } # 保留TypeToken的匿名子类(泛型解析依赖) -keepclassmembers class * extends com.google.gson.reflect.TypeToken { <init>(...); } # 防止HashMap结构被优化 -keepclassmembers class java.util.HashMap { <fields>; <methods>; }
2. 替换保守的ProGuard配置文件
如果proguard-android-optimize.txt的激进优化引发问题,可以换成默认的保守配置:
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
3. 暴露异常信息以便排查
修改catch块,将异常信息可视化,快速定位问题:
catch (Exception e) { e.printStackTrace(); tx1.setText("解析失败: " + e.getMessage()); }
4. 验证JSON文件完整性
解压物理设备上的APK,检查assets/1.json文件是否完整、内容是否正确,避免文件被压缩或损坏导致解析失败。
内容的提问来源于stack exchange,提问作者Muspedia indonesia
相关产品推荐
相关产品推荐

