Всем снова привет! Давно я ничего не писал и вот решил сегодня выдать новый перл (:
Недавно мне нужно было сделать проект в котором приложение подключается к конкретной сети и делает кое какие манипуляции, долго колупался и пытался подключиться по SSID к своей домашней сети но так и не вышло, на stack overflow куча ответов где говорят что это возможно но у меня не вышло, и тогда я попробовал подключиться к MAC своего компьютера и все получилось, девайс после нажатия на кнопку подключался к нужной сети.
Так вот собственно как я это сделал сегодня и хочу рассказать.
Так сложилось что что-бы подключиться к сети нужно сперва ее просканировать классом ScanResult который выведет вам полный список доступных Wifi точек. Потом нужно найти нужную сеть и достать ее BSSID — это по простому MAC адрес компьютеру к которому хотим подключиться. Сперва я приведу пример как это сделать без пароля, а потом просто добавлю строчку которая добавляет пароль к конкретной сети.
У нас будет всего лишь один класс который будет выполнять работу, еще будет подкласс рессивер который будет коннектиться к нужной нам сети.
Для начала давайте создадим разметку и добавим препишены для приложения в манифесте. И так сначала разметка. У нас будет всего два объекта, EditText и Bitton по нажатию на которую будет производиться подключение к имени нужной сети которое вы введете в EditText.
activity_main.xml
А так же нам нужно добавить кучу премишенов для того что бы можно было работать с вайфай, интернетом, регулировать состояние вайфая, доступ к вайфаю и так далее.
Вот так будет выглядеть Манифест после редактирования:
AndroidManifest.xml
С настройками для работы мы закончили, так же скорей всего если у вас обновленный Eclipse вам понадобиться appcompat_v7 который Eclipse создает теперь после каждого создания нового проекта, это жутко бесить но без него работать наперекор всему отказывается, проект выдает кучи ошибок и все. Так что я его прикреплю к проекту как дополнительную библиотеку, и на гите он будет лежать вместе с проектом.
Теперь можем смело вставлять в MainActivity наш код который подключается к конкретной точке.
MainActivity.java
Думаю комментарии тут совершенно лишними не будут. Что мы тут делаем? В первую очередь мы создали кучу переменных для работы с Wifi, такие как конфигурации и менеджеры, они нам дают возможность полностью командовать нашим Wifi в телефоне \ планшете.
Далее мы все это инициализируем в методе init(). После чего в методе onCreate() мы сперва вызываем этот init(), а после обрабатываем нажатие на кнопку и после нажатия вызываем метод и делаем нашу булевую переменную активной которая запускает рессивер.
Все получается запутанно, а это только начало (: Думаю проследить в коде будет проще, там такие же комментарии.
Дальше переходим в сам рессивер. В нем мы сканируем все сети WiFi и получаем кокретные их имена
дальше при помощи ифа мы вытаскиваем нужное нам имя,
и подключаемся к той сети имя которой похоже на введенное из EditText
Остальные параметры важны но самое важное в принципе я описал.
Все это мы делаем в рессивере для того что бы выполнялось оно в отдельном потоке и не захламляло UI поток, да и без отдельного потока приложение просто падает с NullPointerExeption. Так что вот такие пироги.
В итоге вы должны после нажатия кнопку подключаться к нужной сети.
Исходники:
Недавно мне нужно было сделать проект в котором приложение подключается к конкретной сети и делает кое какие манипуляции, долго колупался и пытался подключиться по SSID к своей домашней сети но так и не вышло, на stack overflow куча ответов где говорят что это возможно но у меня не вышло, и тогда я попробовал подключиться к MAC своего компьютера и все получилось, девайс после нажатия на кнопку подключался к нужной сети.
Так вот собственно как я это сделал сегодня и хочу рассказать.
Так сложилось что что-бы подключиться к сети нужно сперва ее просканировать классом ScanResult который выведет вам полный список доступных Wifi точек. Потом нужно найти нужную сеть и достать ее BSSID — это по простому MAC адрес компьютеру к которому хотим подключиться. Сперва я приведу пример как это сделать без пароля, а потом просто добавлю строчку которая добавляет пароль к конкретной сети.
У нас будет всего лишь один класс который будет выполнять работу, еще будет подкласс рессивер который будет коннектиться к нужной нам сети.
Для начала давайте создадим разметку и добавим препишены для приложения в манифесте. И так сначала разметка. У нас будет всего два объекта, EditText и Bitton по нажатию на которую будет производиться подключение к имени нужной сети которое вы введете в EditText.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:ems="10"
android:hint="Enter wifi point name" >
<requestFocus />
</EditText>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText1"
android:layout_below="@+id/editText1"
android:text="Connect" />
</RelativeLayout>
А так же нам нужно добавить кучу премишенов для того что бы можно было работать с вайфай, интернетом, регулировать состояние вайфая, доступ к вайфаю и так далее.
Вот так будет выглядеть Манифест после редактирования:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.connecttowifi"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-feature android:name="android.hardware.wifi" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.connecttowifi.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
С настройками для работы мы закончили, так же скорей всего если у вас обновленный Eclipse вам понадобиться appcompat_v7 который Eclipse создает теперь после каждого создания нового проекта, это жутко бесить но без него работать наперекор всему отказывается, проект выдает кучи ошибок и все. Так что я его прикреплю к проекту как дополнительную библиотеку, и на гите он будет лежать вместе с проектом.
Теперь можем смело вставлять в MainActivity наш код который подключается к конкретной точке.
MainActivity.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends ActionBarActivity {
private WifiManager wifiManager;
private WifiConfiguration wifiConfig;
private WifiReceiver wifiResiver;
private boolean wifiEnabled;
private EditText url;
private Button conect;
private boolean isClick = false;
public void init() {
conect = (Button) findViewById(R.id.button1);
url = (EditText) findViewById(R.id.editText1);
// создаем новый объект для подключения к конкретной точке
wifiConfig = new WifiConfiguration();
// сканнер вайфая который нам будет помогать подключаться к нужной точке
wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
//узнаем включен вайфай или нет
wifiEnabled = wifiManager.isWifiEnabled();
//наш рессивер который будем подключать нас столько сколько нам понадобиться, пока не будет подключена нужная точка
wifiResiver = new WifiReceiver();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// метод который инициализирует все что нам нужно
init();
conect.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//если файвай включен то ничего не делаем иначе включаем его
if(!wifiEnabled) {
wifiManager.setWifiEnabled(true);
}
//запускаем сканнер вайфая, и подключаемся если подкходящая нам есть есть
scheduleSendLocation();
//запускаем рессивер
isClick = true;
}
});
}
/*
* Подключаемся к wifi указаному в edit text
* */
public void scheduleSendLocation() {
registerReceiver(wifiResiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
wifiManager.startScan();
}
protected void onPause() {
//если приложение уходит в фон или например выключаем его вообще, то и рессивер тормазим и выключаем.
unregisterReceiver(wifiResiver);
super.onPause();
}
public void onResume() {
//если кликнули то запускаем рессивер, если же isClick = false то ждем пока кнопка будет нажата
if(isClick)
registerReceiver(wifiResiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
super.onResume();
}
/*
* Рессивер который каждый раз запускает сканнер сети
* */
public class WifiReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context c, Intent intent) {
//сканируем вайфай точки и узнаем какие доступны
List<ScanResult> results = wifiManager.getScanResults();
//проходимся по всем возможным точкам
for (final ScanResult ap : results) {
//ищем нужную нам точку с помощью ифа, будет находить то которую вы ввели
if(ap.SSID.toString().trim().equals(url.getText().toString().trim())) {
// дальше получаем ее MAC и передаем для коннекрта, MAC получаем из результата
//здесь мы уже начинаем коннектиться
wifiConfig.BSSID = ap.BSSID;
wifiConfig.priority = 1;
wifiConfig.allowedKeyManagement.set(KeyMgmt.NONE);
wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wifiConfig.status = WifiConfiguration.Status.ENABLED;
//получаем ID сети и пытаемся к ней подключиться,
int netId = wifiManager.addNetwork(wifiConfig);
wifiManager.saveConfiguration();
//если вайфай выключен то включаем его
wifiManager.enableNetwork(netId, true);
//если же он включен но подключен к другой сети то перегружаем вайфай.
wifiManager.reconnect();
break;
}
}
}
}
}
Думаю комментарии тут совершенно лишними не будут. Что мы тут делаем? В первую очередь мы создали кучу переменных для работы с Wifi, такие как конфигурации и менеджеры, они нам дают возможность полностью командовать нашим Wifi в телефоне \ планшете.
Далее мы все это инициализируем в методе init(). После чего в методе onCreate() мы сперва вызываем этот init(), а после обрабатываем нажатие на кнопку и после нажатия вызываем метод и делаем нашу булевую переменную активной которая запускает рессивер.
Все получается запутанно, а это только начало (: Думаю проследить в коде будет проще, там такие же комментарии.
Дальше переходим в сам рессивер. В нем мы сканируем все сети WiFi и получаем кокретные их имена
List<ScanResult> results = wifiManager.getScanResults();
//проходимся по всем возможным точкам
for (final ScanResult ap : results) {
//здесь можно вывести Toast с именами, примерно вот так
Toast.makeText(MainActivity.this, ap.SSID, Toast.LENGTH_LONG).show();
// тут иф
}
дальше при помощи ифа мы вытаскиваем нужное нам имя,
if(ap.SSID.toString().trim().equals(url.getText().toString().trim())) { ... }
и подключаемся к той сети имя которой похоже на введенное из EditText
wifiConfig.BSSID = ap.BSSID;
Остальные параметры важны но самое важное в принципе я описал.
Все это мы делаем в рессивере для того что бы выполнялось оно в отдельном потоке и не захламляло UI поток, да и без отдельного потока приложение просто падает с NullPointerExeption. Так что вот такие пироги.
В итоге вы должны после нажатия кнопку подключаться к нужной сети.
Комментариев нет:
Отправить комментарий