gifts2017

"Внешнее событие" и мобильная платформа 1С

Опубликовал dewersia dewersia (dewersia) в раздел Программирование - Внешние компоненты

Внешние компоненты в Android для Мобильной Платформы 1С или как вызвать внешнее событие, когда его нет.

Предыстория

В компанию был куплен аппарат CipherLab RS30, ТСД на базе ОС Android 4.4.2 cо встроенным сканером штрихкода. Было решено разработать приложение для работы с этим чудом техники на базе Мобильной Платформы 1С. Для примера была взята конфигурация "Мобильная Касса", в которой была уже реализована работа со штрихсканером, с помощью внешних компонент (Стандартная от 1С, вторая от компании ScanCode).  

После опытов оказалось, что штрихкод считывается во внешнем окне, которое загораживает весь интерфейс, плюс для каждого считывания штрихкода нужно нажимать кнопку для вызова этого окна, что было совершенно неприемлемо. Было принято решение разработать собственную внешнюю компоненту для считывания штрихкода и передачи его в 1С, без дополнительных окон и нажатий лишних кнопок.

И тут началось, оказывается, что в Мобильном Приложение 1С нет предопределенной процедуры ВнешнееСобытие, зато есть объект "ДоставляемыеУведомления", с помощью которого можно отправить локальное сообщение и принять его с помощью обработчика уведомлений. Казалось, что вот оно, решение всех бед, но и тут мы потерпели фиаско, 1С может отправлять и принимать сообщения только от самой себя. После чего была неделя непрерывных поисков решения, информации в интернете не оказалось, а все, на что мы натыкались, говорило о том, что это невозможно.

Пришлось декомпилировать платформу, изучить весь внутренний код, но все попытки заканчивались неудачей. И вот настал день, когда надо было окончательно решить, каким способом организовать работу с этим аппаратом, и мы было уже отказались от идеи внешней компоненты и подумывали запустить всю систему через RDP, как, о чудо, после еще одной отчаянной попытки решение было найдено.

А теперь самое главное.

Ограничения: Данный способ подходит только для приложений, собранных с помощью Конфигурации "Сборщик мобильных приложений", также способ подразумевает небольшое вмешательство в исходные файлы мобильной платформы.

Дано:

1. CipherLab RS30

2. SDK для вашего сканера

3. Сборщик мобильных приложений

4. Сама мобильная платформа

5. Android Studio

А теперь начинается магия:

1. Распаковываем файлы платформы

2. Нас интересует Android\prjandroid-arm\bin\permissions.xml этот файл

Этот файл используется при сборке приложений и добавляет в AndroidManifest разрешения, которые указаны в конфигурации.

3. Нас интересует секция <LocalNotification>, которая добавляется, если установлена отметка Локальные Уведомления в требуемых разрешениях мобильного приложения. По умолчанию она выглядит так.

    <LocalNotification>
        <uses-permission android:name="android.permission.VIBRATE"/>
        <target xpath="/manifest/application" >
            <receiver
                android:name="com.e1c.mobile.LocalNotificationReceiver"
                android:enabled="true" >
            </receiver>
        </target>
    </LocalNotification>

4. Здесь нас интересует секция <receiver>,  com.e1c.mobile.LocalNotificationReceiver является потомком класса BroadcastReceiver, который как раз нам и нужен. Первое, что нам нужно сделать, это добавить атрибут android:exported="true" это позволит принимать сообщения из внешней программы.

5.  Дальше нам нужно добавить фильтр, который будет указывать, какое событие может принять наш receiver, его-то мы и будем передавать из нашей компоненты.

<intent-filter>
       <action android:name="ru.dewersia.barcodeDLL.TRUSTCONNECT" />
</intent-filter>

Теперь наша секция должна выглядеть так

    <LocalNotification>
        <uses-permission android:name="android.permission.VIBRATE"/>
        <target xpath="/manifest/application" >
            <receiver
                android:name="com.e1c.mobile.LocalNotificationReceiver"
                android:enabled="true" android:exported="true">

                <intent-filter>
                    <action android:name=" ru.dewersia.barcodeDLL.TRUSTCONNECT " />
                </intent-filter>

            </receiver>
        </target>
    </LocalNotification>

6. Теперь запаковываем все обратно, наша мобильная платформа готова.

7. Дальше можно приступать и к разработке в 1С, создаем обработчик локальных уведомлений

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Вставить содержимое обработчика.
    Параметр = Неопределено;
    ОП = Новый ОписаниеОповещения("КрутойОбработчик",ЭтаФорма,Параметр);
    ДоставляемыеУведомления.ПодключитьОбработчикУведомлений(ОП);
    былЗапуск = ЛОЖЬ;
КонецПроцедуры


&НаКлиенте
Процедура КрутойОбработчик(Уведомление,Локальное,Показано,ДопПараметры) Экспорт
    Сообщить(Уведомление.Текст);
    ШтрихКод = Уведомление.Текст;
КонецПроцедуры

8. Отправка сообщений в Android выглядит так:

    private void sendMessage(String title,String text) {
        Intent intent = new Intent();
        intent.setAction("ru.dewersia.barcodeDLL.TRUSTCONNECT");
        intent.putExtra("text", text); //Основной текст сообщения
        intent.putExtra("base", "");
        intent.putExtra("title", title); //Будем использовать для определения действия
        sendBroadcast(intent);
    }

В параметры передаваемого сообщения добавляется значение с ключом base

 intent.putExtra("base", "");

Уважаемый DitriX в одном из своих комментариев писал, что туда должен передаваться ID базы, но на все попытки передать туда какое-либо значение из всех возможных, в сообщении появлялась надпись "Сообщение для неизвестной базы", при передаче пустого значения все отлично работает.

Всем большое спасибо за внимание, надеюсь, эта информация будет кому-нибудь полезна.

В результате был написан внешний сервис, работающий в фоновом режиме, который получает штрихкод со сканера и передает его в 1С.

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
BarcodeService
.zip 47,01Mb
11.09.16
14
.zip 47,01Mb 14 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Evgeny Goryachev (gorevg) 09.09.16 06:15
Интересно. Сейчас мы тоже пишем мобильное приложение под ТСД. Надо иметь ввиду. Спасибо!
2. Evgeny Goryachev (gorevg) 09.09.16 10:25
Возможно ли купить у вас получившийся внешний сервис? или выложите его...
3. bulpi bulpi (bulpi) 09.09.16 12:19
Это здорово и очень полезно. Было бы, вот только "внешний сервис, работающий в фоновом режиме" для Андроида я не напишу :( ибо я просто 1с-ник. И таких миллион.
4. Вова Вишин (Tahallus) 09.09.16 15:54
Это если можно сделать приложение на android которое будет это сообщение отправлять.
А бывает что только активное приложение может работать с оборудованием.
Тогда только потрошить платформу и внедрять код.
5. dewersia dewersia (dewersia) 09.09.16 17:56
(2) gorevg, Добрый день, в воскресенье выложу сервис. Не стал этого делать так как достаточно специфичное решение под конкретный аппарат, под каждый аппарат придется его переделывать, использовать свои библиотеки и так далее. Основной задачей было рассказать как можно реализовать вызов внешнего события в Мобильной Платформе.
6. dewersia dewersia (dewersia) 09.09.16 17:58
(3) bulpi, Исходники как уже писал выше, выложу в воскресенье, это как раз и есть сервис работающий в фоновом режиме, 1С запускает сервис, а дальше этот сервис отправляет ей сообщения.
7. dewersia dewersia (dewersia) 09.09.16 18:04
(4) Tahallus, Хм, тогда встает вопрос если это отдельное приложение, которое работает с оборудованием, неужели оно никак не передает данные? А если приложение этого не делает то тогда для чего оно? Такое узкоспециализированное оборудование тогда никак не может быть внедрено в учетную систему компании. Поправьте меня если это не так.
8. Вова Вишин (Tahallus) 10.09.16 20:55
(7) проблема в том что только активное приложение может работать с СШК по serialport. можно сделать отдельное приложение которое будет работать и отправлять сообщение в 1с, но когда оно активно. Это как с аппаратными клавишами, их нажатие может ловить только активное приложение, если конечно прошивка не изменена.
9. Дмитрий Шерстобитов (DitriX) 11.09.16 00:14
Как тут все глубоко ошибаются :)
На счет статьи - таки да, надо отправлять ID, чем это чревато? Создайте две базы в списке и увидите.

Мы (я про фирму ACODE) сделали проще в своих терминалах - у нас не надо нарушать лицензионной соглашение 1С, что делает автор в данной статье :)
Это конечно прикол, я не думаю что реально это будет кто-то проверять, но иди и знай :)

Вопрос номер два - зачем вы выдумывали велосипед? Видь есть Acode Tools, которые не только умею работать с блютуз сканерами, но и умеют еще кучу всего, из без танцев с бубном, как сделали вы сейчас.

З.Ы. Велосипед это хорошо, но все же - вы просто не знали про утилиты, или они вам чем-то не подошли?
10. dewersia dewersia (dewersia) 11.09.16 11:24
(9) DitriX, Добрый день, насчет нескольких баз, в списке несколько баз доступно только в платформе для разработчика, которую кстати нельзя использовать для конечного приложения, поэтому в какой роли выступает ID для отдельного приложения не понятно. Я кстати описал это ограничение в статье. Ваши утилиты это круто, мы их тоже изучали, но я так понял считывание штрих кода все равно происходит в отдельном окне, а не внешним событием, что нас не устраивало. По поводу вмешательства в платформу, это спорный вопрос, ведь исходный код платформы не изменен, изменены только лишь разрешения, которые кстати говоря определяет сам разработчик.

По поводу сканеров, у нас СШК встроенный и в его настройках можно выбрать не эмуляцию клавиатуры, а передачу данных BroadCast сообщением, для него есть SDK под андроид, что и дало возможность использование такого метода, с блютуз сканерами боюсь так действительно не получится, хотя наверное и тут все зависит от конкретной модели и ее возможностей.

Ну и опять же я не пытался привязаться к конкретной задаче, просто работа с торговым и складским оборудованием это наилучший пример. Я хотел лишь показать как можно вызвать пресловутое внешнее событие из внешней компоненты или любого другого приложения на андроид.
11. dewersia dewersia (dewersia) 11.09.16 11:37
(8) Tahallus, Тут согласен, но это как раз ограничение аппаратных средств, тут надо смотреть, может у производителя есть библиотеки для работы с этим аппаратом, изучать их возможности и если это становится не возможным тогда решать нужен вообще такой аппарат или нет, хотя я бы сказал что нет ничего не возможного, я не отношусь к гуру android программистов, но если бы у меня стояла такая задача я бы копал в сторону сервиса, который бы перехватывал нажатие клавиш, думаю что это вполне возможно. А ели можно перехватить нажатие клавиш тогда их обработка и передача это дело техники.
12. dewersia dewersia (dewersia) 11.09.16 11:38
Как и обещал, исходники сервиса разместил.
13. Дмитрий Шерстобитов (DitriX) 12.09.16 00:13
(10) не смотрели вы утилиты, так как там именно через уведомления, неужели вы думали, что мы выпустим такой бред - сканирование в активное поле?
Мало того, еще с 8.3.4, где не было уведомлений - мы эмулировали через смс :) И даже в нескольких релизах 8.3.х - был баг с уведомлениями, они тупо не работали, так что при тестах - надо это учитывать, но мы выключивались тем, что было резервное - смс. Так что у нас там немерянно приколов было.

А про утилиты - всеравно обратите внимание, ибо там куча функций, которые точно нужны на ТСД :)

На счет сканера штрихкода - не понял до конца, наши утилиты поддерживают все сканеры штрихкодов, которые можно подключить по блютузу в SPP режиме, т.е. не в режиме эмуляции. И для этого не надо ковырять ничего.
В вашем случае - я так понял что у вас именно тсд на андроид. Ну тут да, мы для своих тоже отдельные модули пишем, но они имеют обратную совместимость и таки опять - без ковыряния манифестов :)

Ну в целом - да, статья ценная для тех, кому потребуется аналогичное решение проблем. :)
Теперь будет куда отправлять народ с аналогичными вопросами :)
14. dewersia dewersia (dewersia) 12.09.16 06:06
(13) DitriX, Тогда примите мои извинения, значит что-то я упустил. Мне почему-то показалось что сканирование происходит в отдельном окне. Правда один из вариантов, который я еще вижу это push- уведомления ), для которых можно поднять свой сервер и гонять их через него, а что делать если нет соединения с интернет и мобильной связи? Я конечно понимаю, что сейчас это звучит дико, но все же бывает всякое, как тогда быть?
15. Александр Шакмаев (shakmaev) 12.09.16 10:48
(9) DitriX, на сколько я понимаю, ваше решение - это решение только для ваших терминалов. Например, Chainway 2D Soft без SDK не будет ничего слать, кроме как Keyboard Emulator.
В случае с параметром base, Дмитрий прав, 2 и более базы будут работать некорректно, но это не проблема.

Чтобы подставить значение base, можно при старте системы прочитать его из файла bases.v8i, и передать интент в сервис, например.
Вот так выглядит список файлов:
https://yadi.sk/i/a-sooEt8v44tv
Вот так читать например ПриОткрытии:
/data/data/"+ПолныйИД+"/files/1C/1cem/ibases.v8i
16. dewersia dewersia (dewersia) 12.09.16 19:27
(15) shakmaev, Добрый день, большое спасибо за подсказку по поводу ID. Я до него так и не докопался, да и в моем случае мне это было не нужно по крайне мере в текущей задаче.
17. Дмитрий Шерстобитов (DitriX) 14.09.16 02:17
(14) нет, опять не верно поняли, у нас механизм работает так же, как и вы свой описали, только мы дергаем строенны в 1с бродкасты, а вы их перименовываете.
Так что никаких пушей и интрнетов не надо :)

(15) я же вверху исправился, и сказал, что да - это для наших терминалов, но утилиты работают с любыми блютух сканерами по такому же принципу, т.е. аля "внещнее событие", и вот утилиты идут под все устройства. Конечно, в данном случае на ТСД они работать не будут :)

Так ID вы не прочитаете, у вас 2 базы, и все. Какой ID брать? Правильней - получать путь временного каталога и из него вырезать конкретный ID :)
18. vasek (iliabvf) 21.09.16 15:56
(17) DitriX, как то пытался получить у вас информацию как работают утилиты, как подключить другой ТСД (не ACODE), предлагал доработать силами нашей команды взамен исходного когда, но вы так и не захотели ничего давать, в результате мы тоже начали разрабатывать свою утилиту. А тут человек дал дельное решение, спасибо ему.
19. roman kalynchuk (romak78) 10.10.16 17:59
подскажите com.cipherlab.barcode где взять, у меня только com.cipherlab.clbarcodeservice есть в приложениях ?
20. Дмитрий Шерстобитов (DitriX) 15.10.16 20:02
(18) я ж не говорю что это плохо, это выход из ситуации. И мы никогда не скрывали используемой технологии, даже в коде вы могли наблюдать названия соответствующие (SMS и GCM), другое дело, что мы не разрабатываем ни для кого, и не потому что мы плохие или хорошие, а потому что с каждым релизом вылазят новые чудеса. И ваш бы комментарий мог звучать сейчас не так. что мы ничего не делаем, а так, что мы сделали и нифига теерь не работает :)

Тем более что мы сейчас вообще переходим на внешние компоненты, так как такой способ нарушает лицензию 1с, и в более менее крупных внедрениях - руководство просто может не пойти на это, а самое страшное - если такое сделать и их не предупредить. Это чисто медвежья услуга.
Поэтому еще раз повторюсь - механизм рабочий, конечно требует более детального подхода и изучения, не без этого. НО! Это подойдет для лавочников или компаний, которые готовы сэкономить, но при этом на свой страх нарушить лицензии.

Выбирайте сами. Но я считаю важным предупредить про это, иначе поплнится в ряду тех, кто "не переваривает" мобильную 1С.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа