安卓接口传参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则修改为""(空字符串),即解决此问题。

梓喵出没博客(azimiao.com)版权所有,转载请注明链接:https://www.azimiao.com/8383.html
欢迎加入梓喵出没博客交流群:313732000

发表评论

*

*

评论区

  1. rantrism12-10 11:29 回复

    您好~我是腾讯云+社区的运营,关注了您在分享的技术文章,觉得内容很棒,我们诚挚邀请您加入腾讯云自媒体分享计划。完整福利和申请地址请见:[已屏蔽链接]
    作者申请此计划后将作者的文章进行搬迁同步到社区的专栏下,你只需要简单填写一下表单申请即可,我们会给作者提供包括流量、云服务器、域名等,另外还有些周边礼物。 我们诚挚的邀请您并期待您的加入~