Является ли использование Parcelable правильным способом передачи данных между приложениями?
Я пытаюсь понять, как общаться между приложениями в Android, а не только между Activity
экземпляров.
Я установил "клиент", который отправляет объект Messenger в службу (в Intent
отправлено в сервис); служба создает Message
obj и отправляет его обратно клиенту, используя messenger.send(message)
, Это работает нормально, пока я не попытаюсь использовать Message.obj для хранения объекта.
Я создал свой собственный Parcelable
учебный класс MyParcelable
в сервис и положить его в сообщение. Все работает, пока сообщение не будет распаковано в "клиенте". Unmarshall терпит неудачу, потому что "клиент" не имеет доступа к MyParcelable
учебный класс. Это очевидно - они находятся в разных пакетах (скажем, com.whatever.myclient
а также com.whatever.myserver
). Это абсолютно неправильный путь?
Я также пытался создать Parcel
и отправка этого (таким образом, оба приложения будут иметь доступ к классу) - но Parcel
не является Parcelable
, Я читал об используемых загрузчиках классов, но не понимаю, как разделять загрузчики классов в отдельных приложениях (процессы, если я понимаю архитектуру Android в этом отношении). То есть, как можно "научить" одного загрузчика классов тому классу, который существует в другом загрузчике классов? Конечно, кажется, что должно быть очевидное "вот как ты это делаешь", но я этого еще не видел.
3 ответа
Вы не можете удалить класс из процесса, который не знает этого класса (как вы уже правильно указали). Если ты хочешь MyParcelable
быть отправленным на ваш Service
тогда нужно включить MyParcelable
в Service
на сборку, и включить право ClassLoader
для использования при демаршаллинге, потому что демаршаллинг выполняется системным потоком, который не знает, что MyParcelable
даже если вы включили его во время компиляции.
РЕДАКТИРОВАТЬ:
(a) включите MyParcelable в 2 разных pkgs и сделайте так, чтобы они рассматривались как один и тот же класс
Создайте библиотеку из ваших общих классов и включите ее в оба приложения (приложение и Service
). Вы можете пометить ее как библиотеку Android (в Eclipse это прямо в свойствах Android проекта) или экспортировать как JAR и импортировать в оба приложения. Всегда полезно иметь независимые классы в библиотеке, а не помещать их непосредственно в приложения. Таким образом, вы можете использовать их в других проектах;)
(2) включить правильный ClassLoader (например, откуда мне взять правильный загрузчик классов)
Вы можете получить свой ClassLoader
из текущего потока, когда вы выполняете свой код. Очевидно, это ClassLoader
знает о ваших классах, потому что он выполняет ваш код;) Например, в Activity#onCreate()
, ты можешь сделать Thread.currentThread.getContextClassLoader()
, Так как ваш MyParcelable
класс также включен в Service
, вы можете сделать то же самое, чтобы получить действительный ClassLoader
разобрать.
Другое решение для IPC - определить интерфейс AIDL, чтобы вам не приходилось реализовывать Parcelable
,
Хорошо, я нашел "легкий путь", который искал. Вы можете поместить Bundle в поле Message.obj. Пакет Parcelable, поэтому его можно транспортировать между клиентом и сервером. Нет проблем с тем, что сервер не знает, какой класс он получает, поскольку Bundle "встроен" в Android Java. И, возможно, Bundle может включать в себя "sub-Bundles" с in. Это проще, чем иметь дело с обеспечением того, чтобы обе стороны знали определение пользовательского класса. Спасибо за ответы выше - я, конечно, оценил информацию!
Если вы не хотите где-то использовать постоянный слой (я использую облачный apis), вы можете запустить сервис в отдельном процессе и привязать к сервису соответствующие приложения, которым нужны данные объекта общего типа-держателя значения. сервис будет там, где вы создаете и получаете значения obj от имени подключающихся (связывающих) приложений.