Activer Hotspot / Récupérer (code c++) le contexte de l'application pour param fonction Java (via JNI)
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 :
Code:
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);
}
} |
C++ code :
Code:
1 2 3 4 5 6 7
| int fibonacci(int n)
{
return QAndroidJniObject::callStaticMethod<jint>("org/app/test/JniMath"
, "fibonacci"
, "(I)I"
, n);
} |
Ceci marche très bien, je vais maintenant essayer de faire la même chose avec les fonctions permettant de configurer le hotspot Wifi.
J'ai une classe Java "ApManager" :
Code:
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;
}
} |
C++ code :
Code:
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);
} |
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)" ?
J'avoue avoir un peu de mal à comprendre...
Je vous remercie d'avance pour vos réponses.
EDIT : J'ai trouvé :
Code:
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 !"; |
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
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 :
Code:
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); |
Si j'essaie maintenant d'activer le Wifi depuis le code Java, en récupérant "wifia" en paramètre :
Code:
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 ne marche pas ?
Cela veut dire qu'il y a un problème au niveau du passage de l'atrgument ?