以编程方式打开/关闭WiFi热点

时间:2017-03-09 14:19:29

标签: c# android unity3d hotspot

我需要帮助创建一个在热点模式下设置Android WiFi的C#脚本。这是我设法创建的代码。

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

一切正常 - 但我在设置SSID和密码时遇到问题。在查看documentation之后,我知道我必须使用设置对象替换我的空值,但我完全不知道如何在Unity中执行此操作。

1 个答案:

答案 0 :(得分:2)

EASY 方式:

首先尝试实例化WifiConfiguration

AndroidJavaObject wifiConfiguration = new AndroidJavaClass("android.net.wifi.WifiConfiguration");

现在您可以在此对象中调用方法并设置/获取字段:

// to set SSID
wifiConfiguration.Set("SSID", meSSID); // string
wifiConfiguration.Set("preSharedKey", mePassword); // string

设置完所有必填字段后,只需调用setWifiApEnabled方法:

wifiManager.Call<bool>("setWifiApEnabled", wifiConfiguration, enabled);

也许你必须设置比这两个更多的字段,但要确认你应该检查source并确保setWifiApEnabled方法做什么内容。

HARD 方式:
(使用反射代码)

使用AndroidJavaObject反射可能有点棘手,因为你必须记住处理每个对象。

从一开始就是这样:

// 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:

我试图找出为什么上面的代码可能不起作用,但对我来说它工作正常(在某些虚拟机和三星Galaxy S5 Neo上测试)

可能是这种情况(我几乎在午夜时发现)是一个密码。
关于 WPA-PSK

的部分中的this wikipedia article
  

也称为WPA-PSK(预共享密钥)模式,专为家庭和小型办公网络而设计,不需要验证服务器。[9]每个无线网络设备使用256位密钥加密网络流量。该密钥可以输入为64个十六进制数字的字符串,也可以输入为8到63个可打印ASCII字符的密码。[10]如果使用ASCII字符,则通过将PBKDF2密钥派生函数应用于密码短语来计算256位密钥,使用SSID作为盐和HMAC-SHA1的4096次迭代。[11] WPA和WPA2都提供WPA-Personal模式。)

我的建议是使用与上面链接的文章相同的密码,以确保它有效。

另外需要注意的是 SSID 部分,其中包含简短但良好的描述here on wikipedia

  

一个常见的,虽然不正确的假设是,SSID是一串人类可读的字符(如ASCII),以NUL字符(如在C字符串中)终止。必须按照它们的原样处理和处理SSID,序列为0-32个八位字节,其中一些可能不是人类可读的

根据我的检查,你不需要在Java或C#中使用null终止你的字符串,因为它将由本机代码处理,但你不应该超过31个字符(32将是空字符)。

我检查了这个:
SSID MeHotSpot
WPA-PSK :5260305714217573