Android之WiFi密碼檢視器

ャAutism゛發表於2019-03-31

前言

最近在研究WiFi,順便看了一下WiFi的API文件,然後衍生出一系列的腦洞大開,不過這篇文章不打算講它的API,感興趣的可以直接去看它的文件 android.net.wifi
既然能獲取到手機連線到的WiFi資訊,那麼自然也能獲取得到連線過的WiFi密碼啦,不過前提是你的手機必須有root許可權。

先貼個最終的效果圖片~~~

Android之WiFi密碼檢視器

1.獲取手機root許可權
現在有很多軟體都可以獲取root,不過我在獲取root的時候是真的心塞,可能是手機太low了,機型不適配,試過很多軟體都不行,最後下載了KingRoot,然後看著它不停的關機開機再關機再開機最後才root成功的(不過過了5分鐘後又打回原形了,對這手機真的無語),不過這5分鐘也已經夠我測試的啦。所以大家如果一直失敗的話也可以嘗試一下KingRoot,當然這也不是百分百成功的。   

2.獲取本地已連線過的WiFi資料
當手機連線過WiFi時,連線的資訊會儲存在手機的/data/misc/wifi/wpa_supplicant.conf檔案裡,但是這個檔案並不能直接開啟,而是需要靠命令列的方式來列印出來,不多說,直接上程式碼~~~

MainActivity.java

//讀取WiFi配置檔案
private static final String CAT_WIFI_CONF = "cat /data/misc/wifi/wpa_supplicant.conf\n";
//退出
private static final String EXIT = "exit\n";

Process process;
DataOutputStream dataOutputStream;
DataInputStream dataInputStream;

StringBuffer wifiConf = new StringBuffer();
private void getWiFiInfo() {
    try {
        //使當前程式獲得root許可權
        process = Runtime.getRuntime().exec("su");
        dataOutputStream = new DataOutputStream(process.getOutputStream());
        dataInputStream = new DataInputStream(process.getInputStream());
        
        //使用cat來列印該檔案的資料
        dataOutputStream.writeBytes(CAT_WIFI_CONF);
        //列印完後退出
        dataOutputStream.writeBytes(EXIT);
        dataOutputStream.flush();

        //讀取位元組並解碼成指定格式的字元
        InputStreamReader inputStreamReader = new InputStreamReader(dataInputStream, "UTF-8");
        //讀取字元流
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

        String line = null;
        //每讀取一行則拼接一次
        while ((line = bufferedReader.readLine()) != null) {
            wifiConf.append(line);
        }
        
        //關閉流並釋放資源
        bufferedReader.close();
        inputStreamReader.close();
        process.waitFor();

    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        if (TextUtils.isEmpty(wifiConf.toString())) {
            tips.setVisibility(View.VISIBLE);
            Toast.makeText(getApplicationContext(), "您還未獲取Root許可權", Toast.LENGTH_LONG).show();
        }
        try {
            if (dataOutputStream != null) {
                dataOutputStream.close();
            }
            if (dataInputStream != null) {
                dataInputStream.close();
            }
            process.destroy();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //新增WiFi資訊
    addWifiList();
}
複製程式碼

我們通過Runtime.getRuntime().exec("su")為當前程式獲得root環境後,當你執行開啟APP後,會彈出一個框,提示你是否允許當前應用使用root,這裡點選允許,反正是自己寫的程式碼,也不怕它會幹什麼壞事是吧~

Android之WiFi密碼檢視器

我們通過cat /data/misc/wifi/wpa_supplicant.conf列印出來的資料正是我們想得到的WiFi資訊,但是由於裡面的資訊包含很多個欄位,所以我們要篩選出我們需要的內容來。 wpa_supplicant.conf包含的欄位為:

network={
    ssid="wifi_SU"
    psk="Su1ddsfs235sdf82"
    key_mgmt=WPA-PSK
    priority=117
    disabled=1
    id_str="%7B%22creatorUid%22%3A%221000%22%2C%22configKey%22%3A%22%fi_SU%5C%22WPA_PSK%22%7D"
}
其中ssid為WiFi名稱,psk為WiFi密碼,key_mgmt為WiFi的加密型別
我們需要的最重要資料就是前兩個欄位了
複製程式碼

3.建立儲存的物件並新增資料
當知道我們想要的資訊後,就可以新增進我們的列表裡的,首先需要建立一個bean類儲存我們要新增的內容,這個很簡單,就直接貼程式碼了:

WiFiInfo.java

public class WiFiInfo {
    private String name;
    private String pwd;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}
複製程式碼

然後就可以往裡面新增資料啦~~

private List<WiFiInfo> lists;

//通過建立一個正規表示式來匹配是否有需要的欄位,有則進行下一步操作,慢慢看就能懂,不作解釋
private void addWifiList() {
    Pattern network = Pattern.compile("network=\\{([^\\}]+)\\}", Pattern.DOTALL);
    Matcher networkMatcher = network.matcher(wifiConf.toString());
    WiFiInfo wifiInfo;
    while (networkMatcher.find()) {
        String networkBlock = networkMatcher.group();
        Pattern ssid = Pattern.compile("ssid=\"([^\"]+)\"");
        Matcher ssidMatcher = ssid.matcher(networkBlock);
        if (ssidMatcher.find()) {
            wifiInfo = new WiFiInfo();
            wifiInfo.setName(ssidMatcher.group(1));
            Pattern psk = Pattern.compile("psk=\"([^\"]+)\"");
            Matcher pskMatcher = psk.matcher(networkBlock);
            if (pskMatcher.find()) {
                wifiInfo.setPwd(pskMatcher.group(1));
            } else {
                wifiInfo.setPwd("無密碼");
            }
            lists.add(wifiInfo);
        }
    }
    // 列表倒序,看著方便~
    Collections.reverse(lists);
    adapter.notifyDataSetChanged();
}
複製程式碼

4.顯示資料
新增完之後就可以顯示資料了,我這裡的activity_main.xml使用的是recyclerview,比較簡單,然後adapter我使用的是BaseRecyclerViewAdapterHelper,當然我的重點是獲取WiFi密碼,所以其他程式碼能簡單就簡單啦~下面我就直接貼出這些程式碼了:

activity_main.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/wifi_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <!--當未獲取root許可權時的tips-->
    <TextView
        android:id="@+id/tips"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="請先獲取Root許可權"
        android:layout_centerInParent="true"
        android:visibility="gone"/>

</RelativeLayout>
複製程式碼

WiFiAdapter.java

public class WiFiAdapter extends BaseQuickAdapter<WiFiInfo, BaseViewHolder> {

    public WiFiAdapter(int layoutResId, @Nullable List<WiFiInfo> data) {
        super(layoutResId, data);
    }
    
    @Override
    protected void convert(BaseViewHolder helper, WiFiInfo item) {
        helper.setText(R.id.item_name, "名稱:" + item.getName())
                .setText(R.id.item_pwd, "密碼:" + item.getPwd());
    }
}
複製程式碼

item_wifi.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">
        <TextView
            android:id="@+id/item_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/wifi_name" />
        <TextView
            android:id="@+id/item_pwd"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:text="@string/wifi_pwd" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="#30000000" />
        
</LinearLayout>
複製程式碼

然後剩下的就是在MainActivity中配置adapter啦,這些就不貼了,比較簡單。當你手機未獲得root許可權時,則列表會為空,因為你無法讀取wpa_supplicant.conf檔案。

Android之WiFi密碼檢視器

好啦,以後再也不怕忘記密碼啦,只要是你的WiFi萬能鑰匙能連得上的WiFi,就都能知道別人的密碼了~

相關文章