Componente externo para a plataforma móvel 1C (BroadcastReceiver)

Tudo o que foi dito no artigo será interessante exclusivamente para os desenvolvedores da 1C.

Hoje vamos analisar o componente externo para "1C Mobile Application". Este artigo apareceu por dois motivos. Vamos desenvolver tudo sob o mesmo ATOL Smart.Lite

  1. O desenvolvimento de um aplicativo nativo acabou sendo muito mais complicado do que eu pensava inicialmente.
  2. Vários pedidos foram recebidos especificamente para o componente externo para 1C

Antes disso, eu já tinha experiência em escrever componentes externos em c++ . E existe até um modelo para a plataforma x86. Foi escrito sem qualquer entendimento de c++ . No entanto, ele trabalha em dois projetos e não cai. Passamos para a essência do problema. Precisa de um componente nativo para receber mensagens de broadcast em 1C. Iremos pela Internet e entenderemos que existem soluções prontas. Mas eles estão todos no meu site não tão favorito, por cobiça excessiva. E eu não queria pagar pela caixa preta. No entanto, um excelente artigo “Componentes externos da plataforma móvel 1C para o sistema operacional Android” foi encontrado lá. Ele descreve como moldar uma versão móvel de um componente e o que precisa ser instalado. Pelo que entendi, aqui está o código fonte do artigo acima. Muito obrigado ao homem gentil por seus esforços. Ajudou muito com um exemplo vivo a entender o que e como funciona. Então tive que expandir um pouco meus horizontes, como a JNI funciona. Simples e claro aqui e aqui . Eu recomendo que você se familiarize com eles. Estou certo de que os programadores de c ++ reais não irão gostar do meu código. Peço que seja indulgente e cutuque o que pode ser melhorado e escreva mais corretamente.

Vamos começar. Peguei o código-fonte do repositório que indiquei anteriormente e o refiz quase completamente para atender às minhas necessidades. Você pode pegar aqui . Vamos revisar os pontos principais. O principal procedimento para nós é o startEventsWatch , nele, verificamos se não temos BroadcastReceiver conectado e redefinimos a função onReceive Aqui, olhamos para qual evento nos ocorreu, preencha os campos e chamamos a função OnBroadcastReceive e agora é a função de conexão entre java e C + + e nos leva do mundo do Android para o mundo do 1C. Mais sobre isso mais tarde. As linhas queridas do que queremos obter no 1C são assim.

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

Ele descreve que estamos esperando um evento do scanner. No meu caso, este é com.xcheng.scanner... No seu caso, dependendo do scanner, haverá outra linha. Consequentemente, os dados dentro da mensagem também serão diferentes. Como regra, esses dados podem ser obtidos com o fabricante do TSD. Bem, ou veja o logcat. Eu também queria receber os códigos de imprensa dos botões de hardware. Mas o problema não foi resolvido na testa. Apenas adicionar onKeyUP ao código e enviá-lo para sendBroadcast não teve êxito. Não é de surpreender, nossa atividade não está em primeiro plano. Por esse motivo, tive que lançar rapidamente o 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); } } 


Agora, voltando ao envio de dados em 1C. Nosso OnBroadcastReceive chama o 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) estamos trabalhando aqui. jstring j_event, jstring j_type, jstring j_data Essas são as variáveis ​​pelas quais eu passo, o evento, o tipo de CC e o próprio CC. Pode haver outros dados.

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); Com isso, traduzimos a string de jstring para std::wstring e empacotamos tudo para 1C WcharWrapper wmsg((wchar_t*)ws_event.c_str());

Obrigado à pessoa inteligente pela função de conversão. A segunda função vem da caixa no exemplo de 1C.

Título de spoiler
 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; } 


Para quem não quer instalar tudo e compilá-lo. Aqui estão os lançamentos concluídos.


Só isso. À espera de comentários.

Source: https://habr.com/ru/post/pt479132/


All Articles