Composant externe pour la plate-forme mobile 1C (BroadcastReceiver)

Tout ce qui est dit dans l'article sera intéressant exclusivement pour les développeurs 1C.

Aujourd'hui, nous analyserons le composant externe pour «Application mobile 1C». Cet article est paru pour deux raisons. Nous développerons tout sous le même ATOL Smart.Lite

  1. Développer une application native s'est avéré être beaucoup plus compliqué que je ne le pensais à l'origine.
  2. Plusieurs demandes ont été reçues spécifiquement pour le composant externe pour 1C

Avant cela, j'avais déjà de l'expérience dans l'écriture de composants externes c++ . Et il existe même un modèle pour la plate-forme x86. Il a été écrit sans aucune compréhension de c++ . Néanmoins, il fonctionne dans deux projets, et ne tombe pas. Nous passons à l'essentiel du problème. Besoin d'un composant natif pour recevoir des messages Broadcast en 1C. Nous allons parcourir Internet et comprendre qu'il existe des solutions toutes faites. Mais ils sont tous sur mon site pas si préféré, pour une cupidité excessive. Et je ne voulais pas payer pour la boîte noire. Néanmoins, un excellent article «Composants externes de la plate-forme mobile 1C pour le système d'exploitation Android» a été publié. Il décrit comment mouler une version mobile d'un composant et ce qui doit être installé. Si je comprends bien, voici le code source de l'article ci-dessus. Un grand merci à l'homme gentil pour ses efforts. Cela m'a beaucoup aidé avec un exemple vivant pour comprendre quoi et comment cela fonctionne. Ensuite, j'ai dû élargir un peu mes horizons comment fonctionne JNI. Simple et clair ici et ici . Je vous recommande de vous familiariser avec eux. Je suis sûr que les vrais programmeurs C ++ n'aimeront pas mon code. Je vous demande d'être indulgent et de pousser ce qui peut être amélioré et d'écrire plus correctement.

Commençons. J'ai pris le code source du référentiel que j'ai indiqué plus tôt, et je l'ai presque entièrement refait pour répondre à mes besoins. Vous pouvez le prendre ici . Passons en revue les points principaux. La procédure principale pour nous est startEventsWatch Dans ce document, nous vérifions que nous n'avons pas BroadcastReceiver connecté et redéfinissons la fonction onReceive Là, nous regardons quel événement nous est arrivé, remplissez les champs et appelons la fonction OnBroadcastReceive et maintenant c'est la fonction de connexion entre java et C + + et nous fait passer du monde d'Android au monde du 1C. Plus d'informations à ce sujet plus tard. Les lignes chères de ce que nous voulons obtenir en 1C ressemblent à ceci.

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

Il décrit que nous attendons un événement du scanner. Dans mon cas, c'est com.xcheng.scanner... Dans votre cas, selon le scanner, il y aura une autre ligne. Par conséquent, les données à l'intérieur du message seront également différentes. En règle générale, ces données peuvent être obtenues auprès du fabricant du TSD. Eh bien, ou regardez logcat. Je voulais également recevoir les codes de pression des boutons matériels. Mais le problème n'a pas été résolu dans le front. L'ajout de onKeyUP au code et son envoi à sendBroadcast a échoué. Ce n'est pas surprenant, notre Activité n'est pas au premier plan. Pour cette raison, j'ai dû jeter rapidement 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); } } 


Revenons maintenant à nos envois de données en 1C. Notre OnBroadcastReceive appelle la 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) nous pouvons travailler ici avec nous pouvons travailler avec 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) jstring j_event, jstring j_type, jstring j_data Ce sont les variables dans lesquelles je passe, l'événement, le type de CC et le CC lui-même. Il peut y avoir d'autres données.

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); Avec cela, nous traduisons la chaîne de jstring en std::wstring , puis nous emballons le tout pour 1C WcharWrapper wmsg((wchar_t*)ws_event.c_str());

Merci à la personne intelligente pour la fonction de conversion. La deuxième fonction vient de la boîte dans l'exemple de 1C.

Cap 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; } 


Pour ceux qui ne veulent pas tout installer et le compiler eux-mêmes. Voici les versions finales.


C’est tout. En attente de commentaires.

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


All Articles