安卓接口传参null导致Unity停止响应(ANR)

偶然遇到的 Bug,和 Android 同学对完接口后,在进行某个操作时,总会触发安卓系统 ANR 弹窗:“xxx无响应”,而后经常出现 Unity Crash。
ANR 是啥
ANR 是一种 Android 系统中的错误类型,当应用程序的界面线程处于阻塞状态的时间过长,将会触发此错误,并出现 ANR 对话框:“xxx无响应,要将其关闭吗”。
以下两种情况会触发 ANR:
- 当您的 Activity 位于前台时,您的应用在 5 秒钟内未响应输入事件或 BroadcastReceiver(如按键或屏幕轻触事件)。
- 虽然前台没有 Activity,但您的 BroadcastReceiver 用了相当长的时间仍未执行完毕。
遇到此情况我也很意外,因为 Unity 端并没有写耗 CPU 时间的操作。
发现问题
出现问题后,首先抓日志,日志大概如下:
ANR Log:
E CrashReport: ANR in com.xxxx(com.xxxx/com.xxxx.launcher)
11-25 14:58:57.939 22468 22530 E CrashReport: PID: 22468
11-25 14:58:57.939 22468 22530 E CrashReport: Reason: Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)
Unity Crash(SIGSEGV):
11-25 14:58:44.444 22468 22468 E CRASH : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00002458
11-25 14:58:44.444 22468 22468 E CRASH : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-25 14:58:44.444 22468 22468 E CRASH : Build type 'Release', Scripting Backend 'mono', CPU 'armeabi-v7a'
11-25 14:58:44.444 22468 22468 E CRASH : Build fingerprint: 'xxxxxxxxxxxxxxxx'
11-25 14:58:44.445 22468 22468 E CRASH : Revision: '0'
11-25 14:58:44.445 22468 22468 E CRASH : pid: 22468, tid: 22468, name: r.com.xxxx >>> com.xxxx <<<
11-25 14:58:44.445 22468 22468 E CRASH : r0 00000000 r1 00002458 r2 00000000 r3 80000000
11-25 14:58:44.445 22468 22468 E CRASH : r4 00000000 r5 fff18810 r6 fff18810 r7 fff18d10
11-25 14:58:44.445 22468 22468 E CRASH : r8 cddd0690 r9 cddd069c sl fff18930 fp cddd0698
11-25 14:58:44.445 22468 22468 E CRASH : ip ca6636a8 sp fff18808 lr c9dcd8f8 pc c9820e94 cpsr 000057c4
11-25 14:58:44.445 22468 22468 E CRASH :
11-25 14:58:44.445 22468 22468 E CRASH : backtrace:
11-25 14:58:44.452 22468 22468 E CRASH : #00 pc 0029ae94 /data/app/com/xxxx/lib/arm/libunity.so
经过测试,发现问题是因为 Android 接口回调时传参为 null 所致,以下是问题示例:
Java 端代码:
//声明一个接口给 Unity 继承实现使用
package com.azimiao.test;
public interface SomeListenerCallback{
void onSomethingHappen(String msg);
}
Unity C# 端代码:
//Unity 内继承并实现安卓接口
public class SomeListenerCallback : AndroidJavaProxy
{
public SomeListenerCallback():base("com.azimiao.test.SomeListenerCallback")
{
}
public void onSomethingHappen(string msg)
{
Debug.Log("DoSomething:" + (msg ?? ""));
//other
}
}
运行时,new 一个 SomeListenerCallback 对象,并通过协商的接口送到 Android 层保存引用使用,略过不表。
当时我们在一个 BroadcastReceiver 回调中调用接口:
someListenerCallbackInstance.onSomethingHappen(msg);
在某些情况下,msg 在安卓层为null
,此时程序会出现 ANR 现象,同时查看日志会出现 Unity Crash。
问题原因
在 Unity Crash 日志中可见SIGSEGV
,在诊断原生代码崩溃问题一文中已经说明,该信号多为纯 Null 指针解引用
或低地址 Null 指针解引用
时发生。
我们用 String 去接 null,在纯 C# 环境下是可行的,但当实现安卓接口时,引擎最初接的参数都为 AndroidJavaObject,而在将 AndroidJavaObject 转为 C# 中的 String 时,程序 Null 指针调用出错导致出现崩溃问题。
解决方法
经协商,接口调用时检查参数,遇到null
则修改为""
(空字符串),即解决此问题。
您好~我是腾讯云+社区的运营,关注了您在分享的技术文章,觉得内容很棒,我们诚挚邀请您加入腾讯云自媒体分享计划。完整福利和申请地址请见:[已屏蔽链接]
作者申请此计划后将作者的文章进行搬迁同步到社区的专栏下,你只需要简单填写一下表单申请即可,我们会给作者提供包括流量、云服务器、域名等,另外还有些周边礼物。 我们诚挚的邀请您并期待您的加入~