Подписаться на получение новых статей на почту:

Просмотр и состояние Wi-Fi сетей из Android-приложения. Шаг № 83

Всем привет. Рассмотрев в прошлой статье №82 способ использования интерактивного рисунка для нашего Android-приложения Smart House, теперь научимся просматривать состояние сети wi-fi включение/выключение, а также список доступных сетей используя компонент BroadcastReceiver. Рассмотрим способы диагностики, отладки программы, используя логи и всплывающие сообщения.

Научимся слушать внешние события и производить реакцию на них, используя BroadcastReceiver, который выполняет действие по получению Intent (намерение), который, в свою очередь, является механизмом по получению одной операции а также для объявления о запуске активности или сервиса, направленных на выполнение каких-либо действий (как правило, речь о работе с определенной частью данных) или для передачи уведомлений о том, что произошло некое событие. В нижеприведенном коде мы используем логи и всплывающие сообщения для отладки программы. Для использование первого метод требует на вход  тэг  и  текст  сообщения, например Log.d (TAG, “Hello”) с фильтром debug. Тэг представляет собой метку для облегчения поиска в дальнейшем. И с помощью окошка Logcat в 1Android Studio или Eclipse можем отслеживать данные сообщения. У меня почему то они не всегда срабатывают, поэтому полезно будет еще применить всплывающие сообщения с помощью статического метода makeText, который создает View-элемент Toast.

Toast.makeText(context, text, duration).show();

где context – используем текущую Activity, т.е. this; - text – текст, который надо показать;— duration – продолжительность показа (Toast.LENGTH_LONG — длинная, Toast.LENGTH_SHORT — короткая); - show () – отображение на экране.

Ниже создаем класс WiFiMonitor, который наследуется от BroadcastReceiver и следит за состоянием сети и получает ее описание. Используем логи и всплывающие сообщения.

class WiFiMonitor extends BroadcastReceiver {
   private String LOG_TAG = "WiFiMonitor"; 
   @Override  
   public void onReceive(Context context, Intent intent) {//Вызывается, когда BroadcastReceiver получает трансляцию Intent.         
      String action = intent.getAction();//Метод getAction(),для поиска действий, связанных с намерением. Считываем действие        
      Log.d(LOG_TAG, action);//Выводим действие в лог, с фильтром debug. В окне LogCat.  
      ConnectivityManager cm = (ConnectivityManager)context.getSystemService(CONNECTIVITY_SERVICE);//Получаем объект класса ConnectivityManager, который следит за состоянием сети   
      NetworkInfo activeNetwork = cm.getActiveNetworkInfo();//Получаем объект класса NetworkInfo для получения описания состояния сети     
      boolean isConnected = activeNetwork != null &&  activeNetwork.isConnectedOrConnecting();//Проверяем подключение     
      Log.d(LOG_TAG,"isConnected: "+isConnected);//Выводим состояние сети true or false  
      Toast.makeText(context, "isConnected: "+isConnected, Toast.LENGTH_LONG).show();//Всплывающее сообщение

Ниже на рисунке пример работы на эмуляторе и скриншот реального девайса:

isConncted_emul

connect-wi-fi_emul

Выводим состояние сети либо wi–fi либо мобильный интернет.

 

 

 

 

 

 

 if (!isConnected) 
     return;   
 boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;//Проверяем это Wifi или нет.        
 Log.d(LOG_TAG,"isWiFi: "+isWiFi);//Выводим состояние сети  
 Toast.makeText(context, "isWiFi: "+isWiFi, Toast.LENGTH_LONG).show();

Ниже на рисунках пример работы:

isWiFi_emul

wi-fi

if (!isWiFi)   
   return; 
WifiManager wifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);// Используем getSystemService (Class) для извлечения WifiManager для управления доступом Wi-Fi.
WifiInfo connectionInfo = wifiManager.getConnectionInfo();//Возвращает динамическую информацию о текущем соединении Wi-Fi, если таковая активна.  
Log.d(LOG_TAG,connectionInfo.getSSID());  
Toast.makeText(context, "Connected to Internet: "+connectionInfo.getSSID(), Toast.LENGTH_LONG).show();   
  }
}

Ниже на рисунках пример работы:

android_wifi

wi-fi-zyxel

Хочется добавить что эмулятор не поддерживает некоторые функции устройства , а именно (https://developer.android.com/studio/run/emulator.html):
What's not supported
· Wi-Fi (except API level 25 system images do support Wi-Fi);
· Bluetooth;
· NFC;
· SD card insert/eject;
· Device-attached headphones;
· USB;
Поэтому мы использовали API level 25, для эмулирования WI-FI. На рисунках ниже API 27 может показывать только состояние сети мобильного интернета, API25,в дополнение, имеет поддержку WI_FI.

connect_emul

wi-fi_emul

Теперь в методе onCreate, который отвечает за установку параметров и инициализации активности, переопределим методы для выше описанного класса. Зарегистрируем объект данного класса в системе, и с помощью фильтра IntentFilter получаем необходимое событие, а именно изменение сетевого подключения. Если параметры нашего Intent совпадают с условиями этого фильтра, то Activity вызывается. Ниже код.

public void onCreate() {  
   super.onCreate();   
   mWiFiMonitor = new WiFiMonitor();
   IntentFilter intentFilter = new IntentFilter();  
   intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);//Произошло изменение сетевого подключения.     registerReceiver(mWiFiMonitor,intentFilter);
}
@Override
  public void onTerminate() {  
    super.onTerminate();  
    unregisterReceiver(mWiFiMonitor);
}

Этот метод предназначен для использования в эмулируемых средах обработки. Он никогда не будет вызываться на реальном устройстве Android, где процессы удаляются, просто убивая их. При этом не выполняется код пользователя (включая этот обратный вызов).
Если вы переопределите этот метод, вы должны выполнить вызов суперкласса.
Для просмотра сетей Wi-Fi и вывода информации создадим еще один класс и наследуемся от BroadcastReceiver.

static class ScanReceiver extends BroadcastReceiver { 
    private String LOG_TAG = " ";    
  @Override   
    public void onReceive(Context context, Intent intent) { 
       WifiManager wifi = (WifiManager) context.getSystemService(WIFI_SERVICE);//Извлекаем WifiManager для управления доступом Wi-Fi.    
       List scanResultList = wifi.getScanResults();//Возвращает результаты последнего сканирования точки доступа.  
       for (Object scanResult : scanResultList){ 
           Log.d(LOG_TAG,scanResult.toString());    
           Toast.makeText(context, "click"+scanResult.toString(), Toast.LENGTH_LONG).show();    
   }   context.unregisterReceiver(this);    
 }
}

И будем производить поиск сетей по нажатию на кнопку. Ниже код и рисунок работы на эмуляторе и реальном устройстве. Работу с кнопкой в Android-приложении мы частично рассматривали в прошлой статье а также в приложении подключения AVR к ОС Android.

button.setOnClickListener(new View.OnClickListener(){ 
  @Override  
   public void onClick(View v) {   
      final WifiManager wifi = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);  
      ScanReceiver scanReceiver = new ScanReceiver();  
      registerReceiver(scanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));   
      wifi.startScan();         } });
   requestPermissions(new String[{Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION},1);
}

skan_wi_fi scan

 

 

 

 

 

 

Для работы данного приложения необходимо внести разрешения в файл Манифеста, , в корневом теге <manifest>.

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

Разрешения описывают сами себя. При запуске только этих разрешений мы можем получить следующее сообщение в логе:
E/WifiService: Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION   permission to get scan results
Данных разрешений хватало до Android 6.0 ApI23. C появлением данного API и выше политика изменилась. Теперь необходимо добавить

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

где первый получает доступ к приблизительному местоположению, второй — приложение сможет получать доступ к точному местоположению. Два последних разрешения являются опасными.
И в методе OnCreate пропишем следующую строку.

requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},1);

Здесь мы запрашиваем разрешение для данного приложения. Эти разрешения должны запрашиваться в манифесте и должны иметь уровень защиты #PROTECTION_DANGEROUS, опасный, независимо от того, объявлены ли они платформой или сторонним приложением. Пользователи предоставляют разрешения для приложений во время работы приложения, а не при установке приложения. Этот подход упрощает процесс установки приложения, поскольку пользователю не нужно предоставлять разрешения при установке или обновлении приложения. Рисунки ниже:
reguestrequest_emul
Ниже исходники и ресурсы.

Состояние сетей и Wi-Fi ( Скачали: 15 чел. ) 

scan-wi_fi_emul Все, добавляем код в наше приложение SmartHouse. Теперь мы имеем доступ к сетям. В последующем мы выведем сети Wi-Fi в листинг и научимся выбирать определенную и подключаться к ней. В следующей статье вернемся к контроллеру STM32 и свяжем его с ESP8266, который по нашей задумке будет управляющим элементом в системе умный дом. На этом сегодня и остановимся. Всем пока.

Просмотрено 445 раз.

Я на Google+

Добавить комментарий

Ваш e-mail не будет опубликован.

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Subscribe without commenting