Proguard 启用 NoSuchMethodException

Posted

技术标签:

【中文标题】Proguard 启用 NoSuchMethodException【英文标题】:Proguard enabled NoSuchMethodException 【发布时间】:2020-09-06 14:05:39 【问题描述】:

我没有遇到这个问题,如果我没有像这样启用 Proguard:

buildTypes 
    release 
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    

Logcat:

java.lang.RuntimeException: java.lang.NoSuchMethodException: com.example.NewUsers$f.<init> [class android.view.View]
    at i.c.a.b.f.b(:147)
    at androidx.recyclerview.widget.RecyclerView$g.a(:7078)
    at androidx.recyclerview.widget.RecyclerView$v.a(:6235)
    at androidx.recyclerview.widget.RecyclerView$v.b(:6118)
    at androidx.recyclerview.widget.RecyclerView$v.d(:6114)
    at androidx.recyclerview.widget.LinearLayoutManager$c.a(:2303)
    at androidx.recyclerview.widget.LinearLayoutManager.a(:1627)
    at androidx.recyclerview.widget.LinearLayoutManager.a(:1587)
    at androidx.recyclerview.widget.LinearLayoutManager.c(:665)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(:4134)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayout(:3851)
    at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(:1897)
    at androidx.recyclerview.widget.RecyclerView$a.run(:414)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:996)
    at android.view.Choreographer.doCallbacks(Choreographer.java:794)
    at android.view.Choreographer.doFrame(Choreographer.java:725)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:981)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:237)
    at android.app.ActivityThread.main(ActivityThread.java:7807)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047)
 Caused by: java.lang.NoSuchMethodException: com.example.NewUsers$f.<init> [class android.view.View]
    at java.lang.Class.getConstructor0(Class.java:2332)
    at java.lang.Class.getConstructor(Class.java:1728)
    at i.c.a.b.f.b(:144)
    at androidx.recyclerview.widget.RecyclerView$g.a(:7078) 
    at androidx.recyclerview.widget.RecyclerView$v.a(:6235) 
    at androidx.recyclerview.widget.RecyclerView$v.b(:6118) 
    at androidx.recyclerview.widget.RecyclerView$v.d(:6114) 
    at androidx.recyclerview.widget.LinearLayoutManager$c.a(:2303) 
    at androidx.recyclerview.widget.LinearLayoutManager.a(:1627) 
    at androidx.recyclerview.widget.LinearLayoutManager.a(:1587) 
    at androidx.recyclerview.widget.LinearLayoutManager.c(:665) 
    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(:4134) 
    at androidx.recyclerview.widget.RecyclerView.dispatchLayout(:3851) 
    at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(:1897) 
    at androidx.recyclerview.widget.RecyclerView$a.run(:414) 
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:996) 
    at android.view.Choreographer.doCallbacks(Choreographer.java:794) 
    at android.view.Choreographer.doFrame(Choreographer.java:725) 
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:981) 
    at android.os.Handler.handleCallback(Handler.java:883) 
    at android.os.Handler.dispatchMessage(Handler.java:100) 
    at android.os.Looper.loop(Looper.java:237) 
    at android.app.ActivityThread.main(ActivityThread.java:7807) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047) 

当前的proguard:

-keep class com.example.models.**  *; 

Java 类:

public class NewUsers extends AppCompatActivity 

    ....

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_new_users);

        ....

        mNewUsersList = findViewById(R.id.newUsers);
        mNewUsersList.setHasFixedSize(true);
        mNewUsersList.setLayoutManager(new LinearLayoutManager(this));

        onStart();

    

    @Override
    protected void onStart() 
        super.onStart();
        FirebaseRecyclerAdapter<Users, UsersViewHolder> adapter = new FirebaseRecyclerAdapter<Users, UsersViewHolder>(
                Users.class,
                R.layout.users_list,
                UsersViewHolder.class,
                mDatabaseReference
        ) 

            @Override
            protected void populateViewHolder(UsersViewHolder usersViewHolder, Users users, int position) 
                usersViewHolder.setName(users.getName());

            
        ;
        mNewUsersList.setAdapter(adapter);
    

    public static class UsersViewHolder extends RecyclerView.ViewHolder 
        View mView;

        public UsersViewHolder(@NonNull View itemView) 
            super(itemView);
            mView = itemView;
        

        public void setName(String name) 
            TextView mUserNameView = mView.findViewById(R.id.textViewUserName);
            mUserNameView.setText(name);
        
    

有没有可能,我只想启用缩小和缩小以供发布

型号:

public class Users 

    String name;

    public Users() 
    

    public Users(String name) 
        this.name = name;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    


【问题讨论】:

我认为问题在于您在 RecyclerView 适配器中使用的模型类。你的模型包中是否有任何可序列化的类......?? 请检查,我发布了用户模型类 缺少该方法的类不在您保留的包中。将配置更改为-keep class com.example.** *; 我在任何其他课程中都没有遇到任何问题,所以我为什么要保留我在包中的所有课程,我正在寻找最安全的方式 @Robert 发表你的建议作为你的答案...我会给你赏金 【参考方案1】:

检查此日志:

java.lang.RuntimeException: java.lang.NoSuchMethodException: com.example.NewUsers$f.<init> [class android.view.View]

正确的职业守卫规则是:

-keep class com.example.**  *; 

另外,请注意,这将排除 com.example 下的所有类,我建议将数据类移动到一个公共目录并混淆该完整目录。

【讨论】:

恭喜 saurabh【参考方案2】:

您的课程包是com.example,但proguard 规则是com.example.models。修改它应该可以解决问题。

【讨论】:

【参考方案3】:

解决方案一:

将您保留的课程从 com.example.model 更改为 com.example

更好的解决方案

如果你在你使用它的文件中正确地导入这个类,并且没有使用任何类型的反射,proguard 不应该删除它。

试着把它放在一个你可能不需要使用反射或间接方法来访问这个类的常见位置

【讨论】:

【参考方案4】:

java.lang.RuntimeException: java.lang.NoSuchMethodException: com.example.NewUsers$f。 [类android.view.View] 在 i.c.a.b.f.b(:147)

找不到特定方法时抛出的异常。这里由于proguard。你应该试试

-keep class com.example.**  *; 
-keepclassmembers class com.example.**  *; 

在整个包上添加@Keep 可使整个类保持原样。将其添加到方法或字段上将保持方法/字段(及其名称)以及类名不变。

OP 将是

public class HomeActivity extends AppCompatActivity  

private TextView f2032b; 
private Button f2033c; 

仅供参考

您可以通过在项目的 gradle.properties 文件中包含以下内容来启用这些额外的优化:

android.enableR8.fullMode=true

它可能需要您包含额外的 ProGuard 规则以避免运行时问题。阅读有关Enable more aggressive optimizations的官方指南

【讨论】:

以上是关于Proguard 启用 NoSuchMethodException的主要内容,如果未能解决你的问题,请参考以下文章

使用启用了 proguard 的 GSON

启用 ProGuard 规则时 Gson 解析不起作用

如何在android studio中启用proguard? [复制]

了解启用 Proguard 的崩溃和 ANR

启用 Proguard 时未找到 kotlin.Any

启用 proguard 后调试应用程序构建失败