问题
I need help in creating a C# script that set a android WiFi in hotspot mode. Here is the code that I managed to create.
public bool setAPEnabled(bool enabled)
{
using (AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity"))
{
try
{
if(isWifiEnabled()==true){
setWifiEnabled(false);
}
using (var wifiManager = activity.Call<AndroidJavaObject>("getSystemService", "wifi"))
{
return wifiManager.Call<bool>("setWifiApEnabled",null, enabled);
}
}
catch (Exception e)
{
}
}
return false;
}
Everything works well - but I have a problem with setting the SSID and password. After reviewing the documentation I know that I have to replace my null value with the settings object, but I completely don't know how to do it in Unity.
回答1:
The EASY way :
Try instantiating the WifiConfiguration first :
AndroidJavaObject wifiConfiguration = new AndroidJavaClass("android.net.wifi.WifiConfiguration");
Now you can call methods and set/get fields within this object :
// to set SSID
wifiConfiguration.Set("SSID", meSSID); // string
wifiConfiguration.Set("preSharedKey", mePassword); // string
After settings all of the required fields just call your setWifiApEnabled
method :
wifiManager.Call<bool>("setWifiApEnabled", wifiConfiguration, enabled);
Maybe you will have to set more fields than these two but to confirm that you should check the source and ensure what setWifiApEnabled
method does internaly.
The HARD way :
( using reflection code )
Using reflection with AndroidJavaObject
can be a bit tricky because you have to remember to dispose every object.
So from the beginning :
// android code for that should look like :
// wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
// but in Unity C# you have to split this into few chunks:
// 1. Get calling class :
using ( AndroidJavaObject classObj = wifiManager.Call<AndroidJavaObject>("getClass") )
{
// classObj should contains your class object
// 2. call get WifiConfiguration class details :
using ( AndroidJavaObject wifiConfiguration = new AndroidJavaObject("setWifiApEnabled") )
{
// 3. Fill that object :
wifiConfiguration.Set("SSID", meSSID); // string
wifiConfiguration.Set("preSharedKey", mePassword); // string
// 4. Get WifiConfiguration class definition
using (AndroidJavaObject wifiCfgClass = wifiConfiguration.Call<AndroidJavaObject>("getClass") )
{
// 5. Get boolean definition
using ( AndroidJavaObject booleanObj = new AndroidJavaObject("java.lang.Boolean") )
{
using ( AndroidJavaObject booleanClass = booleanObj.Call<AndroidJavaObject>("getClass") )
// 6. Get method definition
using ( AndroidJavaObject methodObj = classObj.Call<AndroidJavaObject>("getMethod", "setWifiApEnabled", wifiCfgClass , booleanClass)
{
// 7. Call that method :)
methodObj.Call("invoke", wifiManager, wifiConfiguration, enabled);
}
}
}
}
}
WifiConfiguration :
I was trying to find out why the above code might not work but for me it was working okay ( tested on some virtual machines and Samsung Galaxy S5 Neo ).
What may be the case ( which I found out at almost midnight ) is a passphrase.
According to this wikipedia article in the section about WPA-PSK
Also referred to as WPA-PSK (pre-shared key) mode, this is designed for home and small office networks and doesn't require an authentication server.[9] Each wireless network device encrypts the network traffic using a 256 bit key. This key may be entered either as a string of 64 hexadecimal digits, or as a passphrase of 8 to 63 printable ASCII characters.[10] If ASCII characters are used, the 256 bit key is calculated by applying the PBKDF2 key derivation function to the passphrase, using the SSID as the salt and 4096 iterations of HMAC-SHA1.[11] WPA-Personal mode is available with both WPA and WPA2.)
My suggestion would be to use the same passphrase as in the article linked above to make sure it's valid.
Also another thing to note is the SSID part which has a short but good description here on wikipedia.
A common, albeit incorrect assumption, is that an SSID is a string of human-readable characters (such as ASCII), terminated by a NUL character (as in a C-string). SSIDs must be treated and handled as what they are, a sequence of 0–32 octets, some of which may not be human-readable
From what I've checked you do not need to null-terminate your string within Java or C# because it will be handled by native code but still you should not exceed 31 characters ( 32 will be the null character ).
I checked this with :
SSID:MeHotSpot
WPA-PSK:5260305714217573
来源:https://stackoverflow.com/questions/42697725/turn-on-off-wifi-hotspot-programmatically