最近在研究WiFi,順便看了一下WiFi的API文檔,而後衍生出一系列的腦洞大開,不過這篇文章不打算講它的API,感興趣的能夠直接去看它的文檔 android.net.wifi 。
既然能獲取到手機鏈接到的WiFi信息,那麼天然也能獲取獲得鏈接過的WiFi密碼啦,不過前提是你的手機必須有root權限。html
先貼個最終的效果圖片~~~java
1.獲取手機root權限
如今有不少軟件均可以獲取root,不過我在獲取root的時候是真的心塞,多是手機太low了,機型不適配,試過不少軟件都不行,最後下載了KingRoot,而後看着它不停的關機開機再關機再開機最後才root成功的(不過過了5分鐘後又打回原形了,對這手機真的無語),不過這5分鐘也已經夠我測試的啦。因此你們若是一直失敗的話也能夠嘗試一下KingRoot,固然這也不是百分百成功的。 android
2.獲取本地已鏈接過的WiFi數據
當手機鏈接過WiFi時,鏈接的信息會保存在手機的/data/misc/wifi/wpa_supplicant.conf文件裏,可是這個文件並不能直接打開,而是須要靠命令行的方式來打印出來,很少說,直接上代碼~~~正則表達式
MainActivity.javabash
//讀取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,這裏點擊容許,反正是本身寫的代碼,也不怕它會幹什麼壞事是吧~app
咱們經過cat /data/misc/wifi/wpa_supplicant.conf打印出來的數據正是咱們想獲得的WiFi信息,可是因爲裏面的信息包含不少個字段,因此咱們要篩選出咱們須要的內容來。 wpa_supplicant.conf包含的字段爲:ide
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.javaui
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;
}
}
複製代碼
而後就能夠往裏面添加數據啦~~this
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文件。
好啦,之後不再怕忘記密碼啦,只要是你的WiFi萬能鑰匙能連得上的WiFi,就都能知作別人的密碼了~