一、需求分析

最近电脑需要连接WiFi,却发现WiFi密码给忘记了。而手机里有保存过的WiFi密码,但是在手机的设置界面看不到。

虽然已经有一些可以查看WiFi密码的app,但是主要还是担心密码被那些app传到后台去。还是自己写一个比较放心。而且用app查看只需要点击一下,要比直接查找系统里保存了密码的文件更加方便。

二、主要功能实现

2.1 读取系统文件

Android系统保存了WiFi密码的文件保存在/data/misc/wifi/wpa_supplicant.conf中[1],通过在代码中运行命令行程序‘cat’来读取文件[3][4]。

String commandResult=commandForResult("cat /data/misc/wifi/wpa_supplicant.conf");
public String commandForResult(String command) { try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = null;
outputStream = new DataOutputStream(process.getOutputStream());
outputStream.writeBytes(command+"\n");
outputStream.flush();
outputStream.writeBytes("exit\n");
outputStream.flush(); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder total = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
total.append(line);
total.append("\n");
}
return total.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "error";
}
}

2.2 对WiFi信息按照priority由大到小排序

wpa_supplicant.conf文件中保存的Wifi信息主要采用如下格式,每个网络信息以network开头。key_mgmt=NONE表示网络不需要密码。当key_mgmt=WPA-PSK时,会通过psk字段来标识密码信息。

目前看到的手机里wpa_supplicant.conf文件中并没有对不同的网络按照priority的值进行排序。而那些经常用的网络priority比较高,被放在了文件的后面,因此考虑对网络信息按照priority由大到小进行排序。

    String sortByPriority(String input){
String [] stringPerLine=input.split("\n");
ArrayList<NetworkPara> list=new ArrayList<MainActivity.NetworkPara>();
int start=0,end=0;
NetworkPara networkPara = null;
for (int i = 0; i < stringPerLine.length; i++) {
if (stringPerLine[i].contains("network={")) {
start=1;
end=0;
networkPara=new NetworkPara();
networkPara.paraString="";
}
if (start==1) {
if (networkPara!=null) {
networkPara.paraString=networkPara.paraString.concat(stringPerLine[i])+"\n";
}
if (stringPerLine[i].contains("priority")) {
String []prioSplit=stringPerLine[i].split("=");
networkPara.priority=Integer.parseInt(prioSplit[prioSplit.length-1]);
}
if (stringPerLine[i].contains("}")) {
start=0;
end=1;
}
}
if (end==1) {
list.add(networkPara);
}
}
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Comparable) ((NetworkPara) (o2)).priority)
.compareTo(((NetworkPara) (o1)).priority);
}
}); String result="";
for (int i = 0; i < list.size(); i++) {
result=result.concat(list.get(i).paraString);
}
return result;
}

2.3 支持按照字符串进行搜索

字符串搜索的入口选择采用在actionar上增加搜索按钮,根据输入字符串进行逐行匹配。当有多个匹配结果时,在界面中显示前进后退按钮,以支持前后内容的选择。

2.3.1 Actionbar中显示搜索按钮

首先在menu item生成时增加搜索按钮,然后主activity implements OnQueryTextListener并实现onQueryTextChange和onQueryTextSubmit方法[2]。

    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); searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.menu_search));
searchView.setOnQueryTextListener(this);
return true;
}
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.zhigao.all_connect.MainActivity" > <item android:id="@+id/menu_search"
android:title="Search"
app:showAsAction="always"
app:actionViewClass="android.support.v7.widget.SearchView"
/>
</menu>

2.3.2 字符串匹配与结果保存

用户输入完待搜索的字符点击搜索之后,执行onQueryTextSubmit函数。采用stringSplit[i].toLowerCase().contains(arg0.toLowerCase())进行不区分大小写的匹配操作。使用scrollTo函数进行scrollview的跳转[5]。

    public boolean onQueryTextSubmit(String arg0) {
// TODO Auto-generated method stub
Log.v(TAG, "querysubmit"+arg0);
matchedLine.clear();
String []stringSplit=sortedResult.split("\n");
for (int i = 0; i < stringSplit.length; i++) {
//case insensitive match
if (stringSplit[i].toLowerCase().contains(arg0.toLowerCase())) {
matchedLine.add(i);
}
} if (matchedLine.size()==0) {
Toast.makeText(getApplicationContext(), "no match!", Toast.LENGTH_SHORT).show();
return false;
}else if (matchedLine.size()==1) { }
else {
forwardButton.setVisibility(View.VISIBLE);
backwardButton.setVisibility(View.VISIBLE);
}
scrollView.post(new Runnable() {
@Override
public void run() {
int y = textView.getLayout().getLineTop(matchedLine.get(0));
scrollView.scrollTo(0, y);
}
});
searchView.clearFocus();
return false;
}

2.3.3 当有多个字符串可以匹配时的结果显示

基于relativelayout构造出button浮在textview上的效果,实现了当用户向下滑动scrollview时,button能够始终保持在右下方的位置[6]。用户点击按钮进行向前或者向后的搜索操作。点击textview之后取消按钮的显示。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/ssidTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</ScrollView> <Button
android:id="@+id/backwardButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="@drawable/backward"
/>
<Button
android:id="@+id/forwardButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/backwardButton"
android:layout_alignParentBottom="true"
android:background="@drawable/forward"
/>
</RelativeLayout>

2.4 生成有签名apk时遇到的问题及目前解决方案

2.4.1 Duplicate id @+id/image问题[7]

生成签名apk运行lint检查时,提示由Duplicate id @+id/image问题。即使是将android support library更新到23.0.1之后仍然出现。目前先将abc_activity_chooser_view.xml中的第二个@+id/image修改为@+id/image2。

2.4.2 This class should be public (android.support.v7.internal.widget.ActionBarView.HomeView)问题

修改lint,让其将这个问题从error判断为warning。window->preferences -> Android Lint Preferences,搜索Instantiatable。将其设置为warning。

2.4.3 "abc_action_bar_home_description_format" is not translated in "mk-rMK" 问题

因为目前不考虑支持过多语言,而且android这个包之后有可能再会更新。因此目前考虑先将lint的missing chanslation设置为warning。

三、完整源码共享

https://github.com/jue-jiang/wifiAssist

四、apk下载

https://github.com/jue-jiang/wifiAssist/blob/master/wifiAssist.apk

五、参考材料

[1]安卓手机如何查看WIFI密码_百度经验

[2]searchView.setOnQueryTextListener(this);

[3]java - Android Reading from an Input stream efficiently - Stack Overflow

[4]java - execute shell command from android - Stack Overflow

[5]java - How to scroll to a given line number, TextView inside ScrollView - Stack Overflow

[6]How to add a floating button on scrolling in android? - Stack Overflow

[7]Issue 73197 - android - abc_activity_chooser_view_include.xml uses android:id="@+id/image" twice - Android Open Source Project - Issue Tracker - Google Project Hosting

安卓手机已保存WiFi密码查看助手(开源)的更多相关文章

  1. 忘记常访问网站密码怎么办?教你如何查看浏览器已保存的密码,如何简单查看Chome浏览器保存的密码?

    利用场景: 同事或朋友外出有事,电脑未锁屏离开座位.可以利用这一间隙,查看Ta在Chrome浏览器上保存的账号密码 查看逻辑: 当我们要查看Chrome浏览器上保存的密码时,点击显示,会弹出一个对话框 ...

  2. 简单绕过Chrome密码查看逻辑,查看浏览器已保存的密码

    简单绕过Chrome密码查看逻辑,查看浏览器已保存的密码   利用场景: 同事或朋友外出有事,电脑未锁屏离开座位.可以利用这一间隙,查看Ta在Chrome浏览器上保存的账号密码 查看逻辑: 当我们要查 ...

  3. 百度经验:Win10查看已存储WiFi密码的两种方法

    方法一:网络和共享中心查询 具体步骤可以参考:Win10查看WIFI密码的方法 方法二:命令提示符查询 1.右键单击开始按钮,选择“命令提示符(管理员)” 2.输入如下命令(下图①号命令): nets ...

  4. 第十八章节 BJROBOT 安卓手机 APP 建地图【ROS全开源阿克曼转向智能网联无人驾驶车】

    1.把小车平放在地板上,用资料里的虚拟机,打开一个终端 ssh 过去主控端启动roslaunch znjrobotbringup.launch 2.在虚拟机端再打开一个终端,ssh 过去主控端启动ro ...

  5. 如何查看chrome浏览器已保存的密码

    该方法是针对在chrome中已经存储了登陆密码的情况. chrome版本是 66.0.3359.139(正式版本) (64 位),不知道哪天会改了这个bug. 一般来说,我们登陆chrome浏览器已经 ...

  6. windows查看已连接WIFI密码

    找到wifi图标. 右键,选择打开“网络和internet设置”,选择状态. 选择更改适配器设置. 选择你所连接的WIFI网络. 右键,选择状态. 选择无线属性. 选择安全. 勾选显示字符.

  7. win10家庭版查看已连接wifi密码

    点击屏幕右下角无线网路图标. 点击网络设置. 完成.

  8. Android WiFi密码(查看工具)

    纯手机端AIDE编写,现在分享出源码 & apk文件. 注: 使用此工具需要root权限. apk文件 : http://yunpan.cn/cHPLZ8zH5BQBV (提取码:9cd2) ...

  9. windows git 清除已保存的密码

    进入git目录 右键 git-bash.exe 执行命令: git config --system --unset credential.helper 然后执行git clone http://... ...

随机推荐

  1. Android Contextual Menus之二:contextual action mode

    Android Contextual Menus之二:contextual action mode 接上文:Android Contextual Menus之一:floating context me ...

  2. mysql innodb 奔溃问题

    ps -A | grep -i mysql kill 列出来的进程 service mysql start 我的问题就解决了 ------------------------------------- ...

  3. Lock同步锁--线程同步

    Lock-同步锁 Lock是java5提供的一个强大的线程同步机制--通过显示定义同步锁对象来实现同步.Lock可以显示的加锁.解锁.每次只能有一个线程对lock对象加锁. Lock有ReadLock ...

  4. 交换两个变量的值swap(a,b)

    方法一:使用第三方变量 , b = , temp; temp = a; a = b; b = temp; 方法二:变量加减法(即121,加减减) , b = ; a = a + b; b = a - ...

  5. iOS 学习 - 10下载(3) NSURLSession 音乐 篇

    使用 NSURLSession 下载,需要注意的是文件下载文件之后会自动保存到一个临时目录,需要开发人员自己将此文件重新放到其他指定的目录中 // // ViewController.m // Web ...

  6. iOS沙盒目录结构解析

    iOS沙盒目录结构解析 原文地址:http://blog.csdn.net/wzzvictory/article/details/18269713     出于安全考虑,iOS系统的沙盒机制规定每个应 ...

  7. Java ThreadLocal

    ThreadLocal类,代表一个线程局部变量,通过把数据放在ThreadLocal中,可以让每个线程创建一个该变量的副本.也可以看成是线程同步的另一种方式吧,通过为每个线程创建一个变量的线程本地副本 ...

  8. ORACLE中伪表 dual 的用法

     dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情,如下: 1.查看当前用户,可以在 SQL Plus中执行下面语句 sel ...

  9. 看美剧英文字幕学英语的利器——“深蓝英文字幕助手”简介

    我从初中开始基本上就是一个英语很烂的人,数理化再好有什么用,工作了,结果发现数理化都没啥用,最有用的还是当年学的最烂的英语.于是在2011年年底开始了学习英语的课程,在学习的过程中,外教经常会放英剧美 ...

  10. Hadoop源码之HDFS(1)--------通信方式

    说起hadoop这个东西,只能说真是个伟大的发明,而本人对cutting大神也是无比的崇拜,记得刚接触hadoop的时候,还觉得这个东西挺多余的,但是现在想想,这个想法略傻逼...... 2006-2 ...