Добрый день.
Наконец у меня дошли руки до разбора нового функционала по мобильной платформе.
В частности, как вы поняли из заголовка статьи – речь пойдет о таком новом объекте, как ЗапускПриложенияМобильногоУстройства.
К сожалению, я не смогу в статье поделиться абсолютно всеми вещами, и добиться понимания читателем всей информации, так как тут будет слишком много специфики по Андроиду.
Но в любом случае попробую донести основную идею.
Итак, что это за такой интересный объект, вокруг которого крутится столько вопросов в инете, и нет ответов, а только догадки.
В двух словах – этот объект позволяет вызвать другое приложение из андроида, и получить ответ от него.
Например, вы можете открыть почту и передать в нее все нужные данные.
Давайте начнем с чего-то малого, но не менее интересного. К примеру – попробуем просканировать штрих-код при помощи камеры телефона, но не средствами 1С, а вызовем специальную программу.
Для этого необходимо установить на телефон программу вот эту.
Далее – создаем кнопку в 1С с вот такой функцией:
Процедура ПроверитьВзаимодействие(Команда)
НовВз=Новый ЗапускПриложенияМобильногоУстройства();
НовВз.Действие="com.google.zxing.client.android.SCAN";
Сообщить(НовВз.Запустить(Истина));
ДляКаждогоСтрИзНовВз.ДополнительныеДанныеЦикл
Сообщить(Стр.Ключ+" - "+Стр.Значение);
КонецЦикла;
КонецПроцедуры
Обновляем конфигурацию и нажимаем кнопку. У меня отображается вот такое окно:
Выбираем Сканер штрих-кодов и сканируем что-то, и видим ответ:
В ответ мы получили результат работы, тот что «-1», и получили результаты сканирования, а именно – штрих-код и тип штрих-кода.
Ну как? Интересно? Если да, то давайте будем копать глубже.
Тут нам однозначно поможет справка 1С, или не поможет?
ЗапускПриложенияМобильногоУстройства (MobileDeviceApplicationRun)
Свойства:
Данные (Data)
Действие (Action)
ДополнительныеДанные (AdditionalData)
ИмяКласса (ClassName)
Категория (Category)
Приложение (Package)
Тип (Type)
Методы:
Запустить (Run)
Описание:
Предназначен для запуска внешних приложений.
В отличие от метода ЗапуститьПриложение позволяет передать в приложение параметры.
Доступен только на устройствах под управлением операционной системы Android.
Из справки, нам стало понятно, что работает это все только на Андроид, ну в принципе ничего странного.
Идем дальше. У нас есть определенные свойства и есть один метод.
Давайте разберем некоторые свойства:
Данные – это URIссылка, помните, мы ранее уже говорили про это в вот этой статье. Т.е. если мы хотим запустить браузер, тот тут мы передаем адрес страницы.
Действие – тут мы с вами описывали то, что мы хотим от мобильной платформы. В справке 1С очень скромно про это написали. Но мы вернемся чуть позже.
Категория – это уточняющая информация для описания действия. Например, если это приложение может делать много чего, то вы указываете конкретно что вы хотите. Либо можно запустить приложение по умолчанию, если оно назначено.
На основании этих трех данных система будет искать – что бы запустить для нас. Можно и не заполнять некоторые из них, тогда просто будет выдаваться больше программ для работы с нашим действием.
Приложение - тут мы можем указать какое именно приложение (его идентификатор) мы хотим использовать для наших действий, например - "com.google.android.gm", в этом случае откроется Gmail.
ИмяКласса - указывается в паре с приложением, выудить его можно при декомпиляции программы в манифесте, ну или в мануале, если есть, в случае Gmail - "com.google.android.gm.ComposeActivityGmail".
Если казать только приложение или только имя класса - ничего не произойдет. Их есть смысл указывать только в том случае, если вы понимаете о чем идет речь :) При этом можно не указывать Категорию.
В версии 8.3.5.79 исправлен баг (№30010918):
Описание:
В мобильной платформе у обьекта ЗапускПриложенияМобильногоУстройства при вызове метода Запустить игнорируется свойство Приложение, если не установлено свойство ИмяКласса.
ДополнительныеДанные – это (типо) структура, в которой мы описываем все параметры для передачи нашему приложению. И в ЭТУ ЖЕ структуру возвращается ответ. Тут не стоит забывать про третий параметр, это тип данных, например, в случае работы с фото, или прикрепляя к письму вложения - мы должны указать Uri представление, так как 1С не значет что это такое, то мы указываем путь и третьим параметром указываем тип, например - "Uri".
Метод Запустить – на самом деле тут два метода. Если передаете в параметр Истина, то приложение может вернуть некий код своей работы. Вот как в браузере, если страница не найдена – возвращает код ошибки 404. Если же его переключить в режим Ложь, то он будет работать как индикатор успешного выполнения приложения, т.е. вернет Истину, если же была ошибка, то вернет Ложь.
Что же это все за данные и откуда их брать?
Если в двух словах, то программы на Андроиде могут создавать Намерения (Intent) и обрабатывать их.
Т.е., когда программа написана специальным образом, то при установке она создает ассоциации с некоторыми событиями и их обработкой. В 1С есть хороший аналог – Оповестить() и ОбработкаОповещения(), но только в случае 1С – это локально, а в случае Андроид – глобально.
И ясное дело, что должны быть соответствующие инструкции по работе с ними.
Идем на сайт разработчиков и читаем - https://code.google.com/p/zxing/source/browse/trunk/android/src/com/google/zxing/client/android/Intents.java
Вот это определение доступных режимов. Например, можете попробовать вызвать вот такой экшн (действие) :
"com.google.zxing.client.android.SHARE"
Посмотрите, что будет.
Теперь давайте отправим почту, за основу я взял первую попавшуюся статью:
Первое на что я смотрю:
IntentemailIntent = newIntent(Intent.ACTION_SEND);
Теперь тут надо быть внимательней. Так как вот это Intent.ACTION_SEND сокращение от android.Intent.action.SEND, а 1С не понимает сокращений, так что не попадайтесь на такие детские ошибки.
Поэтому пишет вот так и тестируем.
Процедура ПроверитьВзаимодействие(Команда)
НовВз=Новый ЗапускПриложенияМобильногоУстройства();
НовВз.Действие="android.Intent.action.SEND";
Сообщить(НовВз.Запустить(Истина));
КонецПроцедуры
В ответ мы получим «0», и ничего не произойдет. Почему? Ну так все же очевидно, видь должно быть написано не:
android.Intent.action.SEND
а:
android.intent.action.SEND
Разве не понятно? J
Меняем регистр букв, и, о чудо – у нас открылась куча приложений, которые могут отработать это событие. Давайте уточним поиск, для этого укажем тип, но не тот, который в статье той, так как количество приложений не уменьшится, а вот такой:
НовВз.Тип="message/rfc822";
Теперь нажав кнопку – у нас откроется значительно меньше приложений.
Ну и можем выбрать Gmail.
Теперь давайте заполним что-то, ну, например, тему и тело письма. В том примере это делается вот так:
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "subject of email");
emailIntent.putExtra(Intent.EXTRA_TEXT , "body of email");
А вставить эти данные нам надо в ДополнительныеДанные. А это по сути массив структуры, где есть ключ и значение. И обратите внимание опять на сокращения.
Мы же должны написать вот так:
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.SUBJECT","Тема письма");
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.TEXT","Текст письма");
В итоге – открыв Gmail, там заполнятся эти поля. Кроме этого, если у вас установлен скайп, то можете попробовать это же выполнить с ним.
Итог
1С дала очень мощный механизм работы с ее продуктом. Это по сути реализация намерений из андроида, и пока, увы, 1С может выступать только как инициатор, но начало положено! Делать можно много чего при помощи этих функций, я указал лишь самые простые вещи, что бы показать суть, показав это вашему андроид программисту, вы сможете сэкономить часы, если не дни нахождения общего языка.
Дополнение
Как же без какого-то бонуса. А в качестве бонуса, я предлагаю вам поэкспериментировать с вот такой вот программкой, которую мой товарищ накатал за два часа. Делает она следующее – выводит сообщение, или делает пуш сообщение.
При чем в отличии от вот этой утилиты, которую мы написали ранее, когда еще не было этих функций в 1С, вам не надо запускать никакие сервисы, и вообще этой утилиты видно не будет, только в приложениях, так как она не имеет интерфейса.
Работать с ней вот так:
Процедура ПроверитьВзаимодействие(Команда)
НовВз=Новый ЗапускПриложенияМобильногоУстройства();
НовВз.Действие="com.ditrix.ownaction.SHOW_TOAST"
НовВз.ДополнительныеДанные.Добавить("com.ditrix.ownaction.EXTRAS_MESSAGE","Данные");
Сообщить(НовВз.Запустить(Истина));
Для Каждого Стр ИзНовВз.ДополнительныеДанные Цикл
Сообщить(Стр.Ключ+" - "+Стр.Значение);
КонецЦикла;
КонецПроцедуры
Это для простого сообщения, а вот это действие для пуша:
"com.ditrix.ownaction.SHOW_NOTIFICATION"
При этом вам вернется ответ в виде 3 данных разных типов.
Удачи!
Фабрика знаний
Тут будут писаться примеры реализации тех или иных механизмов.
Как сделать фото (видео) в любом качестве?
Учтите - работает не везде, зависит от приложения, при помощи которого делается фото. У меня на Cyan прошивке - все отрабатывало нормально.
//Тут указываем путь, при чем путь должен быть доступен всем программам, так что временные файлы 1С не подйут
ФайлКартинки = "file:///sdcard/Download/FotoTestFrom1C.bmp";
НовВз = Новый ЗапускПриложенияМобильногоУстройства("android.media.action.IMAGE_CAPTURE");
//Обязательно указываем этот параметр, если его не указать, тогда вам вернется привью файла в низком качестве и находится он будет в параметрах с ключем data.
НовВз.ДополнительныеДанные.Добавить("output",ФайлКартинки,"Uri");
//Если фото не сделано, то ответ будет "0"
Если НовВз.Запустить(Истина) 0 Тогда
//ну а тут уже готовое фото, так что все что хотим, то и делаем.
ЗапуститьПриложение(ФайлКартинки);
Иначе
Сообщить("Фото не сделано!");
КонецЕсли;
Как отправить файл в разные программы? Спасибо Снежане
НовВз = Новый ЗапускПриложенияМобильногоУстройства();
НовВз.Действие = "android.intent.action.SENDTO";
НовВз.Данные = "mailto:test@test.ru";
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.STREAM","file:///storage/emulated/0/Снежана/CDAInfo.txt","Uri");
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.SUBJECT","Тема письма");
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.TEXT","Теекст-текст-текст");
НовВз.Запустить(Истина);
Как отправить файл только по почте? Спасибо Снежане
Должен быть установлен клиент Gmail
НовВз = Новый ЗапускПриложенияМобильногоУстройства();
НовВз.Действие = "android.intent.action.SEND";
НовВз.Данные = "test@test.ru";
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.STREAM","file:///storage/sdcard0/DCIM/Camera/20140829_115820.jpg","Uri");
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.SUBJECT","Тема письма");
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.TEXT","Теекст-текст-текст");
НовВз.Тип = "text/plain";
//чтобы сразу Gmail открывался
НовВз.Приложение = "com.google.android.gm";
НовВз.ИмяКласса = "com.google.android.gm.ComposeActivityGmail";
//
НовВз.Запустить(Истина);
Пример работы с Viber'ом. Спасибо Снежане
//Открывает вайбер
НовВз.Действие = "com.viber.voip.action.CONVERSATION";
//или
НовВз.Действие = "com.viber.voip.action.MESSAGES";
//Открывает список контактов в вайбере
НовВз.Действие = "android.intent.action.CALL_BUTTON";
//открывает диалог с конкретным человеком в вайбере
НовВз.Действие = "android.intent.action.SENDTO";
НовВз.Данные = "smsto:+380965336452";
НовВз.Приложение = "com.viber.voip";
НовВз.ИмяКласса = "com.viber.voip.SystemDialogActivityPublic";
//Отправить текст по вайберу, предлагает выбрать, кому отправлять, потом сразу отправляет
НовВз.Действие = "android.intent.action.SEND";
НовВз.Приложение = "com.viber.voip";
НовВз.ИмяКласса = "com.viber.voip.WelcomeShareActivity";
НовВз.Тип = "text/plain";
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.TEXT","ТЕКСТ: Теекст-текст-текст");
//Отправить фото по вайберу, предлагает выбрать, кому отправлять
НовВз.Действие = "android.intent.action.SEND";
НовВз.Приложение = "com.viber.voip";
НовВз.ИмяКласса = "com.viber.voip.WelcomeShareActivity";
НовВз.Тип = "image/jpeg";
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.STREAM","file:///storage/emulated/0/DCIM/100ANDRO/DSC_0001.jpg","Uri");
//Открыть контакт в вайбере
НовВз.Действие = "android.intent.action.VIEW";
НовВз.Данные = "tel:+380965336452";
НовВз.Приложение = "com.viber.voip";
НовВз.ИмяКласса = "com.viber.voip.WelcomeShareActivity";
Еще можно открыть контакты устройства и выбрать конкретный контакт, но вот проблема в том, что получаем в итоге Uri-ссылку на контакт, а 1С с ней ничего сделать не может... а хотелось бы данные вытянуть.
Написали в пожелания создание Локального ключа контакта на основании Uri-ссылки.
Спасибо Снежане
// Выбор контакта
Запуск = Новый ЗапускПриложенияМобильногоУстройства();
Запуск.Действие = "android.intent.action.PICK";
Запуск.Тип = "vnd.android.cursor.dir/contact";
Запуск.Запустить(Истина);
Строка = Запуск.Данные;
//Открытие по ссылке
Запуск = Новый ЗапускПриложенияМобильногоУстройства();
Запуск.Действие = "android.intent.action.VIEW";
Запуск.Данные = Строка;
Запуск.Запустить(Истина);
Как правильно указывать путь к файлам? Спасибо Вадиму
Когда мы сохраняем файл средствами моб платформы через
КаталогВременныхФайлов() + "sticker.pdf"
То этот файл недоступен другим приложениям. Можно писать так:
"file:///sdcard/sticker.pdf"
но теоретически карты памяти может и не быть. Поэтому есть более методически правильный метод:
КаталогДокументов() + "sticker.pdf";
Как выбрать файл нужного типа, при помощи менеджера файлов?
НовВз = Новый ЗапускПриложенияМобильногоУстройства();
НовВз.Действие = "android.intent.action.GET_CONTENT";
//Указываем тип искомых файлов, нас интересует только фото
НовВз.Тип = "image/*"; //"file/*"; //"*/*"
//Говорим что интересуют только локальные данные, а не облачные
НовВз.ДополнительныеДанные.Добавить("android.intent.extra.LOCAL_ONLY",Истина);
РезультатРаботы = НовВз.Запустить(Истина);
Если НЕ РезультатРаботы Тогда
Сообщить("Файл не выбран!");
Возврат
КонецЕсли;
ПутьКФайлу = НовВз.Данные;
Как обрезать выбранное фото?
НовВз = Новый ЗапускПриложенияМобильногоУстройства("com.android.camera.action.CROP", ПутьКФайлу);
НовВз.Тип = "image/*";
НовВз.ДополнительныеДанные.Добавить("return-data", true);
РезультатРаботы = НовВз.Запустить(Истина);
Если НЕ РезультатРаботы Тогда
Сообщить("Фото не обработано!");
Возврат
КонецЕсли;
ФайлВр = ПолучитьИмяВременногоФайла("jpg");
НовВз.ДополнительныеДанные.Получить("data").Значение.Записать(ФайлВр); // тут и будет сама картинка, которую можно запихнуть в 1С
ЗапуститьПриложение(ФайлВр);