You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨App调用IntentService时Parcel解组ClassNotFoundException问题求助

解决跨进程调用Service时Parcel反序列化ClassNotFoundException问题

这个错误的核心原因很明确:你在App2中定义的AddressResultReceiver类,在App1的类加载路径里根本不存在。Android的每个应用都有独立的类加载器,当App2把自定义的ResultReceiver子类通过Intent传递给App1时,App1尝试反序列化这个对象,却找不到对应的类定义,自然就抛出了ClassNotFoundException。

下面给你两种可行的解决方案,按推荐优先级排序:


方案一:共享自定义ResultReceiver类到公共Library

把AddressResultReceiver抽成独立的Android Library模块,让App1和App2都依赖这个库,保证两个应用里的类全限定名完全一致,这样双方的类加载器都能找到这个类。

步骤1:创建公共Library并定义类

新建一个Android Library模块,在其中定义AddressResultReceiver(注意包名要固定,比如com.example.common):

package com.example.common;

import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;

public class AddressResultReceiver extends ResultReceiver {
    private ReceiverCallback mCallback;

    public AddressResultReceiver(Handler handler) {
        super(handler);
    }

    // 定义回调接口,让App2的Activity能接收结果
    public interface ReceiverCallback {
        void onReceiveResult(int resultCode, String message);
    }

    public void setReceiverCallback(ReceiverCallback callback) {
        mCallback = callback;
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        if (mCallback != null) {
            String message = resultData.getString("receiver");
            mCallback.onReceiveResult(resultCode, message);
        }
    }
}

步骤2:修改App1的Service代码

确保App1依赖这个Library,然后修改servicev类引用公共库的AddressResultReceiver:

package com.veritran.vttokentest;

import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import com.example.common.AddressResultReceiver;

public class servicev extends IntentService {
    protected AddressResultReceiver mReceiver;

    public servicev() {
        super("yeah");
    }

    @Override
    protected void onHandleIntent(Intent workIntent) {
        Toast.makeText(getApplicationContext(), "onHandle starting", Toast.LENGTH_LONG).show();
        mReceiver = workIntent.getParcelableExtra("receiver");
        deliverResultToReceiver(1, "value of servicev");
    }

    private void deliverResultToReceiver(int resultCode, String message) {
        Bundle bundle = new Bundle();
        bundle.putString("receiver", message);
        mReceiver.send(resultCode, bundle);
    }
}

步骤3:修改App2的MainActivity代码

同样依赖公共Library,然后调整代码接收结果:

package com.example.idscomercial.myapplication;

import android.os.Bundle;
import android.os.Handler;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.Toast;
import com.example.common.AddressResultReceiver;

public class MainActivity extends AppCompatActivity implements AddressResultReceiver.ReceiverCallback {
    protected AddressResultReceiver mResultReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startIntentService();
    }

    protected void startIntentService() {
        mResultReceiver = new AddressResultReceiver(new Handler());
        mResultReceiver.setReceiverCallback(this);
        Intent intent = new Intent("com.veritran.vttokentest.servicev.START_SERVICE");
        intent.setPackage("com.veritran.vttokentest");
        intent.putExtra("receiver", mResultReceiver);
        startService(intent);
    }

    @Override
    public void onReceiveResult(int resultCode, String message) {
        Toast.makeText(this, "收到App1返回结果:" + message, Toast.LENGTH_LONG).show();
    }
}

方案二:改用Messenger实现跨进程通信

如果不想维护公共Library,可以直接用Android原生的Messenger来实现跨进程消息传递。Messenger基于AIDL封装,底层用Binder通信,而且是系统类,两个应用的类加载器都能识别。

步骤1:修改App1的Service代码

package com.veritran.vttokentest;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.widget.Toast;

public class servicev extends Service {
    // 处理App2发来的消息
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            Toast.makeText(getApplicationContext(), "收到App2的请求", Toast.LENGTH_SHORT).show();
            
            // 获取App2的回调Messenger
            Messenger replyMessenger = msg.replyTo;
            try {
                // 组装结果返回
                Message replyMsg = Message.obtain(null, 1);
                Bundle bundle = new Bundle();
                bundle.putString("receiver", "value of servicev");
                replyMsg.setData(bundle);
                replyMessenger.send(replyMsg);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    final Messenger mMessenger = new Messenger(new IncomingHandler());

    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "Service已绑定", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}

步骤2:修改App1的Manifest

给Service添加绑定的IntentFilter:

<service android:enabled="true" android:exported="true" android:name="com.veritran.vttokentest.servicev">
    <intent-filter>
        <action android:name="com.veritran.vttokentest.servicev.BIND_SERVICE" />
    </intent-filter>
</service>

步骤3:修改App2的MainActivity代码

package com.example.idscomercial.myapplication;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    Messenger mService = null;
    boolean mBound = false;

    // 接收App1返回结果的Handler
    class ReplyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                String result = msg.getData().getString("receiver");
                Toast.makeText(MainActivity.this, "收到结果:" + result, Toast.LENGTH_LONG).show();
            }
        }
    }

    final Messenger mMessenger = new Messenger(new ReplyHandler());

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = new Messenger(service);
            mBound = true;
            // 绑定成功后发送请求
            sendRequestToService();
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            mService = null;
            mBound = false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 绑定App1的Service
        Intent intent = new Intent("com.veritran.vttokentest.servicev.BIND_SERVICE");
        intent.setPackage("com.veritran.vttokentest");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private void sendRequestToService() {
        if (!mBound) return;
        Message msg = Message.obtain(null, 0); // 自定义消息码,标识请求类型
        msg.replyTo = mMessenger; // 设置回调Messenger
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}

内容的提问来源于stack exchange,提问作者arnoldssss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:23:56