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
- O desenvolvimento de um aplicativo nativo acabou sendo muito mais complicado do que eu pensava inicialmente.
- 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.