Включить / выключить точку доступа WiFi программно

Мне нужна помощь в создании сценария C#, который устанавливает Android-WiFi в режиме точки доступа. Вот код, который мне удалось создать.

    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 и пароля. Изучив документацию, я знаю, что мне нужно заменить свое нулевое значение на объект настроек, но я совершенно не знаю, как это сделать в Unity.

1 ответ

Решение

ПРОСТОЙ способ:

Попробуйте создать экземпляр 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);

Возможно, вам придется установить больше полей, чем эти два, но для подтверждения того, что вы должны проверить источник и убедиться, что setWifiApEnabled метод делает внутренне.


Твердый путь:
(используя код отражения)

Используя отражение с 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);
                }
            }
        }
    }
}

Конфигурация Wifi:

Я пытался выяснить, почему приведенный выше код может не работать, но у меня он работал нормально (проверено на некоторых виртуальных машинах и Samsung Galaxy S5 Neo).

Что может быть случай (который я узнал почти в полночь) является парольная фраза.
Согласно этой статье в Википедии в разделе о WPA-PSK

Также называется режимом WPA-PSK (предварительный общий ключ), он предназначен для домашних и небольших офисных сетей и не требует сервера аутентификации.[9] Каждое беспроводное сетевое устройство шифрует сетевой трафик с использованием 256-битного ключа. Этот ключ может быть введен либо в виде строки из 64 шестнадцатеричных цифр, либо в виде пароля от 8 до 63 печатных символов ASCII.[10] Если используются символы ASCII, 256-битный ключ вычисляется путем применения функции получения ключа PBKDF2 к ключевой фразе с использованием SSID в качестве соли и 4096 итераций HMAC-SHA1.[11] Персональный режим WPA доступен как для WPA, так и для WPA2.)

Я бы предложил использовать ту же фразу-пароль, что и в статье, приведенной выше, чтобы убедиться, что она действительна.

Еще одна вещь, которую стоит отметить, это часть SSID, которая имеет краткое, но хорошее описание здесь, в Википедии.

Распространенным, хотя и неверным предположением, является то, что SSID - это строка читаемых человеком символов (таких как ASCII), оканчивающаяся символом NUL (как в C-строке). SSID должны обрабатываться и обрабатываться как то, что они представляют собой последовательность из 0–32 октетов, некоторые из которых могут не читаться человеком

Из того, что я проверил, вам не нужно заканчивать нулем вашу строку в Java или C#, потому что она будет обрабатываться собственным кодом, но все равно вы не должны превышать 31 символ ( 32 будет нулевым символом).

Я проверил это с:
SSID: MeHotSpot
WPA-PSK: 5260305714217573

Другие вопросы по тегам