1

我尝试打印 PDF 文件,它工作正常,直到我尝试打印格式错误的 PDF 文件。我不知道为什么应用程序会崩溃,即使我曾经try / catch防止崩溃。我检查并发现PrintManager.java:1101抛出RuntimeException

 case MSG_ON_KILL: {
     if (DEBUG) {
         Log.i(LOG_TAG, "onKill()");
     }

     String reason = (String) message.obj;
     throw new RuntimeException(reason);
 }

所以下面的代码不应该导致崩溃:

public static void startPdfPrintProcedure(@NonNull Context context, @NonNull String filePath, @Nullable String jobName) {
    try {
        PrintManager printManager = (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
        String jobName = formatDefaultJobName(context.getResources(), jobName);
        PrintDocumentAdapter pda = new SimplePrintDocumentAdapter(new File(filePath));
        if (printManager != null) {
            try {
                printManager.print(jobName, pda, null); // <- crash here even though there is a try/catch
            } catch (RuntimeException e) {
                showUnknownError();
            }
        } else {
            showUnknownError();
        }
    } catch (RuntimeException e) {
        showUnknownError();
    }
}

尝试打印 PDF 后出现的异常。:

 java.lang.RuntimeException: Cannot print a malformed PDF file
    at android.print.PrintManager$PrintDocumentAdapterDelegate$MyHandler.handleMessage(PrintManager.java:1101)
    at android.os.Handler.dispatchMessage(Handler.java:112)
    at android.os.Looper.loop(Looper.java:216)
    at android.app.ActivityThread.main(ActivityThread.java:7625)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)

为什么try/catch代码没有捕捉到这个异常?如何保护这段代码不崩溃?

4

1 回答 1

0

发生这种情况是因为一些“天才”Google 开发人员提出了在主线程中引发异常导致应用程序关闭的“好”想法。我曾尝试使用反射解决问题,但实现过于封闭。不幸的是,如果文件不正确,您必须在应用程序即将关闭的情况下使用它,除非您想在调用 API 之前实现一个库来检查 PDF 格式。谷歌永远不会失败,你总是不得不搞乱它的实现。

辅助线程最终调用此处理程序。

    private final class MyHandler extends Handler {

            public static final int MSG_ON_KILL = 5;
            ...

            @Override
            public void handleMessage(Message message) {
                switch (message.what) {
                    ...
                    
                    case MSG_ON_KILL: {
                        if (DEBUG) {
                            Log.i(LOG_TAG, "onKill()");
                        }

                        String reason = (String) message.obj;
                        throw new RuntimeException(reason);<---------
                    }

                    default: {
                        throw new IllegalArgumentException("Unknown message: "
                                + message.what);
                    }
                }
            }
        }
于 2021-01-04T16:18:31.707 回答