Android应用程序之外的RuntimeException

huangapple go评论83阅读模式
英文:

Android RuntimeException outside app code

问题

我遇到了一个奇怪的问题,这个问题只出现在特定的设备上(或者至少在我测试过的其他大约10台设备上没有出现)。

有时,当应用程序应该显示一个包含消息的进度对话框,然后是一个Toast时,它会崩溃;在Play控制台上查看,我看到了以下堆栈跟踪:

java.lang.RuntimeException: 
  at android.view.InputChannel.nativeReadFromParcel (Native Method)
  at android.view.InputChannel.readFromParcel (InputChannel.java:148)
  at android.view.IWindowSession$Stub$Proxy.addToDisplay (IWindowSession.java:796)
  at android.view.ViewRootImpl.setView (ViewRootImpl.java:750)
  at android.view.WindowManagerGlobal.addView (WindowManagerGlobal.java:298)
  at android.view.WindowManagerImpl.addView (WindowManagerImpl.java:91)
  at android.widget.Toast$TN.handleShow (Toast.java:732)
  at android.widget.Toast$TN$1.run (Toast.java:631)
  at android.os.Handler.handleCallback (Handler.java:739)
  at android.os.Handler.dispatchMessage (Handler.java:95)
  at android.os.Looper.loop (Looper.java:145)
  at android.app.ActivityThread.main (ActivityThread.java:6939)
  at java.lang.reflect.Method.invoke (Native Method)
  at java.lang.reflect.Method.invoke (Method.java:372)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1404)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1199)

进度条和Toast应该大约每5秒显示一次。

正如你所看到的,一切都发生在Android本身内部(没有引用到我的实际代码),但我认为以下是涉及的代码片段。

这是显示进度条的地方:

public abstract class FragmentNetworkingBenderAsyncTask<I, O> extends BenderAsyncTask<I, O> {

    @SuppressLint("StaticFieldLeak")
    private final Fragment fragment;
    private AlertDialog waitDialog;

    public FragmentNetworkingBenderAsyncTask(final Fragment fragment) {
        this.fragment = fragment;
    }

    @Override
    protected final void onPreExecute() {
        super.onPreExecute();
        if (fragment.isAdded()) {
            waitDialog = new SpotsDialog.Builder().setContext(fragment.getActivity()).build();           waitDialog.setMessage(MainActivity.commonContext.getString(R.string.Wait));
            waitDialog.show();
            innerOnPreExecute(); //abstract method
        } else {
            this.cancel(true);
        }
    }

    [...]

    @Override
    protected final void onPostExecute(final BenderAsyncTaskResult<O> result) {
        super.onPostExecute(result);
        if (fragment.isAdded()) {
            if (result.isSuccess()) {
                innerOnSuccessfulPostExecute(result); //abstract
            } else {
                innerOnUnsuccessfulPostExecute(result); //abstract
            }
        }
        waitDialog.hide();
    }
}

而这是显示Toast的地方(这个类继承自上一个片段中的类):

@SuppressLint("StaticFieldLeak")
private class ServerOrdersUploader extends FragmentNetworkingBenderAsyncTask<Order, Empty> {
    ServerOrdersUploader(Fragment fragment) {
        super(fragment);
    }

    [...]

    @Override
    protected void innerOnSuccessfulPostExecute(BenderAsyncTaskResult<Empty> result) {
        Toast.makeText(MainActivity.commonContext, MainActivity.commonContext.getString(R.string.UpdateSuccess), Toast.LENGTH_SHORT).show();
        new ServerOrdersDownloader(TableFragment.this).execute(tableNumber); //ServerOrdersDownloader has a similar behaviour
    }

    [...]
}

(完整的代码在此处可用:GitHub链接

正如我所说,这个问题似乎只发生在特定的设备上(一个带有Android 5.1的三星Galaxy Tab A6)。

可能是什么原因?

英文:

I'm having a strange problem which is present only on a specific device (or at least is not present in the ~10 other devices I tested my app on).

Sometimes, when the app should show a progress dialog followed by a Toast containing a message, it crashes instead; looking on Play Console, I see this stack trace:

java.lang.RuntimeException: 
at android.view.InputChannel.nativeReadFromParcel (Native Method)
at android.view.InputChannel.readFromParcel (InputChannel.java:148)
at android.view.IWindowSession$Stub$Proxy.addToDisplay (IWindowSession.java:796)
at android.view.ViewRootImpl.setView (ViewRootImpl.java:750)
at android.view.WindowManagerGlobal.addView (WindowManagerGlobal.java:298)
at android.view.WindowManagerImpl.addView (WindowManagerImpl.java:91)
at android.widget.Toast$TN.handleShow (Toast.java:732)
at android.widget.Toast$TN$1.run (Toast.java:631)
at android.os.Handler.handleCallback (Handler.java:739)
at android.os.Handler.dispatchMessage (Handler.java:95)
at android.os.Looper.loop (Looper.java:145)
at android.app.ActivityThread.main (ActivityThread.java:6939)
at java.lang.reflect.Method.invoke (Native Method)
at java.lang.reflect.Method.invoke (Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1199)

The progress bar and the Toast should be shown about once every 5 seconds.

As you can see, everything happens inside Android itself (there is no reference to my actual code), but I believe the following are the involved pieces of code.

This is where the progress bar is shown:

public abstract class FragmentNetworkingBenderAsyncTask&lt;I, O&gt; extends BenderAsyncTask&lt;I, O&gt; {
@SuppressLint(&quot;StaticFieldLeak&quot;)
private final Fragment fragment;
private AlertDialog waitDialog;
public FragmentNetworkingBenderAsyncTask(final Fragment fragment) {
this.fragment = fragment;
}
@Override
protected final void onPreExecute() {
super.onPreExecute();
if (fragment.isAdded()) {
waitDialog = new SpotsDialog.Builder().setContext(fragment.getActivity()).build();           waitDialog.setMessage(MainActivity.commonContext.getString(R.string.Wait));
waitDialog.show();
innerOnPreExecute(); //abstract method
} else {
this.cancel(true);
}
}
[...]
@Override
protected final void onPostExecute(final BenderAsyncTaskResult&lt;O&gt; result) {
super.onPostExecute(result);
if (fragment.isAdded()) {
if (result.isSuccess()) {
innerOnSuccessfulPostExecute(result); //abstract
} else {
innerOnUnsuccessfulPostExecute(result); //abstract
}
}
waitDialog.hide();
}
}

While this is where the Toast is shown (the class inherits from the one in the previous snippet):

@SuppressLint(&quot;StaticFieldLeak&quot;)
private class ServerOrdersUploader extends FragmentNetworkingBenderAsyncTask&lt;Order, Empty&gt; {
ServerOrdersUploader(Fragment fragment) {
super(fragment);
}
[...]
@Override
protected void innerOnSuccessfulPostExecute(BenderAsyncTaskResult&lt;Empty&gt; result) {
Toast.makeText(MainActivity.commonContext, MainActivity.commonContext.getString(R.string.UpdateSuccess), Toast.LENGTH_SHORT).show();
new ServerOrdersDownloader(TableFragment.this).execute(tableNumber); //ServerOrdersDownloader has a similar behaviour
}
[...]
}

(full code is available here)

As I said, the problem seems to happen only on a specific device (a Samsung Galaxy Tab A6 with Android 5.1).

What could it be?


Edit 31/07/2020: add code snippets

答案1

得分: 1

可能是操作系统本身的一个错误,就像@Ben P.所说的那样,
我觉得问题的原因是当进度条和提示重叠时,操作系统处理起来有问题。
尝试在一个完成后执行另一个。

英文:

It might be a bug with the OS itself as @Ben P. said,
I feel the cause of the issue is when both progress bar and toast are sort of overlapped and the OS is buggy to handle it.
Try Executing one after the other one is finished

huangapple
  • 本文由 发表于 2020年7月21日 18:45:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/63012805.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定