1с мобильное приложение сохранить файл
Предыстория
Еще во времена «1С:Предприятия» версии 8.0 (и последующих версий) существовал программный продукт «Расширение для карманных компьютеров». Расширение позволяло создавать продукты только для ОС Windows Mobile, Windows CE и т.д. Продукт обладал собственным конфигуратором, и сервером, и поддерживался вплоть до выпуска «1С:Предприятия» версии 8.3. Последняя версия расширения (8.2.9) была выпущена в октябре 2013 года, а полная поддержка прекратилась 1 января 2015 года.
Расширение имело ограниченное применение даже во времена расцвета коммуникаторов на Windows Mobile, а уход таких устройств с мобильного рынка явно не добавил популярности этому программному продукту. Устройства на iOS и Android заняли практически весь рынок мобильных устройств, и стало очевидно, что поддержка этих ОС является одним из ключевых моментов для системы, которая должна эксплуатироваться в современном мобильном мире. Также казалось очевидным, что основной подход существующей платформы «1С:Предприятие» должен использоваться и на мобильных устройствах: прикладной разработчик должен в первую очередь думать о решении прикладных задач, а во вторую — о том, какие возможности используемой ОС ему задействовать для решения этих задач. Другими словами, нужен инструмент, который изолирует прикладного разработчика от особенностей конкретных мобильных ОС и инструмента разработки.
Мобильная платформа
- она должна поддерживать современные популярные мобильные операционные системы и устройства под их управлением. В первую очередь это ОС iOS фирмы Apple и Android компании Google.
- эта система должна позволять использовать разработанные приложения в стиле, принятом на современных мобильных устройствах. В частности, интерфейс должен опираться на ручное управление (в буквальном смысле этого слова) с использованием сенсорных экранов.
- система должна обеспечивать единообразный программный интерфейс для реализации различных специфических механизмов, вне зависимости от используемой мобильной ОС.
- разработчик должен использовать тот же инструмент и те же подходы к разработке, что и при разработке приложений для «обычного» компьютера.
- прикладной разработчик должен разрабатывать прикладное решение в привычной среде разработки, по возможности используя единый код для настольной и мобильной систем.
- интерфейс прикладного решения, работающего на мобильном устройстве, должен быть аналогичен для различных платформ и в целом однозначно узнаваем.
Начиная с версии мобильной платформы 8.3.7 стала доступна и отладка приложения непосредственно на мобильном устройстве (подробнее об этом ниже).
- мобильное приложение может быть составной и неотъемлемой частью существующей информационной системы предприятия. Мобильное приложение будет предоставлять интерфейс и другие возможности (включая обмен данными), «заточенные» под возможности существующей информационной системы. В этом случае мобильное приложение очень плотно связано с «обычной» информационной системой и не может эксплуатироваться в отрыве от нее.
- мобильное приложение выполняет специфические задачи, которые практически никак не связаны с информационной системой предприятия. Существует лишь минимальный набор данных, которыми обмениваются мобильное приложение и информационная система. В этом случае, скорее всего, мобильное приложение будет выполнять обмен по некоторому стандартизированному протоколу, что делает возможным применение этого мобильного приложения в совершенно различных случаях и ситуациях.
Устройство мобильной платформы
- Собственно мобильная платформа — мобильная часть фреймворка «1С:Предприятие». Она бывает обычной (которая используется во время сборки приложения для публикации в магазине приложений) и мобильной платформой разработчика, которая используется (сюрприз) во время разработки мобильного приложения.
- Мобильная конфигурация — это конфигурация системы программ «1С:Предприятие», записанная в виде XML-файла.
- Комбинация мобильной платформы и мобильной конфигурации дает мобильное приложение.
- Сборщик мобильных приложений — специализированное прикладное решение, которое умеет сделать из мобильной платформы, конфигурации, заставок, иконок и прочих компонентов, готовый файл мобильного приложения, который можно загрузить в магазины Apple AppStore, Google Play, Windows Phone Apps / Windows Apps.
Немного о платформе разработчика
Что умеет?
Как выглядит?
Графический интерфейс мобильной платформы – отдельная тема. В 1С:Предприятии, как известно, интерфейс описывается декларативно. Это, с одной стороны, накладывает некоторые ограничения на разработку UI (например, отсутствует возможность попиксельного позиционирования), но, с другой стороны, позволяет платформе единообразно отрисовывать интерфейс на экранах разного размера, в тонком и веб-клиенте. Этого же принципа мы старались придерживаться и в мобильной платформе. Насколько хорошо нам это удалось? Попробуем разобраться.
В первых версиях мобильной платформы (до 8.3.5 включительно) графический интерфейс приложений выглядел весьма привычно для искушенных пользователей 1С; фактически он переносил знакомый по «десктопным» версиям 1С интерфейс в мобильный мир. Но с точки зрения пользователей, ранее с 1С не знакомых, интерфейс выглядел несколько архаичным.
Учтя замечания и пожелания, мы коренным образом пересмотрели свой подход к мобильному интерфейсу в версии 8.3.6. Можно сказать, что мы сделали совершенно новый мобильный интерфейс для наших приложений. Он имеет много общего с нашим интерфейсом «Такси». Модель разработки для разработчиков мобильных приложений соответствует модели разработки в «Такси». При этом мобильный интерфейс полностью соответствует принятым в мобильных приложениях подходам к дизайну и UX. Интерфейс полностью учитывает специфику мобильного мира: небольшой размер экрана (а значит, оформление графических элементов должно стать более аскетичным – без теней, градиентов), есть поддержка пальцевых жестов и т.д. Интересный факт: новый механизм платформы, отвечающий за размещение элементов в форме (layouter) оказался настолько удачным и своевременным для мобильной платформы, что был выпущен в ней раньше (в версии 8.3.6) чем в платформе для ПК (в версии 8.3.7), для которой он в первую очередь предназначался.
На картинке можно увидеть, как поменялся наш интерфейс.
Приложение «Управление небольшой фирмой» на версии мобильной платформы 8.3.5:
Оно же на версии 8.3.6:
А вот так выглядит интерфейс мобильной платформы вживую:
Сборщик — и что это за зверь?
- Загружаем версию мобильной платформы 1С, на которой будем собирать приложение
- Загружаем конфигурацию, из которой будем собирать мобильное приложение
- Создаем мобильное приложение, в котором указываем, для каких платформ (Android, iOS, Windows) надо выполнять сборку, какую конфигурацию и платформу следует использовать (в частности, указать, какой сертификат для сборки под iOS использовать в случае, если приложение работает с PUSH-уведомлениями).
- Выполняем «одним кликом» сборку мобильного приложения под все выбранные платформы
- «Другим кликом» отправляем собранные мобильные приложения в магазины приложений (если это приложение для iOS или Android). В магазины Windows Apps / Windows Phone Apps приложение нужно загружать вручную, т.к. Microsoft пока не предоставляет API для размещения приложения в магазине.
Приложения на мобильной платформе
Сама фирма «1С» выпускает на мобильной платформе ряд приложений, являющихся мобильными клиентами серверных приложений 1С (1С:Документооборот, 1С:Управление Небольшой Фирмой и т.д.). Эти приложения реализуют некоторое подмножество функциональности «обычных» клиентов. В случае мобильной версии «1С:Управление Небольшой Фирмой» функциональности достаточно для полноценного использования программы, и мы часто видели ситуацию, когда клиентам для ведения бизнеса достаточно мобильной версии приложения.
Наши партнеры используют мобильную платформу как для разработки тиражных мобильных приложений, распространяемых через магазины приложений, так и для заказных приложений, созданных по запросам конкретных клиентов. Среди тиражных приложений встречаются приложения, которые используют не 1С-ный back-end в качестве центрального хранилища данных.
Среди мобильных приложений, созданных по заказу клиентов, можно упомянуть мобильный клиент для «1С:Управления Производственным Предприятием», созданный по заказу крупного машиностроительного холдинга. Около ста сотрудников холдинга используют мобильное приложение в горячих цехах, где по соображениям техники безопасности поставить стационарные компьютеры невозможно. Встроенная камера мобильного устройства используется для чтения штрих-кодов изделий и поиска их в справочнике номенклатур, мобильное приложение позволяет понять, на каком этапе технологической цепочки находится данное изделие, отметить прохождение изделием очередной операции и т.п.
Заключение
В этой статье я попробую ответить на этот вопрос.
А также посмотрим, как сканировать камерой, как отправлять почту и как делать фото (или видео и в любом качестве), причем не встроенными средствами 1С.
Добрый день.
Наконец у меня дошли руки до разбора нового функционала по мобильной платформе.
В частности, как вы поняли из заголовка статьи – речь пойдет о таком новом объекте, как ЗапускПриложенияМобильногоУстройства .
К сожалению, я не смогу в статье поделиться абсолютно всеми вещами, и добиться понимания читателем всей информации, так как тут будет слишком много специфики по Андроиду .
Но в любом случае попробую донести основную идею.
В двух словах – этот объект позволяет вызвать другое приложение из андроида , и получить ответ от него.
Например, вы можете открыть почту и передать в нее все нужные данные.
Давайте начнем с чего-то малого, но не менее интересного. К примеру – попробуем просканировать штрих-код при помощи камеры телефона, но не средствами 1С, а вызовем специальную программу.
Для этого необходимо установить на телефон программу Далее – создаем кнопку в 1С с вот такой функцией:
Обновляем конфигурацию и нажимаем кнопку. У меня отображается вот такое окно:
Выбираем Сканер штрих-кодов и сканируем что-то, и видим ответ:
В ответ мы получили результат работы, тот что «-1», и получили результаты сканирования, а именно – штрих-код и тип штрих-кода .
Ну как? Интересно? Если да, то давайте будем копать глубже.
Тут нам однозначно поможет справка 1С, или не поможет?
ЗапускПриложенияМобильногоУстройства ( MobileDeviceApplicationRun )
Свойства:
Данные ( Data )
Действие ( Action )
ДополнительныеДанные ( AdditionalData )
ИмяКласса ( ClassName )
Категория ( Category )
Приложение ( Package )
Тип ( Type )
Методы:
Описание:
Предназначен для запуска внешних приложений.
В отличие от метода ЗапуститьПриложение позволяет передать в приложение параметры.
Доступен только на устройствах под управлением операционной системы Android .
Из справки, нам стало понятно, что работает это все только на Андроид , ну в принципе ничего странного.
Идем дальше. У нас есть определенные свойства и есть один метод.
Давайте разберем некоторые свойства:
Данные – это URI ссылка, помните, мы ранее уже говорили про это в вот этой статье. Т.е. если мы хотим запустить браузер, тот тут мы передаем адрес страницы.
Действие – тут мы с вами описывали то, что мы хотим от мобильной платформы. В справке 1С очень скромно про это написали. Но мы вернемся чуть позже.
Категория – это уточняющая информация для описания действия. Например, если это приложение может делать много чего, то вы указываете конкретно что вы хотите. Либо можно запустить приложение по умолчанию, если оно назначено.
На основании этих трех данных система будет искать – что бы запустить для нас. Можно и не заполнять некоторые из них, тогда просто будет выдаваться больше программ для работы с нашим действием.
Приложение - тут мы можем указать какое именно приложение (его идентификатор) мы хотим использовать для наших действий, например - "com.google.android.gm" , в этом случае откроется Gmail.
ИмяКласса - указывается в паре с приложением, выудить его можно при декомпиляции программы в манифесте, ну или в мануале, если есть, в случае Gmail - "com.google.android.gm.ComposeActivityGmail" .
Если казать только приложение или только имя класса - ничего не произойдет. Их есть смысл указывать только в том случае, если вы понимаете о чем идет речь :) При этом можно не указывать Категорию.
В мобильной платформе у обьекта ЗапускПриложенияМобильногоУстройства при вызове метода Запустить игнорируется свойство Приложение, если не установлено свойство ИмяКласса.
ДополнительныеДанные – это ( типо ) структура, в которой мы описываем все параметры для передачи нашему приложению. И в ЭТУ ЖЕ структуру возвращается ответ. Тут не стоит забывать про третий параметр, это тип данных, например, в случае работы с фото, или прикрепляя к письму вложения - мы должны указать Uri представление, так как 1С не значет что это такое, то мы указываем путь и третьим параметром указываем тип, например - "Uri".
Метод Запустить – на самом деле тут два метода. Если передаете в параметр Истина, то приложение может вернуть некий код своей работы. Вот как в браузере, если страница не найдена – возвращает код ошибки 404. Если же его переключить в режим Ложь, то он будет работать как индикатор успешного выполнения приложения, т.е. вернет Истину, если же была ошибка, то вернет Ложь.
Что же это все за данные и откуда их брать?
Если в двух словах, то программы на Андроиде могут создавать Намерения ( Intent ) и обрабатывать их.
Т.е., когда программа написана специальным образом, то при установке она создает ассоциации с некоторыми событиями и их обработкой. В 1С есть хороший аналог – Оповестить( ) и ОбработкаОповещения (), но только в случае 1С – это локально, а в случае Андроид – глобально.
И ясное дело, что должны быть соответствующие инструкции по работе с ними.
Вот это определение доступных режимов. Например, можете попробовать вызвать вот такой экшн (действие ) :
Посмотрите, что будет.
Теперь давайте отправим почту, за основу я взял первую попавшуюся статью:
Первое на что я смотрю:
Теперь тут надо быть внимательней. Так как вот это Intent . ACTION _ SEND сокращение от android.Intent.action.SEND , а 1С не понимает сокращений, так что не попадайтесь на такие детские ошибки.
Поэтому пишет вот так и тестируем.
В ответ мы получим «0», и ничего не произойдет. Почему? Ну так все же очевидно, видь должно быть написано не:
android . intent . action . SEND
Разве не понятно? J
Меняем регистр букв, и, о чудо – у нас открылась куча приложений, которые могут отработать это событие. Давайте уточним поиск, для этого укажем тип, но не тот, который в статье той, так как количество приложений не уменьшится, а вот такой:
Теперь нажав кнопку – у нас откроется значительно меньше приложений.
Ну и можем выбрать 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С, вам не надо запускать никакие сервисы, и вообще этой утилиты видно не будет, только в приложениях, так как она не имеет интерфейса.
Работать с ней вот так:
При этом вам вернется ответ в виде 3 данных разных типов.
Удачи!
Фабрика знаний
Тут будут писаться примеры реализации тех или иных механизмов.
Как сделать фото (видео) в любом качестве?
Учтите - работает не везде, зависит от приложения, при помощи которого делается фото. У меня на Cyan прошивке - все отрабатывало нормально.
Должен быть установлен клиент Gmail
Пример работы с Viber'ом. Спасибо Снежане
Еще можно открыть контакты устройства и выбрать конкретный контакт, но вот проблема в том, что получаем в итоге Uri-ссылку на контакт, а 1С с ней ничего сделать не может. а хотелось бы данные вытянуть.
Написали в пожелания создание Локального ключа контакта на основании Uri-ссылки.
Спасибо Снежане
Как правильно указывать путь к файлам? Спасибо Вадиму
Когда мы сохраняем файл средствами моб платформы через
То этот файл недоступен другим приложениям. Можно писать так:
но теоретически карты памяти может и не быть. Поэтому есть более методически правильный метод:
Как выбрать файл нужного типа, при помощи менеджера файлов?
Он может быть или в виде content или в виде file, тогда все норм. Однако, если вернется провайдер, например, content://com.android.providers.media.documents/. то это фигня.
1С с таким работать не сможет. Все зависит от прогаммы, при помощи которой делается выбор. К примеру - если использовать графу "Недавние", то может вернуться провайдет.
(45) Подскажите пжста, что указывать в (41) под переменной ИмяФайла? полностью путь к ПК или как?
И нужно ли связывать с ПК и создавать сетевую папку в ES проводнике?
Вот его и скачать через несколько попыток.
Как только я не пытался записывать, результат один = ошибка
(5) Сервер 1с на windows, этим можно воспользоваться ))
а потом копируйте в папку \\192.168.1.33\111
т.е. из временного каталога кластера 1с на сервере - копируем в сетевую папку.
КопироватьФайл(, )
Предварительно проверьте, что пользователю, под кем запускается сервер 1с (кластер 1с), доступна запись в эту папку.
(5) В том то и дело что сервера нет который сможет это записать. По сути я записываю произвольный текст ZPL команды на сетевой принтер этикеток.
А без мобильного приложения, через тонкий клиент получается распечатать на сетевом принтере? Ответ должен быть, да.
Тогда код печати нужно разместить в серверной процедуре. И к ней обращаться с клиентов.
(9) Да, локально проблем нет
Размещать код на сервере не обязательно, да и если печать сделать на сервере то все равно будет ошибка Файл не обнаружен '\\192.168.1.33\111\1.txt
(12)
Предварительно проверьте, что пользователю, под кем запускается сервер 1с (кластер 1с), доступна запись в эту папку.
Нужно дать права логину, под кем запускается кластер 1с.
(15) Выступая в роли драйвера принтера для Android, PrintConnect упрощает разработчикам задачу добавления этикетки и печати чеков в их решениях для Android.
PrintConnect решает задачу обнаружения и подключения принтеров Zebra Link-OS через Bluetooth или WLAN, снижая, таким образом, количество кода в вашем приложении. PrintConnect поддерживает нашу функцию Print Touch, делая процесс подключения еще проще!
(16) Это не подходит, во первых другой принтер, во вторых печать идет из 1с. Мне просто нужно чтобы мобильное приложение смогло записать текст в расшаринную папку по сети. SMB клиенты не подходят, так как у них синхронизация не в реалтайм идет.
(1) Создай функцию, которая будет выполнятся на сервере 1с.
И запускай её с клиента любого. Для начала с тонкого клиента, если ошибок не будет - с мобильного.
(17) Зачем писать одно и тоже несколько раз. Я же говорю ошибок нигде нет, везде все работает, не работает только с мобильного приложения
Возможно ли запись напрямую проверить легко. Открыть папку через диалог. Если получится значит должно работать и у вас нет прав.
(21) к тому что с версии 8.3.10 кажись появился диалог работы с ФС, а вот работает ли он с сетевыми ресурсами мне неизвестно! Проверим эту теорию можно будет говорить, можно ли решить вопрос напрямую или придется использовать костыли!
(24) значит в (4) вам дали исчерпывающий ответ.
Также могу вам посоветовать написать в поддержку в 1С, чтобы возможно они реализовали данный функционал через платформу!
Иначе используйте виндоус на телефоне.
(26) с условием в (15) работать не будет, какой ответ вам еще нужен?
Не выполняя (15) есть еще вариант написать компоненту, которая выполнит данную операцию.
(28) Я в курсе что работать не будет. Просто отвечаю на вопросы. Просто не понимаю зачем их все повторяют, выше же все уже написано.
А Вы уверены что у Android используется обратный слеш ("\"), а не прямой ("/")? Он же вроде корнями к Unix восходит. И про передачу на сервер в виде двоичных данных дело говорят, во многих случаях это удобнее, чем морочиться с доступом отдельных пользователей к файловой системе.
(30) Со слешами уже попробовал по разному, и в разном направлении и в разном количестве.
Сервер и двоичные данные там не нужны, если он там будет то и не нужно будет и мобильное приложение
(32) А сетевому ресурсу другого компа там что делать? Ну я посмотрел в эту папку ничего там вроде нет вида ip другого компа, папок конечно много, просто полистал
(33) логика Linux-подобных систем говорит, что любой сетевой ресурс или дисковый раздел следует отобразить как вложенный каталог корневого раздела.
Как вариант, если ES Проводник этого не делает, попытаться смонтировать сетевую папку без него. Вероятно так же, что ES Проводник все-таки что-то монтирует, но не в традиционные места.
(34)Не получилось найти приложение которое бы смонтировало расшаренную папку на устройство. То что пишут либо 2011 года либо приложений нет в маркете, а ссылки не рабочие
в яндексе: android mount smb
То что по ссылке я уже видел, для этого нужно заводить отдельную большую тему что бы проделать то что там написано. Также там как писал выше используют CifsManager которой либо нет либо я не знаю где найти, а то что было в виде нее просто не устанавливается на устройство
Да я вот и себе присматриваю такое приложение, а то надо бы)
Только еще бы найти откуда выкачать, чтоб не было вирусни всякой
Если кому нужно, можно сделать копирование файла по сети через ES Проводник:
В принципе, можно попробовать и другие файловые менеджеры с передачей по LAN. Тогда надо поменять Приложение и ИмяКласса .
Можете помочь с объяснением данного кода?
Мне нужно сохранить файл ххх.txt с андроида в сетевую папку testfolder и обратно получать?
Установил приложение, пытался скопировать, не получается
Напиши если что-то получиться
ТСД на андройде, пишем конфигурацию на 1С моб версии, после считывания необходимо передать файл на 1С 7.7 для загрузки.
(58) Восьмерка имелось ввиду просто база для сервисов. Ну если совсем не хотят ее даже видеть), то можно на IIS сделать прослойку. Отправлять на него, а IIS уже тогда пусть пишет файлик по сети в нужно место. А семерка уже будет этот файлик забирать и обрабатывать.
(51) Это методы именно приложения ES Проводник. Методы можно смотреть еще через просмотрщик манифеста
(51) Если не получается через это приложение, можно попробовать какой-то другой проводник.
Надо только сначала проверить, что у него есть работа с LAN, а потом проверить в манефесте, есть ли обработчик интента "android.intent.action.SEND"
Методы SMBSync2 используешь?
Или такой вариант начинает работать?
(64) В приложении настраиваешь синхронизацию папки.
А в 1С, сохраняешь файл в этот каталог и выполняешь код:
(65) Синхронизация сразу по событию происходит или с какой-то задержкой? В моем случае нужно было отправлять код на порт принтера, сразу нужно было чтобы печатал.
Архив можно сохранить не только на самом устройстве, но и на сервисе Яндекс.Диск. Для этого надо указать параметры авторизации на сервисе. По гиперссылке можно открыть страницу сервиса и зарегистрироваться в нем.
Восстановить данные можно как с устройства, так и непосредственно с сервиса Яндекс.Диск. Перед восстановлением данных задается вопрос об очистке данных приложения. Также пользователь уведомляется об успешном восстановлении данных из архива.
Использование сервисов Гугл.Диск и iCloud записаны, как пожелания к развитию платформы. Использование этих сервисов требует использования ключей разработчика и включения разрешения использования в приложениях.
Возможность работы с вложенными файлами почтовых клиентов также записаны как пожелания к развитию мобильной платформы.
Сразу скажу что несмотря на громкое, как кому-то могло показаться, название статьи — тут не будет никакого прям уж совсем хардкора. А также несмотря на то что реверсинг чаще всего связывается с информационной безопасностью — здесь опять же ничего такого не будет, ибо никаких защит (за исключением небольшой минификации) обходить не было необходимости. Нет их. Мобильная 1с бесплатный продукт в который не встроено никаких проверок, защит и платных функций.
Так что обращаюсь к тем кто надеется увидеть применение деобфускаторов, использование Frida/Xposed, другого хитрого софта — ничего интересного вы для себя не найдете. Тут мы просто будем использовать apktool, baksmali, apksigner, adb, jadx, консоль, текстовый редактор, javac, d8 и все.
Также хочу заранее разочаровать тех кто ждал глубокий разбор платформы, или ее сильную модификацию. Будут внесены только небольшие правки буквально в несколько файлов, и собственно даже эти несколько файлов я не разбирал досконально, все по верхам.
Немного расскажу с чего мне вообще вдруг пришла идея как-то влезать в работу мобилки на 1с. На данный момент я вот уже скоро год как занимаюсь нативной разработкой под андроид, но до этого я проработал 4 года 1с программистом, причем последние года полтора мы часто работали именно с мобильной платформой. Несмотря на то что основные потребности она удовлетворяла, было у нее так же и очень много минусов (помимо языка программирования). В частности нельзя было по-человечески встроить какую нибудь внешнюю библиотеку, по крайней мере штатными средствами и с нашим тогдашним багажом знаний. Так же все было очень грустно, например, с функциональностью отображения меток на карте. Вся возможность ее настройки заключалась в указании текста для меток когда по ним тапаешь. На тот момент единственным способом как-то это обойти было использование специального объекта "ПолеHTMLДокумента", но с ним были свои проблемы. На время работы с 1с все мои знания в нативной разработке под андроид заключались в паре HelloWorld, так что идеи реверсить мобилку 1сную даже в голову не приходило, разные вопросы от заказчиков по нестандартному расширению возможностей 1с мы либо не решали никак, либо пилили очень простые нативные приложения ставившиеся рядом и криво/косо с 1с интегрировали (да и лицензионное соглашение 1с вроде запрещает правки в самой платформе).
Так что первая причина заняться реверсингом 1с заключалась в том, что мне стало интересно, а что я могу сделать имея текущий багаж знаний. Сразу скажу, опыт нативной разработки оказался не сказать что нужен, в повседневной работе почти ничего из того что будет описано ниже не встречается. Так что в принципе наверно любой средний 1сник посидев несколько дней/недель смог бы во всем этом разобраться.
Вторая же причина заключается в том, что мне просто захотелось попробовать поковырять чужие apk, ибо до этого я упускал этот, довольно широкий пласт знаний, и, поскольку нужно было с чего то начинать, мне пришла в голову как раз 1с.
Первое что я сделал, еще когда идея реверсить 1с только смутно бродила в моей голове, просто перетащил мышью apk файл приложения на окно AndroidStudio. Хочу сказать сразу — что мне стало немного грустно, ибо большая часть кода 1с написана на C++ и лежит в .so библиотеках, и их отреверсить посложнее, да и не было интересно. А вот файл classes.dex всецело завладел моим вниманием, тем более что его скромный размер давал мне возможность предположить что и реверсить его будет несложно. В целом так и оказалось. Кстати, интересное следствие того что большая часть кода на C++ — очень много методов и классов избежали обработки с помощью ProGuard. Сложновато делать интероп с минифицированным кодом ;).
Вот что я увидел в окне студии (разбирал x86 версию, чтобы работать с эмулятором а не реальным девайсом)
Как можно видеть на скриншоте выше — минификации приложение почти не подвергалось (в плане переименования классов и методов). Плюс видно что кода на java очень немного и почти все место занимают so библиотеки.
Повтыкав какое-то время на список классов, я увидел любопытный класс MapImpl, навевающий подозрения что именно он виновник такой грустной ситуации с кастомизацией отображения меток.
Список методов и их сигнатуры внушали надежду что все будет очень просто, и я решил заглянуть в smali код, после чего сильно напрягся и пошел читать список команд smali, и как его читать/писать. Впрочем, именно на этом моменте я решил что дело обещает быть несложным и недолгим, а соответственно вот он, повод поиграться с реверсингом. Приняв для себя решение посвятить этому пару вечеров (как же жестоко я ошибался), пошел со спокойной душой спать ложиться.
Проснувшись с утра я решил что поскольку до этого момента никогда не занимался даже подменой ресурсов в приложениях, не то что изменениями логики, нечего мне замахиваться сразу на замену активити с картой, лучше приближаться к решению задачи маленькими шажками. После чего я составил себе небольшой список шагов который должен был привести меня в конечную точку моего путешествия в виде рабочей мобильной платформы с моими правками. Список этот выглядел следующим образом:
- Подготовить конфигурацию 1с для мобильной платформы вся функциональность которой заключается в отображении двух меток на карте.
- Распаковать apk мобильной платформы, запаковать без изменений, убедиться в работоспособности конфигурации.
- Внести небольшие изменения в smali файлы, не меняющие практически ничего, но которые можно было бы увидеть в логах или изменении логики работы, собрать и убедиться что это работает.
- Перегнать smali активности с картой в java, либо же написать активность с таким же интерфейсом, подменить активность в приложении без изменения функциональности. Как альтернативный вариант, если с первым разбираться будет лень или сложновато — написать класс, который будет выполнять часть работы за MapImpl и добавить вызов его методов из smali MapImpl.
- Написать эту статью (давно уже хотелось что-то написать, но другие идеи пока еще варятся в голове, а тут показалось что это наконец довольно достойная тема)
Ну, хорошо хоть с первым пунктом у меня проблем не возникло. Скачал бесплатную учебную версию платформы, скачал мобильную платформу, развернул все это у себя на компьютере (1С, сделайте вы уже версию учебную для linux, у меня как раз очередной порыв уйти с винды, а тут приходится часть работы в ней делать). Конфигурация очень простая, при запуске вызывает функцию ПоказатьНаКарте() в которую передает две точки на карте. Все.
А вот со вторым пунктом из-за моей неграмотности вышло грустнее. Да что уж там, проблемы были со всеми пунктами кроме первого.
Гугл мне сразу подсказал что есть такой отличный инструмент apktool позволяющий буквально двумя командами разбирать apk до .smali файлов, а так же собирать из них обратно. Им я и решил воспользоваться. Распаковал apk следующей командой (здесь и далее, несмотря на то что временами часть работы делал на linux, все команды буду приводить для windows):
и получил каталог unpacked в котором лежала куча файлов, с ними в будущем предстояло работать. Запаковал apk обратно командой
Попытавшись установить его на эмулятор
я получил следующую ошибку:
В общем нужно было больше внимания базе уделять. Я конечно знал что существуют подписи, и о том что они делятся на дебажные и релизные, но не знал что приложения вообще без подписей не устанавливаются. Я решил воспользоваться своей дебажной подписью, и подписав apk командой
мне удалось запустить приложение. Правда вместо карты с двумя точками меня ждал серый экран с подписью google внизу. Почесав репу я решил что дело в том что используется ключ для гугл карт от 1с, который с моей подписью не работает. Поэтому пойдя в консоль разработчика на сайте google я создал новый проект для работы с api google карт на андроиде, получил api key, который указал в res/values/strings.xml в google_maps_key строке, а так же добавил свой дебажный ключ в разрешенные для проекта. Перепаковал и переподписал apk, запустил, и наконец все снова работало.
Следующее что я хотел сделать — это автоматизировать запуск приложения и добавление конфигурации 1с в платформу. Вручную после каждых правок делать это делать было бы той еще морокой.
Сначала я нагуглил и попытался воспользоваться утилитами jadx или dex2jar, чтобы не мучиться с чтением smali, а читать более привычный код на java, но по какой-то причине они не работали (в дальнейшем jadx все таки завести удалось каким то шаманством). Пришлось разбирать smali, благо это оказалось не так ужасно как я боялся.
Чтобы понять, как мобильная платформа получает от десктопной платформы команду на запуск конфигурации при подключении по adb, я решил посмотреть точки входа в приложение и добавить вывод в логи интентов и прочей полезной информации. Начать решил с application ( com.e1c.mobile.E1cApplication ) и активности имеющей android.intent.action.MAIN в intent-filter ( com.e1c.mobile.App ). Также меня заинтересовал reciever com.e1c.mobile.Starter с интересным intent filter на com.e1c.mobile.START_TEMPLATE и com.e1c.mobile.START_CMD . Уж очень похоже на то что он принимает интенты с командами 1с, и именно он стартует конфигурацию из шаблона.
В E1cApplication ничего интересного к сожалению обнаружить не удалось, все что там происходит — установка своего хендлера на крэши.
А вот в двух других классах, Starter и App информации было гораздо больше и оказалась она довольно полезной. Метод App.onCreate(Landroid/os/Bundle;)V довольно большой, так что приводить его целиком не буду, приведу только заинтересовавшие меня части.
Из приведенного выше участка кода видно что приложение получает интент, кладет ссылку на него в регистр p1 , через StringBuilder дописывает к имени класса и метода и передает в статический метод V(Ljava/lang/String;)V класса Utils . Видимо какой-то свой логгер. После чего интент проверяется на наличие дополнительных данных, и, при наличии, из него получается Uri , из которого в свою очередь получается строка методом getQuery() и передается классу Starter . Дальше изучать onCreate смысла не видел, пробежался взглядом и убедился что действия довольно стандартные. Разве что вью вроде бы создается программно абсолютно другим классом, вместо использования LayoutInflater , но сильно глубоко я не копал, так что возможно все и не так как я подумал. Следующий класс куда я пошел — Starter . Благо он и в активити упоминался и в манифесте меня заинтересовал.
К сожалению тот метод что вызывался из активити, оказался нативным ( .method static native startCmd(Ljava/lang/String;)V ), потому обратил внимание на метод onRecieve (в котором приложение принимает интенты на которые подписано). Приводить код не буду, меня в нем заинтересовало что интент так же логигуется методом V(Ljava/lang/String;)V класса Utils . Получается что достаточно дописать немного smali кода в этот метод — и я получу свои логи, причем на тех же местах где их задумывали разработчики платформы. Перейдя в класс Utils я увидел сразу 2 пустых метода, V и W. Видимо пустые они потому как при компиляции релизной версии вырезались. Я просто дописал в них запись переданной строки в стандартный android.utils.Log . Для этого сменил количество требуемых локальных регистров с 0 до 1 (для строки тега), поместил эту самую строку в регистр v0 , а также прописал вызов методов Log
Запустил из 1с десктопной 1с мобильную и получил следующие логи
Как видим — есть вся необходимая информация для автоматизации запуска приложения через adb. Правда к этому моменту я словил двойной фейспалм. Во-первых, наконец подобрал ключи с которыми jadx осилил перевод в java (понятно что писать все равно в smali бы пришлось, но все же). А вторым фейспалмом оказалось то что я осознал что зря я мучаю платформу разработчика (нужна только для разработки и отладки конфигураций), правильнее было бы реверсить сборку релизов 1сных приложений, причем там есть полу готовые gradle проекты для сборки, есть файл с перечнем зависимостей и другие плюшки. Я немного по этому поводу погрустил — и решил все таки закончить с тем что начал. Все равно ради фана делаю все это, а не ради практической пользы.
Автоматизировать установку и запуск через adb приложения я решил с помощью gradle. Все равно к тому моменту у меня уже был написан небольшой перечень тасок (распаковка, копирование модифицированных ресурсов и smali файлов в каталог с распакованным приложением, упаковка, подпись, по сути все таски просто раннеры для команд консольных). К существующим таскам добавил выполняющие следующие команды
Перечисленной выше последовательностью команд мы устанавливаем apk, даем установленному приложению разрешение на чтение диска, копируем конфигурацию 1с на устройство, и даем команды на запуск 1с и загрузку конфигурации. Работает это кстати не на всех версиях андроида, но я тестировал на api 28, и соответственно на нем эта последовательность делает все корректно. На младших версиях могут быть проблемы с выдачей прав.
Тут у меня было несколько вариантов дальнейшего развития событий.
- Правлю напрямую MapImpl.smali, что обещало быть довольно сложным занятиям учитывая что библиотека для работы с гугл-картами довольно серьезно минифицирована, да еще и в синтаксисе smali все писать пришлось бы.
- Использую полученный благодаря jadx файл MapImpl.java, вношу правки в него, используемые в нем классы подменяю на заглушки, перегоняю в smali, подменяю файл, упаковываю. Вариант показался мне напряжным так как уж больно много заглушек пришлось бы городить, к тому же с некоторыми из них были проблемы с которыми у меня не было желания ковыряться.
- Комбинирую подходы 1 и 2, вставляю в smali код вызовы специального класса расширения MapImplExtenstion.java который расширяет часть логики — в итоге выбрал этот вариант, просто потому что он проще первого и второго вариантов, и показался мне пусть возможно чуть более сложным чем вариант 4, но зато менее трудоемким (угу, мечтай, наивный).
- Вообще заменить гугл карты на что-то другое, например яндекс. Сделать всю работу в другом проекте, просто повторив сигнатуры MapImpl, затем минифицировать распаковать, и просто закинуть готовые smali файлы перед упаковкой приложения на соответствующие места. Никаких проблем с минифицированными библиотеками, но пришлось бы регистрироваться для получения ключа для карт, создавать отдельный проект, заморачиваться со стыковкой ресурсов и прочее.
- То же что вариант 4, но заменить гугл на… Гугл. Но тут у меня были подозрения что удастся минифицировать 1 в 1 maps sdk, а ставить эксперименты не было желания.
Используя jadx для декомпиляции в java нашел в декомпилированном коде метод отвечающий за их заполнение
Соответственно у класса MapImplExtension добавил метод ArrayList[] kN(String[] titles, double[] coordinates) который в первом элементе массива вернет список который нужно будет поместить в Xj, а во втором список для Xk.
Скомпилировал следующими командами сначала в class, затем в dex, затем декомпилировал в smali чтобы потом упаковать вместе с остальными файлами
Добавил в MapImpl.smali поле extension типа нашего нового класса, и добавил его инициализацию
А также заменил обработку в классе MapImpl данных от 1с на обработку в классе MapImplExtension
Запаковав и запустив приложение — я радостно увидел что все работает. Но на данный момент я не сделал ничего такого что именно расширило бы возможности мобильной платформы. Просто подменил заголовки у меток на карте. А вот захотев изменить изображения меток я здорово обломался и зарылся довольно надолго в исходники и документацию.
Сначала немного пояснений как вообще устанавливается маркер для метки. У класса MarkerOptions есть метод public MarkerOptions icon (BitmapDescriptor iconDescriptor) в который передается объект созданный одним из статических методов класса BitmapDescriptorFactory .
И вот здесь собственно меня ждал облом. Поскольку 1с это дело не использует — соответствующие классы были просто вырезаны при минификации. Пришлось их восстанавливать, и было это больно и долго. Точнее классы то были, но были переименованы и не содержали нужных методов. Путем ковыряния в сорцах полной библиотеки для работы с картами — по сигнатурам и константам выяснил соответствия классов библиотеки классам приложения, добавил необходимые методы и поля, пересобрал, и порадовался что этот квест наконец закончил, поскольку все наконец то заработало, пусть и не с первой попытки (несколько раз косячил с сигнатурами и путал минифицированные классы).
Результат (внешне не сильно впечатляющий). Выбраны методом тыка две точки с координатами (45;45) и (46;46)
Поскольку объем измененного кода довольно большой — включать в статью его не буду, приведу только изменения сигнатур. Если кому интересны все правки которые я сделал на этом шаге — можете посмотреть в этом коммите.
Подводя итоги — опыт был довольно интересный. По крайней мере для меня. Помог разобраться с некоторыми инструментами, узнал немного лучше о работе андроида и формате байткода для dalvik/art, опыт ковыряния минифицированного кода тоже будет полезен (уже был случай когда в релизной версии R8 вырезал поля класса которые на самом деле использовались, в тот раз только методом тыка разобрался, сейчас бы это проблем не доставило).
Если кому-то интересно самому все повторить и возможно расковырять еще больше — я выложил на github все исходники вместе с кривым gradle скриптом осуществляющим сборку из исходного apk модифицированного.
Читайте также: