Android之WiFi密码查看器

·  阅读 2225

前言

最近在研究WiFi,顺便看了一下WiFi的API文档,然后衍生出一系列的脑洞大开,不过这篇文章不打算讲它的API,感兴趣的可以直接去看它的文档 android.net.wifi
既然能获取到手机连接到的WiFi信息,那么自然也能获取得到连接过的WiFi密码啦,不过前提是你的手机必须有root权限。

先贴个最终的效果图片~~~

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,这里点击允许,反正是自己写的代码,也不怕它会干什么坏事是吧~

我们通过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文件。

好啦,以后再也不怕忘记密码啦,只要是你的WiFi万能钥匙能连得上的WiFi,就都能知道别人的密码了~

分类:
Android
标签:
收藏成功!
已添加到「」, 点击更改