java - 如何在 Delphi 代码中捕获 java 异常
问题描述
我正在编写一个通过 JNI 访问 Google Drive API 的 Delphi/Android 应用程序。我需要调用 Java 方法并捕获发生的任何异常。那么如何在 Delphi 中捕获 Java 异常呢?我还需要异常对象来从中获取意图。
我在网上搜索了一些关于 Env ExceptionCheck 的信息。我想我可以通过这种方式获取异常类,但是如何获取异常对象呢?
Java 代码如下所示:
try {
new Builder(
AndroidHttp.newCompatibleTransport(),
new GsonFactory(),
DriveLoginFragment.this.mCredential
).setApplicationName("My App").build();
}
catch (UserRecoverableAuthIOException e) {
DriveLoginFragment.this.startActivityForResult(
e.getIntent(),
REQUEST_ACCOUNT_PICKER);
return null;
}
Delphi 代码如下所示:
Drive := TJDrive_Builder.JavaClass.init(
TJAndroidHttp.JavaClass.newCompatibleTransport,
TJGsonFactory.JavaClass.init,
GoogleAccountCredential
)
.setApplicationName(StringToJString('My app'))
.build;
解决方案
我按照 Dave Nottage 的建议做了。我编写了一点java代码。
我用以下类制作了一个java库:
package com.softmagic.androidutils;
import java.lang.Thread.UncaughtExceptionHandler;
interface ExpListener {
void onException(Thread thread, Throwable throwable);
}
public class DelphiHandleExceptions implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
listenerInt.onException(thread, throwable);
}
ExpListener listenerInt;
public DelphiHandleExceptions(ExpListener listener) {
listenerInt = listener;
}
}
我通过java2op运行它,并得到以下信息:
unit AndroidApi.JNI.AndroidUtils;
interface
uses
Androidapi.JNIBridge,
Androidapi.JNI.JavaTypes;
type
// ===== Forward declarations =====
Jandroidutils_BuildConfig = interface;//com.softmagic.androidutils.BuildConfig
JDelphiHandleExceptions = interface;//com.softmagic.androidutils.DelphiHandleExceptions
JExpListener = interface;//com.softmagic.androidutils.ExpListener
// ===== Interface declarations =====
Jandroidutils_BuildConfigClass = interface(JObjectClass)
['{EE706AD2-1C35-46DF-BA16-6B6C82A32336}']
{class} function _GetAPPLICATION_ID: JString; cdecl;
{class} function _GetBUILD_TYPE: JString; cdecl;
{class} function _GetDEBUG: Boolean; cdecl;
{class} function _GetFLAVOR: JString; cdecl;
{class} function _GetVERSION_CODE: Integer; cdecl;
{class} function _GetVERSION_NAME: JString; cdecl;
{class} function init: Jandroidutils_BuildConfig; cdecl;//Deprecated
{class} property APPLICATION_ID: JString read _GetAPPLICATION_ID;
{class} property BUILD_TYPE: JString read _GetBUILD_TYPE;
{class} property DEBUG: Boolean read _GetDEBUG;
{class} property FLAVOR: JString read _GetFLAVOR;
{class} property VERSION_CODE: Integer read _GetVERSION_CODE;
{class} property VERSION_NAME: JString read _GetVERSION_NAME;
end;
[JavaSignature('com/softmagic/androidutils/BuildConfig')]
Jandroidutils_BuildConfig = interface(JObject)
['{2F38FDFA-A06E-486C-A2F1-9736596BFD14}']
end;
TJandroidutils_BuildConfig = class(TJavaGenericImport<Jandroidutils_BuildConfigClass, Jandroidutils_BuildConfig>) end;
JDelphiHandleExceptionsClass = interface(JThread_UncaughtExceptionHandlerClass)
['{E39A8542-DF8B-4880-8286-C4BD9993F6CE}']
{class} function init(P1: JExpListener): JDelphiHandleExceptions; cdecl;//Deprecated
{class} procedure uncaughtException(P1: JThread; P2: JThrowable); cdecl;//Deprecated
end;
[JavaSignature('com/softmagic/androidutils/DelphiHandleExceptions')]
JDelphiHandleExceptions = interface(JThread_UncaughtExceptionHandler)
['{B8AC378F-9FCA-4661-95E0-BA73736E6426}']
end;
TJDelphiHandleExceptions = class(TJavaGenericImport<JDelphiHandleExceptionsClass, JDelphiHandleExceptions>) end;
JExpListenerClass = interface(IJavaClass)
['{AC1C06C0-B5D4-4952-9076-5AAAE941703C}']
end;
[JavaSignature('com/softmagic/androidutils/ExpListener')]
JExpListener = interface(IJavaInstance)
['{DC8FC3DE-029F-4127-90AA-AABC2081B78B}']
procedure onException(P1: JThread; P2: JThrowable); cdecl;//Deprecated
end;
TJExpListener = class(TJavaGenericImport<JExpListenerClass, JExpListener>) end;
implementation
procedure RegisterTypes;
begin
TRegTypes.RegisterType('AndroidApi.JNI.AndroidUtils.Jandroidutils_BuildConfig', TypeInfo(AndroidApi.JNI.AndroidUtils.Jandroidutils_BuildConfig));
TRegTypes.RegisterType('AndroidApi.JNI.AndroidUtils.JDelphiHandleExceptions', TypeInfo(AndroidApi.JNI.AndroidUtils.JDelphiHandleExceptions));
TRegTypes.RegisterType('AndroidApi.JNI.AndroidUtils.JExpListener', TypeInfo(AndroidApi.JNI.AndroidUtils.JExpListener));
end;
initialization
RegisterTypes;
end.
我做了以下声明:
JavaExceptionListener: TJavaExceptionListener;
DefUncaughtExceptionHandler: JThread_UncaughtExceptionHandler;
DelphiHandleExceptions: JDelphiHandleExceptions;
在我的 FormCreate 方法中,我输入了:
JavaExceptionListener := TJavaExceptionListener.Create;
DefUncaughtExceptionHandler := TJThread.JavaClass.getDefaultUncaughtExceptionHandler;
DelphiHandleExceptions :=
TJDelphiHandleExceptions.JavaClass.init(JavaExceptionListener);
TJThread.JavaClass.setDefaultUncaughtExceptionHandler(DelphiHandleExceptions);
我定义了监听器:
TJavaExceptionListener = class(TJavaLocal, JExpListener)
procedure onException(P1: JThread; P2: JThrowable); cdecl;
end;
它的方法:
procedure TJavaExceptionListener.onException(P1: JThread; P2: JThrowable);
begin
if TJNIResolver.IsInstanceOf(P2, TJUserRecoverableAuthIOException.GetClsID)
then
begin
TAndroidHelper.Activity.startActivityForResult(TJUserRecoverableAuthIOException.Wrap(P2).getIntent, REQUEST_ACCOUNT_PICKER);
Exit;
end;
DefUncaughtExceptionHandler.uncaughtException(P1, P2);
end;
我还没有测试过。我的应用程序尚未准备好进行测试。我认为这会奏效。
推荐阅读
- terraform - 如果不为空,则添加到列表
- go - 在运行时更新 golang 缓冲通道的容量
- amazon-web-services - Docker 文件需要在没有 Internet 网关的情况下安装 nvm
- python - 如何使用 Tkinter GUI(Python)通过套接字传输文件
- spring-mybatis - @CacheNamespace 和 @CacheNamespaceRef
- cassandra - 轻量级事务抛出 CassandraWriteTimeoutException
- python - 如何将复杂包的python类型提示指定为opencv或tensorflow?
- reactjs - REACTJS 使用 fetch 通过 const 传递变量
- javascript - React Router 不显示页面 - React JS
- apache-spark - Pyspark如果存在滚动日期时间记录,如何创建列并填充真/假