Aller au contenu

JNI c++ et java call back réseau


jpbordi

Recommended Posts

 

Bonjour,

 

Je suis à al recherche d'exemple, de lien, de tutoriel, sur le traitement réseau  sur  des callback java via jni c++

 

un lien sur un projet git exemple illustrant mon cas serait parfait.

 

je fais appel aux pro du jni, callback et reseau

 

Je dois écrire un application C++ avec un  java call back  sur une api java qui traite un appel réseau,  mais je tourne en rond sur les diverse solution, elle marchent

presque, j'ai besoin d'avis différent sur la meilleure solution à appliquer dans mon approche.

 

-Acitvité

    ->appel jni  méthode requete 

             c++ prépare message

             c++ appel java callback via interface pour le traitement réseau  byte[] reponse=requete(byte[] question)

                     java call serveur http  en envoi requete et recupère la réponse et retour au jni appelant

             c++ traiter réponse (save data)

         retour Activité menu ok

 

j'utilise une interface java avec une implémentation  okhttp/volley/httpclient,   pour une question de liberté d'implémentation du client, je ne peux pas utiliser directement du c++ (domage)

une méthode très simple disponible de l'interface

 byet[] reponse= request( byte[] question ) 

 

le JNI est appelé par mon activité et fait il fait un callback sur ma requête via mon interface java, et execute l'impemlentation qui traite la parite réseau.

je suis en mode bloquant,  je pose ma question et j'attends ma réponse pour continuer

 

Jje me heurte à divers problème,  

 

d'abord le premier cas,  simple au premier abord,   

la  requête part vers mon serveur http qui reçu et traité, mais je me heurte à une exeption  NetworkOnMainThreadException

en clair je ne peux pas bloquer mon activité  en exécution sur le thread principal vis à vis de 'utilisateur, 

bizarre, bizarre, je peux avoir avec des timer qui' arrête l'échange au bout de 10s.

y'a t'il une solution pour contourner cette exception, 

 

appel JNI en gros, je pensais éviter l'exception en ouvrant une une nouvelle instance jvm/java env, mais ca ne passe pas, j'ai la même erreur.

 

jvm->AttachCurrentThread(&myNewEnv, &args);
jbyteArray  masterResponseMessageBuf = (jbyteArray) myNewEnv->CallObjectMethod(  httpTaskMgr, httpMethodId, bufArray);
jvm->DetachCurrentThread();

 

public byte[] request( byte[]request )  {

..

... snip

..

Response response= client.newCall(request).execute();
if (!response.isSuccessful())
    throw new IOException("Unexpected code server :" + response);
ResponseBody body = response.body();
int len = (int) body.contentLength();
if (len > 0) {
    byteObject = new byte[len];
    InputStream source = body.byteStream();
    source.read(byteObject);

}

 

Deuxième cas je me tourne vers un appel aync ca marche presque aussi, la requête part et traiter par le serveur http, pas d'exception, 

mais ma response reste vide, je ne suis pas en mode bloquant pour récupérer ma réponse et mettre à disposition de l'appel de mon appelant jni,

 

y a t'il un moyen d'attendre la réponse du serveur avant de sortir de méthode java pour revenir à l'appelant avec bien sur un timeout si délai dépassé.

 

public byte[] request( byte[]request ) {
...
... snip
...
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        e.printStackTrace();
    }

    @Override
    public void onResponse(Call call, final Response response) throws IOException {
        if (!response.isSuccessful()) {
            throw new IOException("Unexpected code " + response);
        }
        
        ResponseBody body = response.body();
        int len = (int) body.contentLength(); 
        if (len > 0) {
          byteObject = new byte[len];
          InputStream source = body.byteStream(); 
          source.read(byteObject);
       }

    }
   return byteObject; // n'attend pas le callback via onResponse  methode ? comment?
}

 

J'ai egalement  utiliser un  async task 

extends AsyncTask<byte[], Void, byte[]>

mais je bloque à l'appel du jni, sur l'appel de la signature methode

a cause de ca, il faut faire un get pour récupèrer la reponse de l'Async

response=obj.execute(question).get(), il n'encaisse pas ce genre de signature de methode au niveau de l'appel jni., j'ai mis de côté cette solution

 

Pour résumer,  

 

je suis en native c++, mon activité(java) appelle mon jni et qui fais un callback java d'une requete http vers mon serveur et je récupère la réponse pour être traiter au niveau c++

 

en mode synchrone j'envoi ma requête en callback jni au serveur et je tombe en NetworkOnMainThreadException

en mode asynchrone j'envoi ma requête,mais ma requête sort avant de récupérer la réponse de mon call back.

 

Merci pour vos avis, je continu à chercher la meilleure solution, je ne sais pas pour l'instant quel est la meilleure approche, un mode async reseau, ou un appel bloquant avec timeout

Cordialement

JP

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Lien vers le commentaire
Partager sur d’autres sites

 

bon, j'ai fini par trouver le bon compromis

j'utilise mon implémentation réseau en mode synchrone via mon interface dans une classe de type AsyncTask

pour pouvoir l'appeler au niveau c++ dans le jni, j'ai définie une classe utilitaire qui appelle ma classe asynchrone qui gère ma classe réseau
ca fonctionne, mais pas super simple, je suis obligé de faire 3 classes.

Je peux implémenter du httpclient, du volley, du okhttp, ou autre chose côté client dans un contexte asynchrone et rester compatible lors des appels jni executé au niveau de mon activité.

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...