最近在研究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,就都能知作别人的密码了~