- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
所以我为 Android 操作系统编写了一个服务和一个 Activity 。
我的服务在它自己的进程中运行,所以我的 Activity 和服务之间的所有通信都是通过 IPC 进行的。为此,我使用标准的 Android .aidl 机制。
到目前为止一切正常。但是,AIDL 使用“throws RemoteException”生成所有方法 stub ,所以我必须处理它们。
我对整个 Android 源代码进行了一次快速 grep,只发现了三个抛出此异常的情况。这些在我没有连接的不同服务中。
我也检查了 C 源代码,因为理论上 RemoteExceptions 可以使用 JNI 接口(interface)生成。没有任何结果。
我的印象是每个人都只是这样处理它们:
try {
mService.someMethodCall (someArguments);
} catch (RemoteException e) {
e.printStackTrace();
}
这不是可靠的代码,我不希望在我的代码库中出现这样的内容。
除此之外:我自己尝试通过 IPC 抛出 RemoteException,我得到的只是堆栈跟踪和系统日志消息,告诉我尚不支持异常。我的应用程序从未见过异常,并且引发异常的服务最终处于非常奇怪的状态(中途工作):-(
问题是:
这些异常会被抛出吗?
有没有人见过这种捕获 RemoteException 的 try-catch block ?
难道它们不存在,而我们只是被迫处理它们,因为“抛出 RemoteException”是死代码或 AIDL 编译器内的遗留代码?
Disclamer:我还没有阅读完整的源代码。我使用 Grep 来查找 RemoteException 的出现,所以我可能由于不同的空白使用而错过了一些。
最佳答案
确实会抛出这些异常,您应该编写适当的 try/catch 逻辑来处理您在服务上调用的远程方法未完成的情况。
就您的调查而言,您在查看本地资源时走在了正确的轨道上。你可能忽略了android.os.RemoteException
实际上只是其他 Binder 相关异常的基类,它是子类 android.os.DeadObjectException
,在 native code of Binder 中抛出.
如果一个 Activity 使用了在另一个进程中运行的服务,而该服务在执行请求的过程中死掉了,它就会看到这个异常。通过对 Marko Gargenta's AIDLDemo example 进行以下小改动,我能够向自己证明这一点。 .
首先,通过更新 AndroidManifest.xml 确保服务在自己的进程中运行:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.marakana" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:theme="@android:style/Theme.Light">
<activity android:name=".AIDLDemo" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--ADD THE android:process TAG TO THE SERVICE-->
<service android:name=".AdditionService" android:process=":process2"/>
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>
然后修改add
方法提前退出:
@Override
public IBinder onBind(Intent intent) {
return new IAdditionService.Stub() {
/**
* Implementation of the add() method
*/
public int add(int value1, int value2) throws RemoteException {
Log.d(TAG, String.format("AdditionService.add(%d, %d)", value1,
value2));
System.exit(-1); // KILL THE PROCESS BEFORE IT CAN RESPOND
return value1 + value2;
}
};
}
在 logcat 中你会看到服务进程死亡,activity 收到 DeadObjectException
,最终系统重新生成服务进程。
D/AdditionService( 1379): AdditionService.add(1, 1)
I/AndroidRuntime( 1379): AndroidRuntime onExit calling exit(-1)
D/Zygote ( 32): Process 1379 exited cleanly (255)
I/ActivityManager( 58): Process com.marakana:process2 (pid 1379) has died.
W/ActivityManager( 58): Scheduling restart of crashed service com.marakana/.AdditionService in 5000ms
D/AIDLDemo( 1372): onClick failed with: android.os.DeadObjectException
W/System.err( 1372): android.os.DeadObjectException
W/System.err( 1372): at android.os.BinderProxy.transact(Native Method)
W/System.err( 1372): at com.marakana.IAdditionService$Stub$Proxy.add(IAdditionService.java:95)
W/System.err( 1372): at com.marakana.AIDLDemo$1.onClick(AIDLDemo.java:81)
W/System.err( 1372): at android.view.View.performClick(View.java:2408)
W/System.err( 1372): at android.view.View$PerformClick.run(View.java:8816)
W/System.err( 1372): at android.os.Handler.handleCallback(Handler.java:587)
W/System.err( 1372): at android.os.Handler.dispatchMessage(Handler.java:92)
W/System.err( 1372): at android.os.Looper.loop(Looper.java:123)
W/System.err( 1372): at android.app.ActivityThread.main(ActivityThread.java:4627)
W/System.err( 1372): at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err( 1372): at java.lang.reflect.Method.invoke(Method.java:521)
W/System.err( 1372): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
W/System.err( 1372): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
W/System.err( 1372): at dalvik.system.NativeStart.main(Native Method)
D/AIDLDemo( 1372): onServiceDisconnected() disconnected
I/ActivityManager( 58): Start proc com.marakana:process2 for service com.marakana/.AdditionService: pid=1399 uid=10037 gids={1015}
D/AdditionService( 1399): onCreate()
D/AIDLDemo( 1372): onServiceConnected() connected
我想如果您的服务与您的 Activity 在同一进程中运行,您可能永远不会看到此异常,但如果是这种情况,您可能不会再为 AIDL 烦恼。
此外,正如您所发现的,Android 不会在进程之间建立异常 channel 。如果您需要将错误传达回调用 Activity ,那么您需要使用其他方式。
关于Android RemoteExceptions 和服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3156389/
1) 谁能帮助我了解“Remoteexception”的概念?一般是什么意思? 2) 另外,unwrapRemoteException 是什么意思?不确定它的意思是“如果这个远程异常包含一个 look
所以我为 Android 操作系统编写了一个服务和一个 Activity 。 我的服务在它自己的进程中运行,所以我的 Activity 和服务之间的所有通信都是通过 IPC 进行的。为此,我使用标准的
我有这个演示脚本,我将其放入 Jenkins 作业中: Write-Host "##############################################" $ErrorAction
我的 IntentService 中有以下代码,用于向注册的客户端发送 Message: for(Messenger client : clients) { client.send(aMess
我注意到HDFS删除命令将随机失败。例如,在MapReduce作业中,我在启动时删除目录。有时它会因以下错误而失败,但是在第二次尝试时会成功。 org.apache.hadoop.ipc.Remote
NullPointerException 是运行时异常的一个可能原因是因为每个方法都可以抛出它,所以每个方法都需要有一个“抛出 NullPointerException”,并且会很丑陋。但这发生在 R
我遵循了本教程:https://docs.oracle.com/javase/6/docs/technotes/guides/rmi/hello/hello-world.html#5 我在命令提示符下
我在我的 EC2 实例上设置了 CHD4。一切正常。 当我尝试访问时:http://ec2-00-000-000-000.us-west-1.compute.amazonaws.com:50075/w
我正在将信息输入数据库,但遇到一些 EJB 异常。信息的路径来自带有操作类的 JSP,它将值插入到远程 EJB 方法中,该方法内部(在该方法内)调用另一个方法来访问 hibernate,然后调用另一个
我有一个奇怪的问题。我正在尝试使用 RMI 编写一个简单的 Hello World java 程序。这是我的文件,全部属于同一个包: Hello.java: package com.something
我正在使用 ubuntu 15.04 进行 RMI 和 SQL 编程。我正在编写以下 3 个文件: ServerIntf.java 、 ServerImpl.java 和 Server.java 当我
我已将 Eclipse 设置为生成有关缺少 Javadoc 标记的警告。但是,我想抑制针对 RMI 接口(interface)缺少 @throws RemoteException 标记的警告,因为这些
这是我想要强制抛出远程异常的代码: transient Bicycle b=null; public Bicycle getBicycle() { if(b==null) {
我想将一些文件从 Windows 机器复制到在 SingleNode 上的 ubuntu 14.04.02 上运行的 hadoop。这是用于此目的的代码; Configuration configur
我无法使用 Hadoop 的 WebHDFS REST API 创建文件。 按照文档,我正在这样做。 curl -i -X PUT "http://hadoop-primarynamenode:500
我正在运行hadoop群集,其中Ubuntu主机作为主从服务器,虚拟机在其上作为另一个从属服务器运行(2节点群集)。 似乎应该在No data nodes are started上解决的问题的解决方案
以下方法: private void startServer() { // snippet that starts the server on the local machine
以下方法: private void startServer() { // snippet that starts the server on the local machine
以下方法: private void startServer() { // snippet that starts the server on the local machine
以下方法: private void startServer() { // snippet that starts the server on the local machine
我是一名优秀的程序员,十分优秀!