7

我有一项服务设置为在单独的进程中启动:

<service android:name=".services.UploadService"
          android:process=":UploadServiceProcess" />

我可以使用 bindService() 成功绑定到它。当我尝试通过调用 Messenger.send() 发送消息时出现我的问题:

service.send(Message.obtain(null, UploadService.MESSAGE_UPLOAD_REQUEST, uploadRequest));

其中 uploadRequest 是实现 Parcelable 的自定义对象

public class UploadRequest implements Parcelable {
    public File file;
    public boolean deleteOnUpload;

public UploadRequest(File file, boolean deleteOnUpload) {
    this.file = file;
    this.deleteOnUpload = deleteOnUpload;
}

private UploadRequest(Parcel in) {
    this.file = new File(in.readString());
}

public int describeContents() {
    return 0;
}

public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.file.getPath());
}

public static final Parcelable.Creator<UploadRequest> CREATOR = new Parcelable.Creator<UploadRequest>() {
    public UploadRequest createFromParcel(Parcel in) {
        return new UploadRequest(in);
    }
    public UploadRequest[] newArray(int size) {
        return new UploadRequest[size];
    }
};

}

我在我的服务句柄消息中设置了一个断点,但我的应用程序永远不会到达断点。但是,如果不是使用我的自定义 UploadRequest 对象我发送 null,我会像我期望的那样到达 handleMessage 断点,但显然我此时无能为力。当调用 writeToParcel 返回非空字符串时,我已经验证了 file.getPath()。这让我相信我的 UploadRequest 课程中有问题,但通过谷歌搜索我看不出我的课程有什么问题。有任何想法吗?

4

3 回答 3

13

消息成员 obj的文档说:

要发送给收件人的任意对象。当使用 Messenger 跨进程发送消息时,如果它包含一个框架类的 Parcelable(不是应用程序实现的),它只能是非空的。对于其他数据传输,请使用 setData(Bundle)。请注意,在 FROYO 版本之前,此处不支持 Parcelable 对象。

我的猜测是您看到了一个问题,因为您正在创建自己的 parcelable,这在跨越流程边界时是不允许的。相反,您必须将您的对象打包成一个包。这也意味着您的对象将需要实现 Serializable 但不需要是 Parcelable。

于 2011-02-24T05:04:42.690 回答
4

刚刚试过这个。

Message.obj 可以传递一个框架类,例如 ContentValues。

Message.SetData 可以跨进程传输 Bundle,您可以将任何 Parcelable 对象放入该包中。

只记得在收到消息时在捆绑包上调用 setClassLoader。

发送方

        Message localMsg = Message.obtain();
        localMsg.what = TPServiceConnection.MSG_REPLY_SERVICE_HELLO;

        Bundle data = new Bundle();

        ContentValues cv = new ContentValues();
        cv.put("KEY", mRand.nextInt());
        data.putParcelable("KEY", cv);

        TPServiceDataModal modal = new TPServiceDataModal(mRand.nextInt());
        data.putParcelable("KEY2", modal);

        localMsg.setData(data);

接收方

        Bundle data = msg.getData();
        data.setClassLoader(this.getClass().getClassLoader());

        Parcelable parcelable = data.getParcelable("KEY");
        if (parcelable instanceof ContentValues) {
            ContentValues cv = (ContentValues) parcelable;
            Log.d(TAG, "reply content: " + cv.getAsInteger("KEY"));
        }

        Parcelable parcelable2 = data.getParcelable("KEY2");
        if (parcelable2 instanceof TPServiceDataModal) {
            TPServiceDataModal modal = (TPServiceDataModal) parcelable2;
            Log.d(TAG, "reply modal: " + modal.mData);
        }

其中 TPServiceDataModal 是 Parcelable 类。

于 2014-12-17T05:56:25.570 回答
0

传递parcelable对象的示例Bundle,记住使用classLoader正确的包来定义对象

客户端应用

val msg: Message = Message.obtain(null, MSG_SAY_HELLO)
msg.data = Bundle().apply {
    putParcelable("KEY_MY_OBJECT", MyObject("an", 12))
}
mService?.send(msg)

.

package com.example.androidmessengerclient    
@Parcelize
class MyObject(val name: String, val age: Int) : Parcelable

服务器应用

override fun handleMessage(msg: Message) {
            when (msg.what) {
                123 -> {

                     msg.data.classLoader = MyObject::class.java.classLoader
                     val o = msg.data.getParcelable<MyObject>("KEY_MY_OBJECT")
                }
            }
}

. 应用中的模型Server需要和应用有相同的Client

package com.example.androidmessengerclient    
@Parcelize
class MyObject(val name: String, val age: Int) : Parcelable
于 2021-02-02T07:54:00.047 回答