Android Studio稳定版Debug正常,Release/签名APK触发NPE崩溃求助
兄弟,我之前也碰到过几乎一模一样的坑!Debug模式下跑起来顺得不行,一切到Release或者打签名APK就各种崩溃,堆栈还指向InputConnection.finishComposingText()的空指针——十有八九是**代码混淆(R8/ProGuard)**搞的鬼,毕竟Debug模式下默认关闭混淆,而Release模式会开启代码收缩和优化,很容易把系统输入相关的接口方法给“优化没了”。
下面是我亲测有效的解决步骤:
1. 先确认是不是混淆的锅
先临时关闭Release变体的混淆,快速验证问题根源:
打开模块级别的build.gradle文件,找到Release对应的buildType,把minifyEnabled设为false:
buildTypes { release { minifyEnabled false // 临时改成false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }
然后重新打Release包或者生成签名APK测试,如果崩溃消失了,那百分百是混淆的问题,接下来针对性加规则就行。
2. 添加InputConnection相关的混淆Keep规则
R8可能会把InputConnection接口的方法或者实现类给优化掉,导致运行时调用finishComposingText()时拿到的是null对象。打开你的proguard-rules.pro文件,添加以下规则:
精确匹配(推荐)
只保留你用到的InputConnection方法,避免过度Keep影响包大小:
-keep interface android.view.inputmethod.InputConnection { boolean finishComposingText(); // 如果你还用到了其他方法,比如commitText、setComposingText,也一起加上 boolean commitText(android.text.CharSequence, int); boolean setComposingText(android.text.CharSequence, int); } -keep class * implements android.view.inputmethod.InputConnection
宽泛匹配(快速解决)
如果不确定用到了哪些方法,也可以直接保留整个输入方法相关的类和接口:
-keep class android.view.inputmethod.** { *; }
3. 检查自定义View/EditText的混淆规则
如果你项目里有自定义的EditText或者View,并且重写了getInputConnection()方法,也要确保这个方法不被混淆优化掉,否则可能返回null:
// 把com.your.package.YourCustomView换成你自己的类名 -keepclassmembers class com.your.package.YourCustomView { android.view.inputmethod.InputConnection getInputConnection(android.view.inputmethod.EditorInfo); }
4. 其他可能的排查点
如果加了上面的规则还是崩溃,那可以检查:
- 是不是在Release模式下,某些输入相关的回调(比如
TextWatcher、OnEditorActionListener)被混淆移除了?可以给这些回调也加Keep规则:
-keep class * implements android.text.TextWatcher { public void beforeTextChanged(android.text.CharSequence, int, int, int); public void onTextChanged(android.text.CharSequence, int, int, int); public void afterTextChanged(android.text.Editable); }
- 是不是你的代码里在调用
finishComposingText()之前没有判空?虽然Debug下没问题,但Release下因为优化可能提前出现null,建议在调用前加个非空判断:
if (inputConnection != null) { inputConnection.finishComposingText(); }
按上面的步骤操作后,重新打Release包测试,应该就能解决这个崩溃问题了!
内容的提问来源于stack exchange,提问作者seyed Jafari

