Отправить объект из сервиса в действие (не может выполнить маркер без возможности передачи)
Я пытаюсь отправить данные из своей деятельности в службу и получить некоторую информацию обратно, но я получаю:
java.lang.RuntimeException: Невозможно провести маршалирование объектов, не подлежащих разделению, между процессами.
Код из активности выглядит так:
Message msg = Message.obtain(null, 1);
msg.obj=1;
msg.replyTo=new Messenger(new PlanRequestIncomingHandler());
try {
msgService.send(msg);
} catch (RemoteException e) {
Log.i(tag, "Can not send msg to service");
e.printStackTrace();
}
Когда я установил msg.obj = something
Я получаю java.lang.RuntimeException, кто-нибудь может мне помочь?
5 ответов
Вы можете передавать объекты типа Parcelable через Messenger. Или, если вы хотите передать примитивные типы данных, используйте обертку Bundle, как показано ниже.
В конце службы:
//Create a bundle object and put your data in it
Bundle bundle = new Bundle();
bundle.putInt("key", 1);
Message msg = Message.obtain(null, 123);
msg.obj = bundle;
msg.replyTo = new Messenger(new PlanRequestIncomingHandler());
try {
msgService.send(msg);
} catch (RemoteException e) {
Log.i(tag, "Can't send msg to service");
e.printStackTrace();
}
В конце действия:
switch(msg.what) {
case 123:
if(msg.obj != null) {
Bundle bundle = (Bundle) msg.obj;
System.out.println("Got integer "+ bundle.getInt("key"));
}
break;
}
ура:-)
Старый вопрос, но я отвечаю, чтобы он мог кому-то помочь в будущем.
Если вы используете реальные объекты, то, конечно, внедрите Parcelable Android: как реализовать Parcelable для моих объектов?
Однако, как ОП заявил, что он пытался использовать Примитивы, и это не сработало, это то, что нужно сделать.
Проблема лежит здесь msg.obj=1;
Это ожидает фактический объект, который реализует Parcelable
использование msg.arg1 = 1;
Затем вы можете получить аргумент на стороне службы, используя msg.arg1
Для простоты я использую (прямо из моего кода)
Message msg = Message.obtain(null, PlayerService.MSG_ACTION_SEEK, i, -1);
-1 просто держатель для меня.
Надеюсь это поможет.
Изменить: будьте осторожны с
Message msg = Message.obtain(null, PlayerService.MSG_ACTION_SEEK, i);
Эта подпись эквивалентна первой попытке ОП и ожидает Parcelable, и это то, что фактически споткнуло меня и заставило меня искать в первую очередь. Он не выдаст ошибку до времени выполнения.
Вы должны использовать Bundle для передачи данных обычного типа, иначе это будет неправильно:
Java.lang.RuntimeException: не может неразборчивые объекты через процессы маршала.
Поскольку данные транзакции Binder называются Parcel, интерфейс Parcelable должен быть реализован, в противном случае обмен данными между двумя приложениями невозможен. Причина, по которой Bundle передается, потому что класс реализует интерфейс Parcelable. Конечно, если вы хотите передать класс, необходимо также реализовать интерфейс.
Вы можете написать как вниз:
Message msg = Message.obtain(null, 1);
msg.getData().putInt("key",1);
msg.replyTo=new Messenger(new PlanRequestIncomingHandler());
try {
msgService.send(msg);
} catch (RemoteException e) {
Log.i(tag, "Can not send msg to service");
e.printStackTrace();
}
прости я плохо знаю английский
Помимо примитивных данных, объекты, которые вы перемещаете между операциями и службами, должны реализовывать Parcelable и предпочтительно Serializable.
Надеюсь, это поможет,
Лучший
-serkan
Я реализовал Actor Model (например, Akka) для Android, так как Akka требует Java 8, я сделал свою собственную реализацию для Android, используя RxJava2, это было очень легко реализовать... И как только оно появилось, вы можете отправлять сообщения удержание любого объекта для любого получателя (Activity, Fragment, Service, Pojo и т. д.), не беспокоясь о потоках или сериализации
Трудно объяснить мою собственную реализацию в деталях, если вы не знаете, что такое Actor Model, но если вы знаете, вы можете создать интерфейс с именем "Actor" одним методом
void onMessageReceived(Message message);
И вы можете реализовать этот интерфейс любым имеющимся у вас Actor, а для регистрации любого Actor вы можете создать класс ActorSystem с методами:
static void register(Actor actor, PublishSubject<Message> mailbox);
static void unregister(Actor actor);
static void send(Message message, Class<? extends Actor> ... actors);
И когда вы регистрируете своего Actor (Activity или Service), вы решаете, какой ваш поток / планировщик будет получать ваши сообщения, через:
PublishSubject.observeOn(Schedulers.trampoline());
И вы регистрируете своего актера в onCreate() и отменяете регистрацию в onDestroy()
Или, если вам нужна библиотека для этого (но я ее не тестировал), вы можете взглянуть на это: