我的团队正在开发一个Android项目,该项目由几个交换数据的Android应用程序组成(在同一部手机上).我们的想法是让几个应用程序收集一些数据并将这些数据发送到主应用程序.这里的主要挑战是在CPU负载和电池使用方面尽可能便宜地进行交换.
据我所知,有两种方法可以实现进程间通信:
我想知道在以下场景中哪些更有效:
无论是在比较方面还是与基准的参考/链接方面,我都将不胜感激.
我有一个.aidl文件,它定义了一个接口类型的单个parcelable,比方说
parcelable MyInterface;
Run Code Online (Sandbox Code Playgroud)
因此,MyInterface是在MyInterface.java中声明的Java接口,它扩展了Parcelable接口.android parcelable机制要求我在parcelable类中定义一个静态CREATOR.但是,如何为接口执行此操作,因为接口类不知道具体实现,因此无法实现createFromParcel()方法?
android运行时将如何决定调用哪个CREATOR(来自哪个子类)?甚至不可能在.aidl文件中使用接口类型?
我有一个VOIP
应用程序,我需要在设备启动的后台登录应用程序.
目前我的应用程序的init是在UI
Active(onCreate()
)上完成的.
在我的脑海里,我有以下几点,任何人都可以帮助并消除我的疑虑.
Service Remote(AIDL)
或本地服务以及为什么?UI
和Service
互动是如何发生的?UI
获得回拨之后是否活跃?UI
还是Service
?Service
我的Controller
ie Service
作为UI
数据通过反之亦然?示例应用程序:Skype.
我正在尝试为不同包中的多个服务共享一个公共对象。每个服务必须调用相同的对象。
例如,服务 A(来自 APK A)实例化一个自定义对象,我希望服务 B 和 C(来自 APK B 和 C)检索该对象的引用并调用它的某些方法。
我在 Android 参考中发现使用Parcel应该是可能的:
活动对象
Parcel 的一个不同寻常的功能是能够读取和写入活动对象。对于这些对象,不写入对象的实际内容,而是写入引用该对象的特殊标记。从 Parcel 读回对象时,您不会获得该对象的新实例,而是一个对最初写入的完全相同对象进行操作的句柄。有两种形式的活动对象可用。
Binder 对象是 Android 通用跨进程通信系统的核心工具。IBinder 接口描述了一个带有 Binder 对象的抽象协议。任何这样的接口都可以写入 Parcel 中,在阅读时,您将收到实现该接口的原始对象或一个特殊的代理实现,该代理实现将回调通信回原始对象。使用的方法有 writeStrongBinder(IBinder), writeStrongInterface(IInterface), readStrongBinder(), writeBinderArray(IBinder[]), readBinderArray(IBinder[]), createBinderArray(), writeBinderList(List), readBinderList(List), createBinderArrayList() .
我试图通过 AIDL 传递我的对象(扩展绑定器)来做到这一点,但没有任何效果,当我尝试从方法 createFromParcel(Parcel in) 检索引用时,我总是得到 ClassCastException。
我的代码示例:
public class CustomObject extends Binder implements Parcelable {
public CustomObject() {
super();
}
public static final Parcelable.Creator<CustomObject> CREATOR = new Parcelable.Creator<CustomObject>() {
public CustomObject createFromParcel(Parcel in) {
IBinder i = in.readStrongBinder(); …
Run Code Online (Sandbox Code Playgroud) 我们向第三方开发者公开 AIDL 服务。我们希望从此服务返回可打包对象,但我们担心向后兼容性。我的意思是,针对 Parcelable 版本 N 编译的客户端和针对版本 N+1 编译的服务必须协同工作。
根据我的测试,对于简单的平面对象(仅限简单类型字段),只要将新字段打包在流的末尾,就可以向后兼容...例如,
in.writeInt(field1);
in.writeInt(field2); // new field
Run Code Online (Sandbox Code Playgroud)
然而,当涉及到复杂的物体时,事情就会爆炸。例如,
class D implements Parcelable {
int field1;
}
class C implements Parcelable {
List<D> ds;
}
Run Code Online (Sandbox Code Playgroud)
如果将第二个字段添加到 class 中D
,
class D implements Parcelable {
int field1;
int field2; // new field
}
Run Code Online (Sandbox Code Playgroud)
类的解组C
失败(我尝试使用Parcel.writeList()
和Parcel.writeParcelableArray()
)。
这件案子竟然无法处理,这似乎几乎是不可想象的。当然,我们可以按原样保留旧的绑定器接口,并创建一个新的绑定器接口,该接口返回带有附加字段的新类的对象,但是对于返回经常更改的类的服务,这将导致混乱。例如,接口 1.0 返回一个Person
. 现在我们添加一个字段,并且我们有一个新的binder接口2.0,它返回Person2
对象,等等。
这让我们不得不使用一些更宽容的格式(例如 JSON)来传递 IPC 数据。
有什么建议么?
我对服务创建期间的封送有一个简单的疑问。当接口中writeToParcel()
声明的方法在Parcelable
生成的存根中调用时(如果将aidl方法参数声明为in
),为什么接口中没有readFromParcel()
声明Parcelable
(用于out
参数)?
我可以创建自己的,readFromParcel()
但根据我的理解,readFromParcel()
如果生成的存根想要调用它,则 Parcelable 接口中应该有一个覆盖声明。但是Parcelable 接口的文档没有显示任何readFromParcel()
方法的迹象。为什么会这样?它是否包含在以前的 API 版本中,后来被删除了?请解释 !
如果 createFromParcel() 和 readFromParcel() 都试图读取一个 Parcelable 对象并用其中的数据填充成员字段,那么它有什么不同?
场景:我有一个Controller
(普通的 Java 类)必须能够引导多个Slave
s。
ASlave
的性质可以不同,因此它可以是:
Service
,我们称之为 a ServiceSlave
:这个对象的生命周期通常不同于应用程序的组件(比如,它不依赖于当前的活动)ObjectSlave
:这个对象的生命周期在某种程度上绑定到它被创建的范围(比如,当前活动)这两种类型的Slave
共同点是它们可以驻留在不同的进程中。
由于这最后一个“要求”,我立即将注意力转向AIDL
/Messenger
作为 aController
和 a之间的通信形式Slave
,因为它提供了 IPC。
然而,似乎AIDL
(反过来Messenger
,因为它也应该基于 AIDL)只有在您使用Service
. 也就是说,我没有办法在AIDL
没有IBinder
对象的情况下实现基于 -based 的接口,通常在onServiceConnected
方法中提供。
第一个问题:AIDL
真的只能在处理a时使用Service
吗?如果是,为什么会这样?
现在,考虑我的场景。我想,就像任何其他优秀的开发人员一样,编写一个单一的、优雅的界面,允许Controller
引导每个Slave
,而不管它们的性质。到目前为止,我想到的唯一解决方案是使用Intent
s 和BroadcastReceiver
s,所有这些都方便地包装在专用的 Java 类中。
第二个问题:这是唯一可行的方法吗?我在监督什么吗?
编辑
我想我应该提供有关Controller …
Android AIDL 是否支持泛型?
例如,假设我有一个 class Result<T>
,其中 T 可以是任何类型,包括原语(通过自动装箱)或其他自定义类,例如Car
. 任何自定义类都Parcelable
按照 Binder 的要求实现。
那么可能的 AIDL 方法签名将是
Result<Car> m1();
Result<Void> m2();
Result<Boolean> m3();
我有一个在 ProjectA 下的包中实现的 AIDL 文件,并且我正在尝试从 ProjectB 下的另一个包导入 Parcelable 类 (Foo)。以下是我实现 MyService.AIDL 文件的方式:
package com.packageA.projectA
import com.packageB.projectB.Foo
interface MyService{
void getSomething(Foo foo);
}
Run Code Online (Sandbox Code Playgroud)
但是,我收到此编译错误“无法找到类 com.example.projectB.Foo 的导入”。如果我将 packageB 复制到 packageA,则不会出现编译错误。
有没有办法从不同项目下的包中导入parcelable类?我知道在 stackoverflow 和其他地方(比如 google group)上有多个关于在同一项目下导入 Parcelable 的问题,但没有来自不同项目的问题。感谢您的时间。
有人可以区分应该使用广播接收器、AIDL(Android 接口定义语言)和信使的场景吗?有人告诉我使用广播接收器会耗尽电池,所以我不应该使用它。AIDL 和信使用于 IPC(进程间通信),但我可以使用 AIDL 方式将数据从服务传递到同一进程内的活动。
那么在这种情况下,我应该选择 AIDL 还是广播接收器?
aidl ×10
android ×10
parcelable ×3
ipc ×2
java ×2
controller ×1
generics ×1
interprocess ×1
parcel ×1
performance ×1
service ×1