Bonjour,
Je suis en train de développer une application pour un projet d'école d'ingénieurs, j'utilise QT 5.4.1 (Qt creator 3.4.1, MinGW) sur Windows 7 64 bits.
Mon application sera assez simple, elle aura juste à activer le hotspot Wifi (Point d'accès), attendre qu'une autre application s'y connecte, et ensuite envoyer un message (String) à cette application
Comme il n'y a pas de fonction permettant d'activier le hotspot Wifi dans le NDK, j'utilise JNI (Java Native Interface) pour appeller les fonctions Java depuis lecode natif (c++).
Par exemple, pour une fonction toute simple :
Code Java :
C++ code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.app.test; import android.os.Vibrator; public class JniMath { public static int fibonacci(int n) { if(n<0) return -1; else if(n==0 || n==1) return n; return fibonacci(n-1)+fibonacci(n-2); } }
Ceci marche très bien, je vais maintenant essayer de faire la même chose avec les fonctions permettant de configurer le hotspot Wifi.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 int fibonacci(int n) { return QAndroidJniObject::callStaticMethod<jint>("org/app/test/JniMath" , "fibonacci" , "(I)I" , n); }
J'ai une classe Java "ApManager" :
C++ code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 package org.app.test; import android.content.*; import android.net.wifi.*; import java.lang.reflect.*; //Classe qui gère le Hotspot Wifi (point d'accès) public class ApManager { //Le hotspot Wifi est-il activé ? public static boolean isApOn(Context context) { WifiManager wifimanager = (WifiManager) context.getSystemService(context.WIFI_SERVICE); try { Method method = wifimanager.getClass().getDeclaredMethod("isWifiApEnabled"); method.setAccessible(true); return (Boolean) method.invoke(wifimanager); } catch (Throwable ignored) {} return false; } //(des)Activer le hotspot Wifi public static boolean configApState(Context context, boolean b) { WifiManager wifimanager = (WifiManager) context.getSystemService(context.WIFI_SERVICE); WifiConfiguration wificonfiguration = null; try { //Si le Wifi est activé, le désactiver if(isApOn(context)) { wifimanager.setWifiEnabled(false); } Method method = wifimanager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class); method.invoke(wifimanager, wificonfiguration, b); return true; } catch(Exception e) { e.printStackTrace(); } return false; } }
Le code me semble correct, j'hésite entre les deux signatures mais j'ai un autre problème plus génant : Je ne vois pas comment, depuis le code C++, obtenir le contexte de l'application, pour pouvoir ensiute le passer comme argument à mes fonctions "bool getWifiApState(QAndroidJniObject context)" et "bool setWifiApEnabled(QAndroidJniObject context, bool b)" ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 bool getWifiApState(QAndroidJniObject context) { return QAndroidJniObject::callStaticMethod<jboolean>("org/app/test/ApManager" , "isApOn" , "(Ljava/lang/Object)Z" //Ou (Landroid/content/Context)Z ???? , context.object<jobject>()); } bool setWifiApEnabled(QAndroidJniObject context, bool b) { return QAndroidJniObject::callStaticMethod<jboolean>("org/app/test/ApManager" , "configApState" , "(Ljava/lang/Object;Z)Z" //Ou (Landroid/content/Context;Z)Z ??? , context.object<jobject>() , b); }
J'avoue avoir un peu de mal à comprendre...
Je vous remercie d'avance pour vos réponses.
EDIT : J'ai trouvé :
Malheureusement, cela ne marche pas, le hotspot Wifi ne s'active pas et je ne'arrive pas à récupérer son état. Même si j'essaie de faire quelque chose de simple comme activer le Wifi (via wifimanager.setWifiEnabled(true), cela ne marche pas non plus
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 interface = QApplication::platformNativeInterface(); activiti = (jobject)interface->nativeResourceForIntegration("QtActivity"); at = new QAndroidJniObject(activiti); appctx = at->callObjectMethod("getApplicationContext", "()Landroid/content/Context;"); if(appctx.isValid()) qDebug() << "I am valid !"; else qDebug() << "I ain't valid !";
Une idée ?
EDIT 2 : C'est assez bizarre, en fait j'ai déjà réussi à activer le Wifi (pas le hotspot), grâce au code natif suivant :
Si j'essaie maintenant d'activer le Wifi depuis le code Java, en récupérant "wifia" en paramètre :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); QAndroidJniObject serviceField = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Context", "WIFI_SERVICE"); QAndroidJniObject wifia = activity.callObjectMethod("getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", serviceField.object<jobject>()); wifia.callMethod<jboolean>("setWifiEnabled", "(Z)Z", true);
Cela ne marche pas ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 public class ApManager { //Is Wifi on or off ? public static boolean isApOn(WifiManager wifimanager) { return wifimanager.isWifiEnabled(); } //Turn Wifi on or off public static boolean configApState(WifiManager wifimanager, boolean b) { return wifimanager.setWifiEnabled(b); } }
Cela veut dire qu'il y a un problème au niveau du passage de l'atrgument ?
Partager