Да, ваша идея возможна. Исключение ClassNotFoundException
вызвано тем, что вы пытаетесь разархивировать класс, который был создан в другом процессе другим ClassLoader
.
Класс
ResultReceiver
реализует интерфейс Parcelable
, который подходит для межпроцессных вызовов (IPC), однако для чтения вашего объекта в сервисе вам необходимо использовать тот же ClassLoader, который использовался для создания объекта в клиентском приложении. (т.е. в деятельности). Чтобы получить ClassLoader на стороне службы, вызовите метод createPackageContext
, передающий имя пакета клиента и комбинацию флагов CONTEXT_INCLUDE_CODE
| CONTEXT_IGNORE_SECURITY
. Это вернет объект контекста клиента, из которого можно получить правильный объект ClassLoader.
Пример:
public int onStartCommand(Intent intent, int flags, int startId) {
try {
// assuming SignerClient activity is located in the package "com.example.client.A"
Context context = createPackageContext("com.example.client.A", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
ClassLoader cl = context.getClassLoader();
Bundle bundle = intent.getExtras();
bundle.setClassLoader(cl);
ResultReceiver rr = bundle.getParcelable("resultreceiver");
//... your interaction with ResultReceiver ...
rr.send(1, null); // will result in a onReceiveResult call in the client activity
} catch (NameNotFoundException e) {
Log.e("MyService", "SignerClient package context was not found", e);
throw new RuntimeException(e);
}
return START_STICKY;
}
Я только что использовал это в своем коде - работает как шарм.
UPDATE
Однако я предлагаю рассмотреть возможность использования Messenger
вместо ResultReceiver
. Он реализует интерфейс Parcelable
и не нуждается в расширении, поэтому проблема ClassLoader невозможна. И это также рекомендуется в официальной документации .
ОБНОВЛЕНИЕ 2
Если вы все еще предпочитаете использовать ResultReceiver
, взгляните на Ответ Роберта в этой теме . Это выглядит чище и проще, чем хакерские манипуляции с контекстом.