DylanCaiCoding / ViewBindingKTX

The most comprehensive utils of ViewBinding. (最全面的 ViewBinding 工具,支持 Kotlin 和 Java 用法,支持 BRVAH,支持封装到基类,支持 DataBinding,支持选择是否使用反射)
Apache License 2.0
810 stars 91 forks source link

release 混淆报错 #55

Open wlingf opened 2 years ago

wlingf commented 2 years ago

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.android.sms, PID: 4568 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.sms/com.android.sms.ui.splash.SplashActivity}: java.lang.IllegalArgumentException: There is no generic of ViewBinding. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3752) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3920) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2345) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:264) at android.app.ActivityThread.main(ActivityThread.java:8268) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049) Caused by: java.lang.IllegalArgumentException: There is no generic of ViewBinding. at p1.a.b(ViewBindingUtil.kt:90) at p1.a.a(ViewBindingUtil.kt:35) at cc.jianke.mvvmmodule.viewbinding.BaseViewBindingActivity.onCreate(BaseViewBindingActivity.kt:20) at android.app.Activity.performCreate(Activity.java:8151) at android.app.Activity.performCreate(Activity.java:8135) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3721) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3920)  at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)  at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2345)  at android.os.Handler.dispatchMessage(Handler.java:106)  at android.os.Looper.loop(Looper.java:264)  at android.app.ActivityThread.main(ActivityThread.java:8268)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049) 

DylanCaiCoding commented 2 years ago

这个问题有点奇怪,我自己用着没有问题,本库的示例代码直接混淆也能正常运行。我的库目前有上千个人用,有少数几个人跟我反馈过混淆问题,不清楚是什么原因导致的。

wlingf commented 2 years ago

还是不行

wlingf commented 2 years ago

以下是项目的混淆规则

---------------------------------基本指令区----------------------------------

忽略警告

-ignorewarnings

代码混淆压缩比,在0~7之间

-optimizationpasses 5

混合时不使用大小写混合,混合后的类名为小写

-dontusemixedcaseclassnames

指定不去忽略非公共库的类

-dontskipnonpubliclibraryclasses

指定不忽略包可见的库类成员(字段和方法)。默认地,当解析库类的时候ProGuard会跳过这些类成员,项目类一般不会去引用它们。然而有的时候,程序里的类相当于库类存在于相同包。此时它们会引用他们的包可见的类成员。在这种情况下为了保持程序代码保持一致性去读取这些类的成员是有用的。

-dontskipnonpubliclibraryclassmembers

不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。

-dontpreverify

指定处理期间打印更多相关信息

-verbose

-printmapping proguardMapping.txt

指定要启用和禁用的优化,在更精细的水平。只有当优化适用。 混淆时采用的算法(google推荐,一般不改变)

-optimizations !code/simplification/cast,!field/,!class/merging/

避免混淆Annotation、内部类

-keepattributes Annotation,InnerClasses

避免混淆泛型

-keepattributes Signature

抛出异常时保留代码行号

-keepattributes SourceFile,LineNumberTable

----------------------------------------------------------------------------

---------------------------------默认保留区---------------------------------

-keep public class extends android.app.Activity -keep public class extends android.app.Application -keep public class extends android.app.Service -keep public class extends android.content.BroadcastReceiver -keep public class extends android.content.ContentProvider -keep public class extends android.app.backup.BackupAgentHelper -keep public class extends android.preference.Preference -keep public class extends android.view.View -keep public class com.android.vending.licensing.ILicensingService -keep class android.support.* {;} -keepclasseswithmembernames class * { native ; }

-keepclassmembers class extends android.app.Activity{ public void (android.view.View); }

-keepclassmembers enum * { public static [] values(); public static valueOf(java.lang.String); }

-keep public class * extends android.view.View{ get(); void set(); public (android.content.Context); public (android.content.Context, android.util.AttributeSet); public (android.content.Context, android.util.AttributeSet, int); }

-keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet); public (android.content.Context, android.util.AttributeSet, int); }

-keep class implements android.os.Parcelable { public static final android.os.Parcelable$Creator ; }

-keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); }

-keep class *.R$ { *; }

-keepclassmembers class { void (*OnEvent); }

----------------------------------------------------------------------------

---------------------------------webview------------------------------------

-keepclassmembers class fqcn.of.javascript.interface.for.Webview { public *; }

-keepclassmembers class extends android.webkit.WebViewClient { public void (android.webkit.WebView, java.lang.String, android.graphics.Bitmap); public boolean *(android.webkit.WebView, java.lang.String); }

-keepclassmembers class extends android.webkit.WebViewClient { public void (android.webkit.WebView, java.lang.String); }

----------------------------------------------------------------------------

-------------------------------------------定制化区域----------------------------------------------

---------------------------------1.实体类---------------------------------

-keep class com.android.sms.entity.* { ; }

-------------------------------------------------------------------------

---------------------------------2.第三方包-------------------------------

XPopup

-dontwarn com.lxj.xpopup.widget. -keep class com.lxj.xpopup.widget.{*;}

-------------------------------------------------------------------------

---------------------------------3.与js互相调用的类------------------------

-------------------------------------------------------------------------

---------------------------------4.反射相关的类和方法-----------------------

-keep public class extends cc.jianke.mvvmmodule.mvvm.BaseViewModel { ; }

-keep public class cc.jianke.mvvmmodule.utils.Utils { *; }

-keepclassmembers class implements androidx.viewbinding.ViewBinding { public static bind(); public static ** inflate(...); }

----------------------------------------------------------------------------

xjhh commented 2 years ago

有一种情况,使用腾讯的资源混淆会出现该问题,将布局添加到白名单就可以了

bill556 commented 2 years ago

我也出现了这个问题,是今天升级了AGP 7.1.2 用上JAVA11才出现的

bill556 commented 2 years ago

现在作者的DEMO 是gradle:4.2.1 + 6.7.1 我之前是这个版本也是没问题的 到了7.0+才出现混淆问题

bill556 commented 2 years ago

排除到了问题 我也是项目用了hilt 升级到2.41问题解决

kuroyukihime0 commented 2 years ago

建一个APG7.2.0 + Gradle-7.4.2的新项目时也碰到了这个问题, 单参数inflate没问题,3参数的就找不到,但是反编译是可以看到method的 不管是自己写的工具类还是这个库都有问题, 混淆规则也添加了

暂时还没有解决,3参数的inflate换成非反射的方案先用着了

asker517 commented 2 years ago

遇到同样的问题。。加混淆也没用

asker517 commented 2 years ago

@kuroyukihime0 @DylanCaiCoding @bill556

遇到同样的问题。。加混淆也没用

很奇怪,用反射的方式,我是在使用封装在基类BindingViewDelegate结合MultiType用的时候开启混淆后出现There is no generic of ViewBinding.的,然后如果gradleisDebuggable = true就没问题,反之就会如此,关键问题是不是所有继承BindingViewDelegate的子类item都会出现问题,排查到出问题的item之后。。我新建了一个类,代码复制过来,竟然又能正常……Orzzz 大佬们能看出到底是啥问题么

agp: 7.2.1 kotlin:1.6.21

DylanCaiCoding commented 2 years ago

个人测试了把项目代码升级成 Gradle 7.1.2 没有出现混淆问题,代码已上传到了 gradle7 分支,大家可以切换分支运行 release 验证一下。

Gradle 7.2 好像要升级成花栗鼠版本才能使用,由于看到很多人使用花栗鼠版本遇到问题,个人一直没升级。是否在 Gradle 7.2 有混淆问题,个人还没验证,可以尝试降成 7.1.2 (gradle-7.2-bin.zip) 看下问题能否解决。如果还是不行,可能需要找下其它原因,比如目前为止有过 3 个人和我反馈把 hilt 升级到 2.41 解决了。

q947721485 commented 2 years ago

同样3个参数混淆问题,gradle版本7.3.3

zdxiang commented 2 years ago

遇到同样的问题。gradle-7.3.3。没有使用hilt

leon2017 commented 2 years ago

遇到同样的问题。gradle-7.2.1。没有使用hilt

leon2017 commented 2 years ago

遇到同样的问题。gradle-7.2.1。没有使用hilt 加了这个 解决了问题


-keepclassmembers class * implements androidx.viewbinding.ViewBinding {
public static ** bind(***);
public static ** inflate(...);
}```
Piscen commented 2 years ago

遇到同样的问题。gradle-7.2.1。没有使用hilt 加了这个 解决了问题

-keepclassmembers class * implements androidx.viewbinding.ViewBinding {
     public static ** bind(***);
     public static ** inflate(...);
}```

遇到同样问题,gradle-7.0.2,加了这个已解决

Fonnson commented 1 year ago

非常简单的反射封装,如果MainActivity调用了binding.root或者binding.(任意view)不会崩溃,否则就会报NoSuchMethodException

Caused by: java.lang.NoSuchMethodException: java.lang.Object.inflate [class android.view.LayoutInflater]

这是什么原因?

abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
    lateinit var binding: VB
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val type = javaClass.genericSuperclass as ParameterizedType
        val aClass = type.actualTypeArguments[0] as Class<*>
        val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
        binding = method.invoke(null, layoutInflater) as VB
        setContentView(binding.root)
    }
}
class MainActivity : BaseActivity<ActivityMainBinding>() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.root
    }
}
ldlywt commented 1 year ago

解决办法

-keep class * implements androidx.viewbinding.ViewBinding {
    *;
}
tanranran commented 1 year ago

AGP 8以上,因为android.enableR8.fullMode会强制开启,还需要加上以下三行

-keep class implements androidx.viewbinding.ViewBinding {;}

-keepclassmembers class implements androidx.viewbinding.ViewBinding { public static bind(); public static ** inflate(...); }

-keep,allowobfuscation,allowshrinking class 你的包名. BaseBindingActivity

stars-one commented 1 week ago

测试发现:

如果Activity继承BaseBindingActivity,且此Activity上有个hilt注解@AndroidEntryPoint,楼上的混淆规则无效(目前我只能把Hilt注解给干掉解决问题

我用的hilt版本是2.48.1