Внешняя компонента для 1С Мобильной платформы (BroadcastReceiver)

  • Tutorial
Все сказанное в статье будет интересно исключительно разработчикам 1С.

Сегодня мы разберем внешнюю компоненту для «1С Мобильное приложение». Эта статья появилась по двум причинам. Разрабатывать будем все под тот же АТОЛ Smart.Lite

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

До этого у меня уже был опыт написания c++ внешних компонент. И даже есть шаблон под x86 платформу. Писалось вообще без понимания c++. Но тем не менее, в двух проектах работает, и не падает. Переходим к сути проблемы. Нужна нативная компонента для получения Broadcast сообщений в 1С. Пробежимся по интернету и поймем, что готовые решения есть. Но все они находятся на мной не очень любимом сайте, за чрезмерную жадность. А платить за черный ящик я не хотел. Тем не менее там попалась отличная статья «Внешние компоненты мобильной платформы 1С для ОС Андроид». В ней описывается как слепить мобильную версию компоненты, и что надо установить. Как я понимаю вот здесь лежат исходники выше упомянутой статьи. Огромное спасибо доброму человеку за труды. Очень помогло на живом примере понять что и как работает. Далее пришлось немного расширить свой кругозор как же работает JNI. Просто и понятно здесь и здесь. Рекомендую ознакомиться с ними. Уверен, что настоящим программистам c++ мой код не понравится. Прошу отнестись снисходительно и ткнуть, что можно улучшить и написать правильней.

Приступим. Я взял исходный код с репозитория который указывал раньше, и почти полностью его переделал под свои нужды. Взять можно здесь. Пробежимся по основным моментам. Главное процедурой у нас является startEventsWatch В ней мы проверяем, что у нас не подключен BroadcastReceiver и переопределяем функцию onReceive Там мы смотрим какое событие к нам пришло, заполняем поля, и вызываем функцию OnBroadcastReceive и вот она то и является связующей функцией между java и С++ и переносит нас из мира Android в мир 1С. Об этом чуть позже. Заветные строчки, что же мы хотим получать в 1С выглядят вот так.

filter.addAction("com.xcheng.scanner.action.BARCODE_DECODING_BROADCAST");
filter.addAction(NEW_KEY_UP);

Здесь описывается, что мы ожидаем событие(action) от сканера. В моем случае это com.xcheng.scanner.... В вашем случае в зависимости от сканера, будет другая строка. Соответственно и данные внутри сообщения, тоже будут другими. Как правило эти данные можно получить у производителя ТСД. Ну или посмотреть в logcat. Еще я хотел получать коды нажатия аппаратных кнопок. Но проблема в лоб не решилась. Простое добавления onKeyUP в код и отправка этого в sendBroadcast успехом не увенчались. Оно и не удивительно, наша Activity не на переднем плане. По этой причине пришлось быстренько накидать AccessibilityService

startEventsWatch
  public void startEventsWatch()
  {

    if (m_Receiver==null)
    {
      m_Receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
          if (intent != null) {
            String event, type, data;

            switch (intent.getAction()) {
              case "com.xcheng.scanner.action.BARCODE_DECODING_BROADCAST":
                event = "NewBarcode";
                type = intent.getStringExtra("EXTRA_BARCODE_DECODING_SYMBOLE");
                data = intent.getStringExtra("EXTRA_BARCODE_DECODING_DATA");
                OnBroadcastReceive(m_V8Object, event, type, data);
                break;
              case NEW_KEY_UP:
                event = "NewKeyUP";
                type = "key";
                data = intent.getStringExtra(KEY_CODE);
                OnBroadcastReceive(m_V8Object, event, type, data);
            }
          }
        }
      };

      IntentFilter filter = new IntentFilter();
      filter.addAction("com.xcheng.scanner.action.BARCODE_DECODING_BROADCAST");
      filter.addAction(NEW_KEY_UP);

      m_Activity.registerReceiver(m_Receiver, filter);
    }

  }


Теперь вернемся к нашей отправке данных в 1С. Наша OnBroadcastReceive вызывает процедуру extern "C" JNIEXPORT void JNICALL Java_org_innovait_atolsmartliteutils_MainApp_OnBroadcastReceive(JNIEnv* env, jclass jClass, jlong pObject, jstring j_event, jstring j_type, jstring j_data) Вот здесь мы можем добавить переменные, с которыми хотим работать со стороны Java. jstring j_event, jstring j_type, jstring j_data Это переменные в которых я передаю, событие, тип ШК, и сам ШК. Могут быть и другие данные.

Java_org_innovait_atolsmartliteutils_MainApp_OnBroadcastReceive
extern "C" JNIEXPORT void JNICALL Java_org_innovait_atolsmartliteutils_MainApp_OnBroadcastReceive(JNIEnv* env, jclass jClass, jlong pObject, jstring j_event, jstring j_type, jstring j_data) {
	IAddInDefBaseEx *pAddIn = (IAddInDefBaseEx *) pObject;
	if (pAddIn != nullptr) {
		
		std::wstring ws_event =ToWStringJni(j_event);
		std::wstring ws_type = ToWStringJni(j_type);
		std::wstring ws_data = ToWStringJni(j_data);

		std::wstring obj_data{};

		obj_data = L"{\"type\": \"" + ws_type + L"\", \"data\": \"" + ws_data + L"\"}";	

		WcharWrapper wdata((wchar_t*)obj_data.c_str());
		WcharWrapper wmsg((wchar_t*)ws_event.c_str());

		pAddIn->ExternalEvent(s_EventSource, wmsg, wdata);
	}
}


std::wstring ws_event =ToWStringJni(j_event); Этим мы переводим строку из jstring в std::wstring, и потом это все запаковываем для 1С WcharWrapper wmsg((wchar_t*)ws_event.c_str());

Спасибо умному человеку за функцию конвертации. Вторая функция идет из коробки в примере от 1С.

Заголовок спойлера
std::wstring ToWStringJni(jstring jstr)
{
	std::wstring ret;
	if (jstr)
	{
		JNIEnv* env = getJniEnv();
		const jchar* jChars = env->GetStringChars(jstr, NULL);
		jsize jLen = env->GetStringLength(jstr);
		ret.assign(jChars, jChars + jLen);
		env->ReleaseStringChars(jstr, jChars);
	}
	return ret;
}


Тем кто не хочет все устанавливать и сам компилировать. Вот готовые релизы.


На этом все. Жду комментариев.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 8

    0
    Как я понимаю вот здесь лежат исходники по мотивам которой и написана та самая статья

    Автор той самой статьи которая была написана за год до этих исходников автор оригинальных решений который выдает их уже более двадцати последних лет. В частности первым связал компоненты 1с с платформой .NET

      0
      Так я вроде бы и не воровал ничего. Честно указал, где и что нашел. Заочно поблагодарил. Да часть кода осталась(~10%), но я сильно проект переработал. Там не очень хорошо была реализована отсылка внешнего события. Использовалось только «Данные». А «Источник» и «Событие» всегда были одинаковыми. И вот если для источника это нормально, то для «Событие» — должно приходить именно какое событие шлется. В моем случае это — «ШК», «Нажатие кнопки»
        0

        Не совсем точно указано что та самая статья написана по мотивам другой разработки.

          0

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

            0

            Скорее, факты нужны чтобы утверждать что один код возможно основан на другом коде.

              0

              Я нигде не утверждаю что один код основан на другом. Я привёл ссылки, где чётко указано, кто является владельцем публикаций. Я нигде не утверждаю что одно, это производное от другого. Честно, не понимаю возражений.

        0

        Хотелось бы ещё узнать про более 20ти лет. Тогда только 7.7 была. Что конкретного, он тогда написал. Может стоит статью на эту тему написать? Из тех времен я помню многое, и до сих пор работаю с 77

          0

          Этот разработчик работает более двадцати лет с 1с. Первая его статья которая получила популярность относится к 2003году и называется Взаимодействие с COM-объектами из NET на примере внешней компоненты для 1С: Предприятия


          Она была опубликована в блоге Майкрософт и сейчас на ее там уже нет но можно найти на нее ссылку в некоторых лентах новостей.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое