2014/02/13

[Android] 用WifiManager來get wifi的SSID, power level和所使用的channel基本資訊

***2017/01/06更新***
請參考 [Android] WifiManager for Android M or later
******

在行動裝置上最常用到的莫過於是網路了,其中因為Wi-Fi在很多政府機關、公共場所都是免費可使用的,因此Wi-Fi應該算得上是在行動裝置中很重要的一部分。

Android本身有提供WifiInfoWifiManager兩個類別提供我們來使用及控制Wi-Fi,除了可以開啟、關閉Wi-Fi之外,也可以取得目前的位置有哪些Wi-Fi網路存在、訊號強度如何,所使用的頻帶有否跟其他Wi-Fi網路重疊,也可以取得目前連線的Wi-Fi IP資訊、速度等資訊。

以下利用WifiInfo和WifiManager類別簡單的開發一個查詢目前周遭有哪些Wi-Fi網路,取得服務設定的識別碼(Service Set Identifie, SSID),並且回報最強的訊號是哪一個SSID,所使用的是哪個頻段(2.4G/5G)等等。


其中在實作上,一開始要先判斷裝置的Wi-Fi是否有開啟,如果沒有就開啟Wi-Fi
boolean
setWifiEnabled(boolean enabled)
Enable or disable Wi-Fi.
接著Scan目前有的Wi-Fi網路
boolean
Request a scan for access points.
取得Scan的結果,並且用List<ScanResult>的資料結構存取下來
Return the results of the latest access point scan.
用一個HashMap<String, String>的資料結構把每個資訊put到ArrayList裡面,簡單的把每個搜尋到的網路依據Power Level大小作排序後,再利用SimpleAdapter把Wi-Fi的SSID、Power Level和Frequency的資料連結到三個TextView的layout xml,最後連結到ListVier並且show出來。
Fields
public String
The address of the access point.
public String
The network name.
public String
Describes the authentication, key management, and encryption schemes supported by the access point.
public int
The frequency in MHz of the channel over which the client is communicating with the access point.
public int
The detected signal level in dBm.
public long
Time Synchronization Function (tsf) timestamp in microseconds when this result was last seen.

因為需要用到Wi-Fi的權限,所以在AndroidManifest.xml中要加入
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
底下為程式碼
MainActivity.java
package com.example.androidwifi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
  WifiManager wifi;
  ListView lv;
  TextView textStatus;
  Button buttonScan;
  int size = 0;
  List results;
  ArrayList> arraylist = new ArrayList>();
  SimpleAdapter adapter;
	
  private static final Map wifichannel = new HashMap();
  static{
   wifichannel.put("2412", "2.4G Ch01");wifichannel.put("2417", "2.4G Ch02");
   wifichannel.put("2422", "2.4G Ch03");wifichannel.put("2427", "2.4G Ch04");
   wifichannel.put("2432", "2.4G Ch05");wifichannel.put("2437", "2.4G Ch06");
   wifichannel.put("2442", "2.4G Ch07");wifichannel.put("2447", "2.4G Ch08");
   wifichannel.put("2452", "2.4G Ch09");wifichannel.put("2457", "2.4G Ch10");
   wifichannel.put("2462", "2.4G Ch11");wifichannel.put("2467", "2.4G Ch12");
   wifichannel.put("2472", "2.4G Ch13");wifichannel.put("2484", "2.4G Ch14");
  }
	
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
        
    textStatus = (TextView) findViewById(R.id.textView2);
    buttonScan = (Button) findViewById(R.id.button1);
    lv = (ListView) findViewById(R.id.listView1);
        
    wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    if(wifi.isWifiEnabled()==false)
    {
      AlertDialog.Builder dialog = new AlertDialog.Builder(this);
      dialog.setTitle("Remind");
      dialog.setMessage("Your Wi-Fi is not enabled, enable?");
      dialog.setIcon(android.R.drawable.ic_dialog_info);
      dialog.setCancelable(false);
      dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
				
        @Override
        public void onClick(DialogInterface dialog, int which) {
          // TODO Auto-generated method stub
          wifi.setWifiEnabled(true);
          Toast.makeText(getApplicationContext(), "wifi is disabled..making it enabled", Toast.LENGTH_LONG).show();	
        }
      });
      dialog.show();
    }

  this.adapter = new SimpleAdapter(MainActivity.this, arraylist, R.layout.list, new String[] {"ssid","power","freq"}, new int[] {R.id.ssid, R.id.power, R.id.freq});
  lv.setAdapter(adapter);
        
  registerReceiver(new BroadcastReceiver() {
			
    @Override
    public void onReceive(Context context, Intent intent) {
      // TODO Auto-generated method stub
      results = wifi.getScanResults();
      size = results.size();
    }
  }, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
        
  buttonScan.setOnClickListener(new OnClickListener() {
			
    @Override
    public void onClick(View v) {
      // TODO Auto-generated method stub
        arraylist.clear();
        wifi.startScan();
				
        Toast.makeText(MainActivity.this, "Scanning..."+size, Toast.LENGTH_LONG).show();
        try {
          size = size -1;
          while(size >= 0)
          {
            HashMap item = new HashMap();
            item.put("ssid", results.get(size).SSID);
            item.put("power", new String(results.get(size).level+" dBm"));
            String wifichn = wifichannel.containsKey(new String(""+results.get(size).frequency))? wifichannel.get(new String(""+results.get(size).frequency)):"5G";
            item.put("freq", wifichn);
            arraylist.add(item);
            size--;
            adapter.notifyDataSetChanged();
          }
          Collections.sort(arraylist, new Comparator>() {

            @Override
            public int compare(HashMap lhs, HashMap rhs) {
              // TODO Auto-generated method stub
              return ((String) lhs.get("power")).compareTo((String) rhs.get("power"));
            }
          });
          textStatus.setText(arraylist.get(0).get("ssid"));
        } catch (Exception e) {
          // TODO: handle exception
        }
      }
    });
       
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }   
}
一些xml檔案的物件Layout設定
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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/button1"
        android:layout_marginTop="46dp"
        android:background="#ff8" >
    </ListView>

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="@string/wifi_ssid" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/listView1"
        android:layout_below="@+id/button1"
        android:text="@string/wifi_analysis" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignTop="@+id/textView1"
        android:text="@string/start_scan" />

</RelativeLayout>
list.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/ssid"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:text="TextView" />

    <TextView
        android:id="@+id/power"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/ssid"
        android:layout_below="@+id/ssid"
        android:text="TextView" />

    <TextView
        android:id="@+id/freq"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/power"
        android:layout_alignBottom="@+id/power"
        android:layout_centerHorizontal="true"
        android:text="TextView" />

</RelativeLayout>

GitHub AndroidWifi

執行的結果如下
一開始開啟裝置的Wi-Fi

然後按下Start Scan的按鈕開始搜尋附近的Wi-Fi網路

最後把搜尋的結果列出來,並且依照Power Level大小排列,並選出最大Power的SSID無線網路

***2017/01/06更新***
請參考 [Android] WifiManager for Android M or later
******

沒有留言:

張貼留言