Java.lang.RuntimeException: 无法从包裹中读取输入通道文件描述符

63

我正在使用Crashlytics来跟踪我的应用程序崩溃。有一个Bug很难找出原因。从Crashlytics的堆栈跟踪如下:

java.lang.RuntimeException: Could not read input channel file descriptors from parcel.
       at android.view.InputChannel.nativeReadFromParcel(InputChannel.java)
       at android.view.InputChannel.readFromParcel(InputChannel.java:148)
       at android.view.InputChannel$1.createFromParcel(InputChannel.java:39)
       at android.view.InputChannel$1.createFromParcel(InputChannel.java:36)
       at com.android.internal.view.InputBindResult.<init>(InputBindResult.java:62)
       at com.android.internal.view.InputBindResult$1.createFromParcel(InputBindResult.java:102)
       at com.android.internal.view.InputBindResult$1.createFromParcel(InputBindResult.java:99)
       at com.android.internal.view.IInputMethodManager$Stub$Proxy.windowGainedFocus(IInputMethodManager.java:851)
       at android.view.inputmethod.InputMethodManager.startInputInner(InputMethodManager.java:1292)
       at android.view.inputmethod.InputMethodManager.onWindowFocus(InputMethodManager.java:1518)
       at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3550)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:157)
       at android.app.ActivityThread.main(ActivityThread.java:5293)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:515)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
       at dalvik.system.NativeStart.main(NativeStart.java)

我知道有一个类似的问题在这里。但是有一点不同。根据crashlytics的统计数据,崩溃主要发生在三星安卓手机上。

我对安卓不太熟悉,不知道为什么会出现这种崩溃,也不知道如何修复。

非常感谢任何建议。


请发布一些代码。 - GrIsHu
@GrIsHu 我会进行一些搜索并更新一些代码。 - chancyWu
4
这很可能是Android系统的一个漏洞,目前还没有解决方案。已经进行了报告。 - A.J.
我已回答了一个类似的问题。希望它可以帮到你。 - Ircover
对我来说,这是我的设备的问题,但我不知道具体是什么。重启后,现在一切都正常了,好像有魔力一样。 - Naveen Niraula
显示剩余7条评论
5个回答

42

我认为这是一个很广泛的领域,可能会有很多情况会触发这个系统级异常。但也许通过这个特定项目中如何修复此异常的例子可以帮助某些人。

我在三星手机上遇到了类似的异常:
"Could not read input channel file descriptors from parcel"

java.lang.RuntimeException: Could not read input channel file descriptors from parcel.
        at android.view.InputChannel.nativeReadFromParcel(Native Method)
        at android.view.InputChannel.readFromParcel(InputChannel.java:148)
        at android.view.IWindowSession$Stub$Proxy.addToDisplay(IWindowSession.java:690)
        at android.view.ViewRootImpl.setView(ViewRootImpl.java:525)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:269)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
        at android.widget.Toast$TN.handleShow(Toast.java:402)
        at android.widget.Toast$TN$1.run(Toast.java:310)
        at android.os.Handler.handleCallback(Handler.java:730)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:5103)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:525)
        at       com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)

这件事发生在我接手维护的一个大型旧项目中,这个浮动错误仅在几个小时后才发生。我花了相当长的时间研究它,并阅读了一些相关的SO答案,但除了它是Android系统级别的错误之外,没有任何线索,可能是内存中存在一些额外数据或对象的重复或大对象等。

https://code.google.com/p/android/issues/detail?id=32470

我能想到的最后一件事是SoundPool。它在项目中并不常用——每次只有不超过10种不同的声音播放。
但它是根本原因!有时会从SoundPool中出现浮动异常"unable to load sample (null)"。 这使我意识到SoundPool的使用方式有误:

public void play(int rscId) {
...
    final int soundId = soundPool.load(mContext, rscId, 1);
    ...
    soundPool.play(soundId, volume, volume, 5, 0, 1f);

每次应用程序调用播放声音方法时,都会生成新的ID并重新加载声音资源!在一定时间后,一些不相关的异常开始发生,直到应用程序崩溃,并出现"无法从包中读取输入通道文件描述符"异常。
有趣的是,其中一个不相关的异常是:
"ExceptionHandled in unable to open database file (code 14)":

ExceptionHandled in unable to open database file (code 14)
android.database.sqlite.SQLiteCantOpenDatabaseException: 
unable to open database file (code 14)
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow
(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow
(SQLiteConnection.java:845)

当然这与数据库和烤面包/邮包无关。针对这种情况的解决方法非常简单:按照Android文档建议预加载所有声音:http://developer.android.com/reference/android/media/SoundPool.html

"加载逻辑通过调用相应的SoundPool.load()函数遍历声音列表。这通常应在进程早期完成,以便在播放之前有足够的时间将其解压缩为原始PCM格式。
一旦声音被加载并开始播放,应用程序可以通过调用SoundPool.play()来触发声音。"

因此,我将soundPool.load()play()方法中移出,异常:
"Could not read input channel file descriptors from parcel",以及异常"unable to open database file (code 14)"也消失了。

public void play(int soundId) {
    ...
    soundPool.play(soundId, volume, volume, 5, 0, 1f);

当不再需要时,也应该调用soundPool.release(); soundPool = null。可能它也会对这些异常产生影响,请参见此处的详细信息。

Could not read input channel file descriptors from parcel

很可能这并不是原始问题的确切情况,但希望它可以提供一些信息以进一步挖掘。例如寻找其他异常、被忽略的异常或错误的文件/数据处理方式。


您找到了此问题的确切原因吗? - IgorGanapolsky
很遗憾,我所描述的只是这个运行时异常的触发器。然而,通过消除答案中提到的问题,可以解决这个运行时异常。 - Andrew Terekhine

10

我已经寻找很长时间的答案,就像其他人面对这个异常一样。

据我看来,这个崩溃也可能是由与 InputMethodManager 一起使用的非异常 TextViewEditText 触发的:

java.lang.RuntimeException: Could not read input channel file descriptors from parcel.
    at android.view.InputChannel.nativeReadFromParcel(Native Method)
    at android.view.InputChannel.readFromParcel(InputChannel.java:148)
    at android.view.InputChannel$1.createFromParcel(InputChannel.java:39)
    at android.view.InputChannel$1.createFromParcel(InputChannel.java:36)
    at com.android.internal.view.InputBindResult.<init>(InputBindResult.java:68)
    at com.android.internal.view.InputBindResult$1.createFromParcel(InputBindResult.java:112)
    at com.android.internal.view.InputBindResult$1.createFromParcel(InputBindResult.java:109)
    at com.android.internal.view.IInputMethodManager$Stub$Proxy.startInput(IInputMethodManager.java:697)
    at android.view.inputmethod.InputMethodManager.startInputInner(InputMethodManager.java:1407)
    at android.view.inputmethod.InputMethodManager.checkFocus(InputMethodManager.java:1518)
    at android.view.inputmethod.InputMethodManager.restartInput(InputMethodManager.java:1286)
    at android.widget.TextView.setText(TextView.java:4718)
    at android.widget.TextView.setText(TextView.java:4656)
    at android.widget.TextView.append(TextView.java:4330)
    at android.widget.TextView.append(TextView.java:4320)
    ...

当使用TextView添加文本时,它会将文本转换为Editable并启动InputMethodManager。但是在此过程中,由于InputMethod出现问题,导致无法创建InputBindResult并读取错误的数据包。
在这种情况下,解决方法非常简单:不要直接调用TextViewappend方法,而是使用StringBuilderSpannableStringBuilder构建文本,并调用TextView.setText(text)方法来设置文本!

3
我不使用append,而是直接在同一个TextView的onFocusChanged中附加setText内容。尽管这种情况非常罕见,但它会在crashlytics中报告崩溃。 - Omar HossamEldin
@OmarHossamEldin 你有解决方法吗?我很少见到在TextView的构造函数内调用.setText()时出现崩溃。 - A1m

3

之前的用户评论说这个错误很难追踪。我触发了这个错误,是因为我在一个while循环中构建了一个自定义的警告对话框(包含多个TextView对象),而不是使用if语句。应用程序在显示对话框之前就崩溃了。


你知道如何解决这个问题吗? - Lahiru Chandima
@LahiruChandima - 不好意思,我自从发布答案后不久就没有再使用Android Java进行编码了,所以这不是我继续遇到的问题。 - SmrtGrunt

0

ViewRootImpl$ViewRootHandler 表示你使用了 view.post 或者 view.postDelay 方法。 在 post 方法中可能会有 requestFocus 或者 Keyboard


0

我最近遇到了这个问题。

java.lang.RuntimeException: Could not read input channel file descr
iptors from parcel.

我搜索日志,发现以下信息:

01-01 09:07:52.164 5162 6777 W zygote64: ashmem_create_region failed for 'indirect ref table': Too many open files

问题在于我反复创建HandlerThread,但没有执行quit()方法,最终导致fd泄漏。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接