Gson在生产模式APK Android中未Map数据

bq3bfh9z  于 2022-11-06  发布在  Android
关注(0)|答案(6)|浏览(193)

我正在使用Gson将数据Map到ArrayList中。它在设备上运行应用程序或在调试模式下工作正常,但它不在生产模式APK中Map数据。以下是代码

Const.courses = new ArrayList<>();
    Log.v("Courses",object.toString());
    Type type = new TypeToken<ArrayList<Course>>() {
    }.getType();

    if(object != null && object.has("data") ){

        try {
            if(object.get("data") != null && object.getJSONArray("data").length()>0) {
                Const.courses.clear();
                Const.courses = new GsonBuilder().create().fromJson(object.getJSONArray("data").toString(), type);

                Log.d("Course from Array",Const.courses.get(0).getTitle());

  adapter = new CourseAdapter(getApplicationContext(), R.layout.course_row_layout, Const.courses);
                listView.setDivider(new ColorDrawable(ContextCompat.getColor(getApplicationContext(), android.R.color.transparent)));
                listView.setAdapter(adapter);
            }else{
                tvSelectCourse.setVisibility(View.GONE);
                tvNoCourse.setVisibility(View.VISIBLE);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

这里是Logcat.任何帮助将不胜感激.

02-16 23:30:57.836 1234-1234/? V/Courses: {"contentEncoding":null,"contentType":null,"data":[{"id":1,"title":"course Updated"},{"id":12,"title":"Arabic"},{"id":13,"title":"usman"},{"id":14,"title":"really "},{"id":15,"title":"urdu"},{"id":17,"title":"abc"},{"id":21,"title":"course"},{"id":22,"title":"Ali don"},{"id":24,"title":"umair"},{"id":25,"title":"math"},{"id":27,"title":"world"},{"id":28,"title":"wether"},{"id":33,"title":"computer Science "},{"id":34,"title":"cs"},{"id":37,"title":"maths"},{"id":38,"title":"hello"},{"id":39,"title":"course Updated"},{"id":42,"title":"for testing purpose"}],"jsonRequestBehavior":0,"maxJsonLength":null,"recursionLimit":null}
02-16 23:30:57.852 1234-1234/? D/AndroidRuntime: Shutting down VM
02-16 23:30:57.859 1234-1234/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                 Process: com.umer.doratiteacher, PID: 1234
                                                 java.lang.NullPointerException: println needs a message
                                                     at android.util.Log.println_native(Native Method)
                                                     at android.util.Log.d(Log.java:139)
                                                     at com.umer.doratiteacher.MainActivity$3.a(Unknown Source)
                                                     at com.umer.doratiteacher.d.a$3.a(Unknown Source)
                                                     at com.umer.doratiteacher.d.a$3.a(Unknown Source)
                                                     at com.a.a.a.i.a(Unknown Source)
                                                     at com.a.a.e$a.run(Unknown Source)
                                                     at android.os.Handler.handleCallback(Handler.java:739)
                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                     at android.os.Looper.loop(Looper.java:234)
                                                     at android.app.ActivityThread.main(ActivityThread.java:5526)
                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
wgeznvg7

wgeznvg71#

如前所述,问题来自于Proguard(当minifyEnabledtrue时)。
基于这个链接https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg,我只需添加3行代码就可以使代码正常工作


# Gson uses generic type information stored in a class file when working with fields. Proguard

# removes such information by default, so configure it to keep all of it.

-keepattributes Signature

# Gson specific classes

-keep class sun.misc.Unsafe { *; }

# -keep class com.google.gson.stream.**{ *; }

# Application classes that will be serialized/deserialized over Gson

-keep class com.example.YourPackage.**{ *; }

最后一行是代码所在包的名称。如果您将所有代码放在一个主包中(所有java文件都在一个目录中),或者在一个文件中只有GSON解析,那么用最后一行替换它(我测试了上面的代码,但没有测试下面的代码)。

-keep class com.example.YourPackage.YourClass.**{ *; }
aemubtdh

aemubtdh2#

加里正确地指出了问题出在Proguard上。他给出的解决方案确实有效。另一种方法是添加

@Keep

androidx.annotation.Keep到您的类的注解。

polkgigr

polkgigr3#

下面是build.gradle中的代码

buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
            lintOptions {
                disable 'MissingTranslation'
            }
        }
...

您必须在proguard_rules.pro中定义哪些类不应更改其名称
这是我的:

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose

-dontwarn org.joda.time.**
-keep class org.joda.time.**{

* ;

}

-keep class com.xxx.xxx.**{
public *;
}

-keep class android.support.**{*;}
-keep class org.jsoup.**{*;}
-keep class com.google.**{*;}

使用-keep来保留类名或方法名,下面是文件中的详细信息链接


# For more details, see

# http://developer.android.com/guide/developing/tools/proguard.html
j1dl9f46

j1dl9f464#

您应该为类属性添加注解,这样Gson就知道要查找什么:

public class RData {

    @SerializedName("code")
    public String code;
    @SerializedName("info")
    public String info; 
}
klr1opcd

klr1opcd5#

乍一看堆栈跟踪,似乎您正在将null传递给Log调用:
Log.d("Course from Array",Const.courses.get(0).getTitle()); .
一个快速的解决方法是在将getTitle()方法传递给log方法之前,检查以确保它不是null

erhoui1w

erhoui1w6#

经过一整天的挣扎,我结束了在这里,上面的响应标记为有效的指向我在正确的方向。我已经有了所有的proguard规则提到,所有的工作都很好,直到...我已经更新了gradle和Android Studio!
现在Android Studio默认使用带有proguard规则的R8。所以我在R8中寻找答案,瞧!这里是link
我在上述规则的基础上补充了以下内容:

-keepclassmembers,allowobfuscation class * {
 @com.google.gson.annotations.SerializedName <fields>;
}

最后对我起作用了。希望这对其他人有帮助

相关问题