├── ICON.png
├── Screenshots
├── 1.jpg
├── 2.jpg
├── 3.jpg
├── 4.jpg
├── 5.jpg
├── 6.jpg
├── 7.jpg
├── 8.jpg
├── 9.jpg
└── 10.jpg
├── app
├── src
│ └── main
│ │ ├── res
│ │ ├── drawable
│ │ │ └── ic.png
│ │ ├── layout
│ │ │ ├── list.xml
│ │ │ └── item.xml
│ │ └── menu
│ │ │ ├── more.xml
│ │ │ ├── file.xml
│ │ │ └── copy.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── zzz
│ │ └── wifiview
│ │ ├── WiFiAdapter.java
│ │ ├── MainActivity.java
│ │ ├── FileActivity.java
│ │ ├── ReadFile.java
│ │ └── ViewActivity.java
└── build.gradle
├── LICENSE
├── CHANGELOG.md
└── README.md
/ICON.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/ICON.png
--------------------------------------------------------------------------------
/Screenshots/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/1.jpg
--------------------------------------------------------------------------------
/Screenshots/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/2.jpg
--------------------------------------------------------------------------------
/Screenshots/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/3.jpg
--------------------------------------------------------------------------------
/Screenshots/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/4.jpg
--------------------------------------------------------------------------------
/Screenshots/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/5.jpg
--------------------------------------------------------------------------------
/Screenshots/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/6.jpg
--------------------------------------------------------------------------------
/Screenshots/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/7.jpg
--------------------------------------------------------------------------------
/Screenshots/8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/8.jpg
--------------------------------------------------------------------------------
/Screenshots/9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/9.jpg
--------------------------------------------------------------------------------
/Screenshots/10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/Screenshots/10.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamGmilk/WiFi-View/HEAD/app/src/main/res/drawable/ic.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/list.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion '29.0.0'
6 | defaultConfig {
7 | applicationId "com.zzz.wifiview"
8 | minSdkVersion 14
9 | targetSdkVersion 30
10 | versionCode 40
11 | versionName '12'
12 | }
13 | }
14 | dependencies {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/more.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/file.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/copy.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 JamGmilk
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzz/wifiview/WiFiAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zzz.wifiview;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.BaseAdapter;
7 | import android.widget.TextView;
8 | import java.util.ArrayList;
9 | import java.util.Map;
10 |
11 | public class WiFiAdapter extends BaseAdapter {
12 | private Context context;
13 | ArrayList> list;
14 |
15 | public WiFiAdapter(Context context, ArrayList> list) {
16 | super();
17 | this.context = context;
18 | this.list = list;
19 | }
20 |
21 | @Override
22 | public int getCount() {
23 | return list.size();
24 | }
25 |
26 | @Override
27 | public Object getItem(int position) {
28 | return position;
29 | }
30 |
31 | @Override
32 | public long getItemId(int position) {
33 | return position;
34 | }
35 |
36 | @Override
37 | public View getView(int position, View view, ViewGroup parent) {
38 | ViewHolder holder;
39 |
40 | if (view != null) {
41 | holder = (ViewHolder) view.getTag();
42 | } else {
43 | view = View.inflate(context, R.layout.item, null);
44 | holder = new ViewHolder();
45 | holder.ssid = (TextView) view.findViewById(R.id.title);
46 | holder.password = (TextView) view.findViewById(R.id.text);
47 | view.setTag(holder);
48 | }
49 |
50 | Map map = list.get(position);
51 | holder.ssid.setText(map.get("ssid"));
52 | holder.password.setText(map.get("psk"));
53 |
54 | return view;
55 | }
56 |
57 |
58 | class ViewHolder {
59 | public TextView ssid;
60 | public TextView password;
61 | }
62 |
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzz/wifiview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.zzz.wifiview;
2 |
3 | import android.app.Activity;
4 | import android.app.AlertDialog;
5 | import android.content.DialogInterface;
6 | import android.content.Intent;
7 | import android.net.Uri;
8 | import android.os.Bundle;
9 | import java.io.DataOutputStream;
10 |
11 | public class MainActivity extends Activity {
12 |
13 | @Override
14 | protected void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setTheme(android.R.style.Theme_DeviceDefault); // 暗色主题
17 |
18 | // 检测是否获取root,有则启动ViewActivity
19 | if (isRoot()) {
20 | startActivity(new Intent().setClassName("com.zzz.wifiview", "com.zzz.wifiview.ViewActivity"));
21 | finish();
22 | } else {
23 | showNoROOTDialog();
24 | }
25 | }
26 |
27 |
28 | private void showNoROOTDialog() {
29 | AlertDialog.Builder noROOTDialog = new AlertDialog.Builder(this);
30 | noROOTDialog.setTitle("无法获取 ROOT 权限");
31 | noROOTDialog.setCancelable(false);
32 | noROOTDialog.setMessage("需要 ROOT 权限以访问 WiFi 密码数据。");
33 | noROOTDialog.setPositiveButton("关闭", new DialogInterface.OnClickListener() {
34 | @Override
35 | public void onClick(DialogInterface dialog, int which) {
36 | finish();
37 | }
38 | });
39 | noROOTDialog.setNeutralButton("卸载", new DialogInterface.OnClickListener() {
40 | @Override
41 | public void onClick(DialogInterface dialog, int which) {
42 | Uri uri = Uri.parse("package:com.zzz.wifiview");
43 | Intent intent = new Intent(Intent.ACTION_DELETE, uri);
44 | startActivity(intent);
45 | finish();
46 | }
47 | });
48 | noROOTDialog.show();
49 | }
50 |
51 |
52 | /** 判断应用是否被授予root权限 */
53 | public static synchronized boolean isRoot() {
54 | Process process = null;
55 | DataOutputStream os = null;
56 | try {
57 | process = Runtime.getRuntime().exec("su");
58 | os = new DataOutputStream(process.getOutputStream());
59 | os.writeBytes("exit\n");
60 | os.flush();
61 | int exitValue = process.waitFor();
62 | if (exitValue == 0) {
63 | return true;
64 | } else {
65 | return false;
66 | }
67 | } catch (Exception e) {
68 | e.printStackTrace();
69 | return false;
70 | } finally {
71 | try {
72 | if (os != null) {
73 | os.close();
74 | }
75 | process.destroy();
76 | } catch (Exception e) {
77 | e.printStackTrace();
78 | }
79 | }
80 | }
81 |
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 历代更新日志
2 |
3 |
4 | ### 12 (40)
5 | - 支持 Android 11+
6 | - 调整 位置权限提示
7 |
8 | ### 11 (39)
9 | - 增加 权限弹窗限制
10 | - 支持 浏览其他加密类型的 WiFi 信息
11 | - 修复 计数菌动态更新
12 | - 调整 通知提示内容
13 |
14 | ### 10 (38)
15 | - 修复 当前连接的 WiFi 不能置顶的问题
16 | - 调整 API 级别为 29 (Android 10)
17 | - 调整 复制菜单
18 | - 新增 隐私说明
19 | - 新增 开放源代码
20 |
21 | ### 10 (37)
22 | - 合并 复制菜单
23 | - 优化 删除方法
24 | - 优化 读取备份的信息传递
25 | - 优化 无 ROOT 时的界面
26 | - 修复 无法添加备份
27 | - 修复 特殊备份名称引起的文件检索崩溃
28 | - 修复 WiFi 条目不能删除的问题
29 | - 修复 若干个 bug
30 |
31 | ### 9.0 (36)
32 | - 删除 打开方式
33 | - 调整 操作逻辑
34 |
35 | ### 8.1 (35)
36 | - 删除 杂项
37 | - 替换 刷新列表方式
38 | - 精简 软件包
39 |
40 | ### 8.0 (34)
41 | - 支持 当连接的 WiFi 在表头显示
42 | - 支持 读取备份
43 | - 支持 A-Z 排序
44 | - 支持 使用 WiFi View 打开本地 WiFi 密码配置文件
45 | - 支持 清空备份
46 | - 修复 软件不自觉的创建备份文件夹
47 | - 支持 修复 WiFi 配置文件出错导致的崩溃
48 | - 优化 若干处若干次
49 |
50 | ### 7.1.2 (33)
51 | - 恢复 删除 WiFi
52 | - 新增 若干个功能
53 |
54 | ### 7.1 (32)
55 | - 新增 备份与恢复
56 | - 停用 WiFi 删除
57 |
58 | ### 7.0 (31)
59 | - 新增 浏览源信息
60 | - 支持 显示 WiFi 条目在源文件的位置
61 | - 新增 WiFi 密码删除(不稳定)
62 |
63 | ### 6.0.1 (30)
64 | - 紧急 版本回倒
65 |
66 | ### 6.0 (29)
67 | - 支持 浏览源信息
68 | - 优化 复制反馈
69 |
70 | ### 5.1.1 (28)
71 | - 支持 Android 8.0
72 | - 修正 正常的版本号
73 | - 调整 targetSdkVersion
74 | - 提高 运行处理的高效性
75 | - 优化 代码的美观
76 | - 检查 稳定性
77 |
78 | ### 5.0.2 (27)
79 | - 支持 Android 8.0
80 |
81 | ### 5.0 (26)
82 | - 修复版本号过低的问题
83 |
84 | ### 4.4.4 (25)
85 | - 精简 软件
86 | - 保留 核心功能
87 |
88 | ### 4.4 (24)
89 | - 删除 无效代码
90 | - 压制 图标
91 | - 修改 蓝色主题
92 |
93 | ### 4.3 (23)
94 | - 调整 计数菌不可点击
95 | - 修复 看不懂英文的问题
96 |
97 | ### 4.2 (22)
98 | - 支持 显示 WiFi 数量在 menu 里
99 | - 支持 自定义文件目录
100 | - 支持 导出分享
101 |
102 | ### 4.1 (21)
103 | - 修复 跳转方式
104 | - 精简 继续精简
105 |
106 | ### 4.0 (20)
107 | - 新增 自定义备份名称
108 |
109 | ### 3.2 (19)
110 | - 新增 菜单
111 | - 新增 跳转到 WiFi 设置
112 | - 新增 备份
113 | - 修复 菜单问题
114 | - 修复 时长问题
115 |
116 | ### 3.0 (18)
117 | - 新增 备份
118 | - 修复 菜单问题
119 |
120 | ### 2.9 (17)
121 | - 新增 菜单
122 | - 新增 跳转到WiFi设置
123 |
124 | ### 2.1 (16)
125 | - 新增 计数菌 (=・ω・=)
126 |
127 | ### 2.6 (15)
128 | - 新增 报错提示 (不要再问我为啥是空白界面了😅)
129 |
130 | ### 2.8 (14)
131 | - 修改了菜单(样式如介绍图)
132 |
133 | ### 2.7 (13)
134 | - 紧急修复
135 |
136 | ### 2.6 (12)
137 | - 更换了新图标 192*192 px
138 | - 修复了在部分设备上无法获取 root 的问题
139 |
140 | ### 2.5 (11)
141 | - 移除了 values
142 | - 移除了 debug 调试
143 |
144 | ### 2.4 (10)
145 | - 继续精简,体积减小到 15 KB
146 | - 删掉了无用的代码
147 |
148 | ### 2.3 (9)
149 | - 调整 点击 item 为直接复制密码,长按打开复制菜单
150 | - 除去 WiFi Setting
151 |
152 | ### 2.2 (8)
153 | - 调整 点击 item 为直接复制密码,长按打开复制菜单
154 | - 精简 代码
155 | - 调整 item 高度
156 | - 更换 Icon
157 |
158 | ### 2.1 (7)
159 | - 精简
160 |
161 | ### 2.0 (6)
162 | - 精简
163 |
164 | ### 1.1.1.1.1 (5)
165 | - 精简 软件体积
166 | - 除去 无用功能
167 | - 支持 密码显示
168 |
169 | ### 1.1.1.1 (4)
170 | - 新增 快速跳转到 WiFi 设置
171 | - 优化 界面布局
172 |
173 | ### 1.1.1 (3)
174 | - 新增 提示界面
175 | - 删除 其他尺寸的图标
176 |
177 | ### 1.1 (2)
178 | - 新增 WiFi 密码查看
179 | - 新增 WiFi 开关
180 | - 新增 退出确认
181 |
182 | ### 1.0 (1)
183 | Hello World!
184 |
185 | ## - END -
186 |
187 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WiFi View
2 |
3 | 快速查看与管理在 Android 设备上连过的 WiFi 的密码
4 |
5 |
6 | ### 应用特性
7 | - 支持 Android 4.0 +
8 | - 支持显示中文名称的 WiFi
9 | - 支持一键复制 SSID 与密码
10 | - 支持备份与恢复
11 | - 支持查看 WiFi 的源信息
12 |
13 |
14 | ## 应用截图
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | ## 历代更新日志
28 | [CHANGELOG.md](CHANGELOG.md)
29 |
30 |
31 | ## 下载
32 | - [GitHub](https://github.com/JamGmilk/WiFi-View/releases)
33 | - [酷安](https://www.coolapk.com/apk/com.zzz.wifiview)
34 |
35 |
36 | ## 隐私权限说明
37 | ### ACCESS_SUPERUSER:
38 | 使用 ROOT 权限读写 WiFi 密码配置文件。
39 |
40 | ### ACCESS_WIFI_STATE:
41 | 扫描 WLAN ,用于置顶当前连接的 WiFi 。
42 |
43 | ### ACCESS_FINE_LOCATION:
44 | 此项权限是 Android 官方要求的[[1]]。在 Android 8.0 以后,需要授予此权限才能使用 ACCESS_WIFI_STATE 权限。
45 |
46 | >软件扫描 WLAN 需要满足以下所有条件:
47 | > ① 授予软件精确位置权限
48 | > ② 设备已启用位置服务
49 |
50 | [[1]] https://developer.android.google.cn/guide/topics/connectivity/wifi-scan#wifi-scan-restrictions
51 |
52 | [1]:
53 |
54 |
55 | ## 注意
56 |
57 | 1. 手动删除的 WiFi 无法获取;
58 |
59 | 2. 部分系统可能会加密,导致软件不能正常工作;
60 |
61 | 3. 软件需要读取 /data 下的系统文件,必须授予 ROOT 权限。
62 | > Android 8.0 以下读取 /data/misc/wifi/wpa_supplicant.conf
63 | > Android 8~11 读取 /data/misc/wifi/WifiConfigStore.xml
64 | > Android 11 以上读取 /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml
65 |
66 | ## License
67 | ```
68 | Copyright (c) 2021 JamGmilk
69 |
70 | Permission is hereby granted, free of charge, to any person obtaining a copy
71 | of this software and associated documentation files (the "Software"), to deal
72 | in the Software without restriction, including without limitation the rights
73 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
74 | copies of the Software, and to permit persons to whom the Software is
75 | furnished to do so, subject to the following conditions:
76 |
77 | The above copyright notice and this permission notice shall be included in all
78 | copies or substantial portions of the Software.
79 |
80 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
82 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
83 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
84 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
85 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
86 | SOFTWARE.
87 | ```
88 |
89 | *Copyright © 2016-2021 JamGmilk.*
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzz/wifiview/FileActivity.java:
--------------------------------------------------------------------------------
1 | package com.zzz.wifiview;
2 |
3 | import android.app.Activity;
4 | import android.app.AlertDialog;
5 | import android.content.Context;
6 | import android.content.DialogInterface;
7 | import android.content.Intent;
8 | import android.os.Bundle;
9 | import android.text.InputType;
10 | import android.view.Menu;
11 | import android.view.MenuItem;
12 | import android.view.View;
13 | import android.widget.AdapterView;
14 | import android.widget.ArrayAdapter;
15 | import android.widget.EditText;
16 | import android.widget.ListAdapter;
17 | import android.widget.ListView;
18 | import android.widget.PopupMenu;
19 | import android.widget.Toast;
20 | import java.io.DataOutputStream;
21 | import java.io.File;
22 | import java.text.SimpleDateFormat;
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | public class FileActivity extends Activity {
27 |
28 | ArrayList fileList;
29 | Context context = this;
30 | PopupMenu popup;
31 |
32 | String backupPath; // 添加备份文件目录
33 | String backupParentPath; // /AppData/files/Backup
34 | String wifiPath; // /data/misc/wifi/xxx.xml
35 |
36 | int num; // 计数菌
37 |
38 | /* 设定时间格式 */
39 | java.util.Date utilDate = new java.util.Date();
40 | SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmm");
41 |
42 |
43 | @Override
44 | protected void onCreate(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 | setContentView(R.layout.list);
47 |
48 | /* 设置备份目录 */
49 | backupParentPath = context.getExternalFilesDir("Backup").getPath();
50 |
51 | /* 设置 WiFi 密码文件路径 */
52 | if (android.os.Build.VERSION.SDK_INT >= 26) {
53 | if (android.os.Build.VERSION.SDK_INT >= 30) {
54 | wifiPath = "/data/misc/apexdata/com.android.wifi/WifiConfigStore.xml";
55 | } else {
56 | wifiPath = "/data/misc/wifi/WifiConfigStore.xml";
57 | }
58 | } else {
59 | wifiPath = "/data/misc/wifi/wpa_supplicant.conf";
60 | }
61 |
62 | /* 获取备份文件列表 */
63 | fileList = new ArrayList();
64 | getAllFiles(new File(backupParentPath));
65 | List data = new ArrayList();
66 | for(int i=0; i(this, android.R.layout.simple_list_item_1, strings);
77 | lv.setAdapter(adapter);
78 | lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
79 | @Override
80 | public void onItemClick(AdapterView> parent, View view, final int position, long id) {
81 | // Toast.makeText(FileActivity.this, backupParentPath + "/" + strings[position], 0).show();
82 | popup = new PopupMenu(FileActivity.this, view);
83 | getMenuInflater().inflate(R.menu.file,popup.getMenu());
84 | popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
85 | @Override
86 | public boolean onMenuItemClick(MenuItem item) {
87 | switch(item.getItemId()) {
88 | case R.id.menu_recovery: // 时光穿梭
89 | showRestoreDialog(backupParentPath + "/" + strings[position]);
90 | break;
91 | case R.id.menu_read: // 读取备份
92 | Intent intent1 = new Intent();
93 | intent1.setClass(FileActivity.this, ViewActivity.class);
94 | intent1.putExtra("name", strings[position]);
95 | intent1.putExtra("path", backupParentPath + "/" + strings[position]);
96 | intent1.putExtra("read", true);
97 | startActivity(intent1); // 此时 ViewActivity 的主菜单不再显示而是替换成文字返回
98 | break;
99 | case R.id.menu_delete1: // 删除备份
100 | cmd("rm -f " + backupParentPath + "/" + strings[position]);
101 |
102 | Intent intent = getIntent();
103 | finish();
104 | startActivity(intent);
105 | break;
106 | default:
107 | return false;
108 | }
109 | return true;
110 | }
111 | });
112 | popup.show();
113 | }
114 | });
115 |
116 | }
117 |
118 |
119 | @Override
120 | public boolean onCreateOptionsMenu(Menu menu) {
121 | super.onCreateOptionsMenu(menu);
122 | menu.add(0,0,0,"添加备份");
123 | menu.add(0,1,0,"Notice");
124 | menu.getItem(1).setEnabled(false);
125 | menu.getItem(1).setTitle("共 " + num + " 条备份");
126 | return true;
127 | }
128 |
129 |
130 | @Override
131 | public boolean onOptionsItemSelected(MenuItem item) {
132 | switch (item.getItemId()) {
133 | case 0: // 添加备份
134 | showBackupDialog();
135 | return true;
136 | default:
137 | return super.onOptionsItemSelected(item);
138 | }
139 | }
140 |
141 |
142 | private void showBackupDialog() {
143 | final EditText et = new EditText(this);
144 | AlertDialog.Builder BackupDialog = new AlertDialog.Builder(this);
145 | BackupDialog
146 | .setTitle("备份名称")
147 | .setView(et);
148 |
149 | et.setText(formatter.format(utilDate));
150 | et.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
151 |
152 | BackupDialog
153 | .setPositiveButton("开始备份",new DialogInterface.OnClickListener() {
154 | @Override
155 | public void onClick(DialogInterface dialog,int which) {
156 | backupPath = backupParentPath + "/" + et.getText().toString();
157 |
158 | cmd("cp -f " + wifiPath + " " + backupPath);
159 |
160 | Intent intent = getIntent();
161 | finish();
162 | startActivity(intent);
163 | }
164 | })
165 | .setNegativeButton("取消", null)
166 | /*.setNeutralButton("发送备份",new DialogInterface.OnClickListener() {
167 | @Override
168 | public void onClick(DialogInterface dialog,int which) {
169 | backupPath = backupParentPath + "/" + et.getText().toString();
170 |
171 | cmd("cp -f " + wifiPath + " " + backupPath);
172 |
173 | File sendFile = new File(backupPath);
174 | Intent share = new Intent(Intent.ACTION_SEND);
175 | share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(sendFile));
176 | *///share.setType("*/*");
177 | /*startActivity(Intent.createChooser(share, "发送"));
178 | }
179 | })*/
180 | .show();
181 | }
182 |
183 |
184 | private void showRestoreDialog(final String path) {
185 | AlertDialog.Builder RestoreDialog = new AlertDialog.Builder(this);
186 | RestoreDialog
187 | .setTitle("警告")
188 | .setMessage("此操作将会替换设备的 WiFi 密码文件。是否继续?\n\n" + "当前文件:\n" + path)
189 | .setPositiveButton("继续",new DialogInterface.OnClickListener() {
190 | @Override
191 | public void onClick(DialogInterface dialog,int which) {
192 | cmd("cp -f " + path + " " + wifiPath);
193 | cmd("chmod 660 " + wifiPath);
194 | finish();
195 | startActivity(new Intent().setClassName("com.zzz.wifiview","com.zzz.wifiview.ViewActivity"));
196 | }
197 | })
198 | .setNegativeButton("取消", null)
199 | .show();
200 | }
201 |
202 |
203 | /* 获取备份文件列表 */
204 | private void getAllFiles(File root) {
205 | File files[] = root.listFiles();
206 | if(files != null)
207 | for(File f:files) {
208 | if(f.isDirectory()) {
209 | getAllFiles(f);
210 | } else {
211 | this.fileList.add(f);
212 | }
213 | }
214 | }
215 |
216 |
217 | /* 执行命令 */
218 | public void cmd(String command) {
219 | Process process = null;
220 | DataOutputStream os = null;
221 | try {
222 | process = Runtime.getRuntime().exec("su");
223 | os = new DataOutputStream(process.getOutputStream());
224 | os.writeBytes(command + "\n");
225 | os.writeBytes("exit\n");
226 | os.flush();
227 | process.waitFor();
228 | } catch (Exception e) {
229 | e.printStackTrace();
230 | Toast.makeText(this, "FAcmd: " + e.getMessage(), Toast.LENGTH_LONG).show();
231 | } finally {
232 | try {
233 | if (os != null) {
234 | os.close();
235 | }
236 | process.destroy();
237 | } catch (Exception e) {
238 | e.printStackTrace();
239 | Toast.makeText(this, "FAcmdF: " + e.getMessage(), Toast.LENGTH_LONG).show();
240 | }
241 | }
242 | }
243 |
244 |
245 | }
246 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzz/wifiview/ReadFile.java:
--------------------------------------------------------------------------------
1 | package com.zzz.wifiview;
2 |
3 | import android.content.Context;
4 | import android.net.wifi.WifiInfo;
5 | import android.net.wifi.WifiManager;
6 | import android.util.Log;
7 | import java.io.BufferedReader;
8 | import java.io.DataOutputStream;
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.io.InputStreamReader;
12 | import java.io.RandomAccessFile;
13 | import java.io.UnsupportedEncodingException;
14 | import java.util.ArrayList;
15 | import java.util.Collections;
16 | import java.util.Comparator;
17 | import java.util.HashMap;
18 | import java.util.Map;
19 | import java.util.regex.Matcher;
20 | import java.util.regex.Pattern;
21 |
22 | public class ReadFile {
23 |
24 | int mode = 0;
25 |
26 | ArrayList> list = new ArrayList>();
27 |
28 | public ReadFile(String path, int i) {
29 | mode = i;
30 |
31 | Process process = null;
32 | String s = "";
33 | DataOutputStream os = null;
34 | BufferedReader br = null;
35 | try {
36 | process = Runtime.getRuntime().exec("su");
37 | os = new DataOutputStream(process.getOutputStream());
38 | os.writeBytes("cat " + path + "\n");
39 | os.writeBytes("exit\n");
40 | os.flush();
41 | br = new BufferedReader(new InputStreamReader(process.getInputStream()));
42 | String line = null;
43 | while ((line = br.readLine()) != null) {
44 | s += line.trim() + "\n";
45 | }
46 | } catch (IOException e) {
47 | exceptionCatch("ReadFile: " + e.getMessage());
48 | e.printStackTrace();
49 | } finally {
50 | try {
51 | if (os != null) {
52 | os.close();
53 | }
54 | if (br != null) {
55 | br.close();
56 | }
57 | process.destroy();
58 | } catch (Exception e) {
59 | exceptionCatch("ReadFile, finally: " + e.getMessage());
60 | e.printStackTrace();
61 | }
62 | }
63 | scan(s);
64 | }
65 |
66 | /* 一个简陋的日志记录方法:exceptionCatch(formatter.format(utilDate) + " : " + "58"); */
67 | public void exceptionCatch(String strcontent) {
68 | String path = "/storage/emulated/0/Android/data/com.zzz.wifiview/debug/debug.txt";
69 | // System.currentTimeMillis();
70 | String strContent = strcontent + "\r\n";
71 | try {
72 | File file = new File(path);
73 | if (!file.exists()) {
74 | Log.e("TestFile", "Create the file:" + path);
75 | file.getParentFile().mkdirs();
76 | file.createNewFile();
77 | }
78 | RandomAccessFile rf = new RandomAccessFile(file,"rwd");
79 | rf.seek(file.length());
80 | rf.write(strContent.getBytes());
81 | rf.close();
82 | } catch (Exception e){
83 | Log.e("TestFile", "Error on write File:"+e);
84 | }
85 | }
86 |
87 |
88 | /* 分隔每个 WiFi 条目 */
89 | private void scan(String s) {
90 | if (android.os.Build.VERSION.SDK_INT >= 26) {
91 | Pattern pattern = Pattern.compile("\\n([\\s\\S]+?)\\n\\ ");
92 | Matcher matcher = pattern.matcher(s);
93 | while (matcher.find()) {
94 | addOreo(matcher.group());
95 | }
96 | } else {
97 | Pattern pattern1 = Pattern.compile("network=\\{\\n([\\s\\S]+?)\\n\\}");
98 | Matcher matcher1 = pattern1.matcher(s);
99 | while (matcher1.find()) {
100 | add(matcher1.group());
101 | }
102 | }
103 | }
104 |
105 |
106 | /* Android 8.0 之前的解析 WiFi 方法*/
107 | private void add(String s) {
108 | exceptionCatch(s);
109 | HashMap map = new HashMap();
110 | map.put("view", s); // 源信息
111 |
112 | String[] list = s.split("\\n");
113 |
114 | String ssid = "";
115 | String psk = "";
116 | String key_mgmt = "";
117 |
118 | // Get value
119 | // 找出 ssid 和 key_mgmt
120 | for (String info : list) {
121 | if (info.contains("=")) {
122 | int index = info.indexOf("=");
123 | if (info.substring(0, index).contains("ssid")) {
124 | if (!info.substring(0, index).contains("scan_ssid")) {
125 | ssid = info.substring(index+1, info.length());
126 | if (ssid.contains("\"")) {
127 | ssid = ssid.substring(1, ssid.length()-1);
128 | } else {
129 | ssid = toUTF8(ssid);
130 | }
131 | }
132 | } else if (info.substring(0, index).contains("key_mgmt")) {
133 | key_mgmt = info.substring(index+1, info.length());
134 | }
135 | }
136 | }
137 |
138 | if (mode == 1) { // WPA-PSK 模式
139 | if (key_mgmt.contains("WPA-PSK")) {
140 | // 找出 psk
141 | for (String info : list) {
142 | if (info.contains("=")) {
143 | int index = info.indexOf("=");
144 | if (info.substring(0, index).contains("psk")) {
145 | psk = info.substring(index+2, info.length()-1);
146 | }
147 | }
148 | }
149 |
150 | map.put("ssid", ssid);
151 | map.put("psk", psk);
152 |
153 | }
154 | } else if (mode == 2) { // 非 WPA-PSK 模式
155 | if (!key_mgmt.contains("WPA-PSK")) {
156 | map.put("ssid", ssid);
157 | map.put("psk", key_mgmt);
158 | }
159 | }
160 |
161 | this.list.add(map);
162 | }
163 |
164 |
165 | /* Android 8.0 之后的解析 WiFi 方法 */
166 | private void addOreo(String s) {
167 | HashMap map = new HashMap();
168 | map.put("view", s);
169 |
170 | String[] list = s.split("\\n");
171 |
172 | String ssid = "";
173 | String psk = "";
174 | String key_mgmt = "";
175 |
176 | // Get value
177 |
178 | for (String info : list) {
179 | if (info.contains("name=\"SSID\">")) {
180 | ssid = info.substring(info.indexOf(""")+6, info.lastIndexOf("""));
181 | } else if (info.contains("name=\"ConfigKey\">")) {
182 | key_mgmt = info.substring(info.indexOf(""")+6, info.length());
183 | key_mgmt = key_mgmt.substring(key_mgmt.indexOf(""")+6, key_mgmt.lastIndexOf(" "));
184 | key_mgmt = key_mgmt.replace("-", "");
185 | }
186 | }
187 |
188 | if (mode == 1) {
189 | if (key_mgmt.contains("WPA_PSK")) {
190 | for (String info : list) {
191 | if (info.contains("name=\"PreSharedKey\">")) {
192 | psk = info.substring(info.indexOf(""")+6, info.lastIndexOf("""));
193 | }
194 | }
195 |
196 | map.put("ssid", ssid);
197 | map.put("psk", psk);
198 |
199 | }
200 | } else if (mode == 2) {
201 | if (!key_mgmt.contains("WPA_PSK")) {
202 | map.put("ssid", ssid);
203 | map.put("psk", key_mgmt);
204 | }
205 | }
206 |
207 | this.list.add(map);
208 | }
209 |
210 |
211 | public ArrayList> getList(Context context) {
212 | ArrayList> m = new ArrayList>();
213 | for (Map map : this.list) {
214 | if (map.containsKey("ssid") && map.containsKey("psk")) m.add(map);
215 | }
216 | return this.sorting(m, context);
217 | }
218 |
219 |
220 | private ArrayList> sorting(ArrayList> lv, Context context) {
221 | if (lv.size() < 1) return lv;
222 | Collections.sort(lv, new sort(getSSID(context)));
223 | return lv;
224 | }
225 |
226 |
227 | private String getSSID(Context context) {
228 | try {
229 | WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
230 | if (!wifiManager.isWifiEnabled()) return ""; // 关闭 WiFi 时
231 | WifiInfo wifiInfo = wifiManager.getConnectionInfo();
232 | String ssid = wifiInfo.getSSID();
233 |
234 | // 判断有无引号
235 | if (ssid.contains("\"")) {
236 | ssid = ssid.substring(1, ssid.length()-1);
237 | } else {
238 | ssid = toUTF8(ssid);
239 | }
240 | return ssid;
241 | } catch (Exception e) {
242 | exceptionCatch("getCurrentWiFi: " + e.getMessage());
243 | e.printStackTrace();
244 | return "";
245 | }
246 | }
247 |
248 |
249 | private static String toUTF8(String s) {
250 | if (s == null || s.equals("")) return null;
251 |
252 | try {
253 | s = s.toUpperCase();
254 | int total = s.length() / 2;
255 | int pos = 0;
256 | byte[] buffer = new byte[total];
257 | for (int i = 0; i < total; i++) {
258 | int start = i * 2;
259 | buffer[i] = (byte) Integer.parseInt(s.substring(start, start + 2), 16);
260 | pos++;
261 | }
262 | return new String(buffer, 0, pos, "UTF-8");
263 | } catch (UnsupportedEncodingException e) {
264 | e.printStackTrace();
265 | return null;
266 | }
267 | }
268 |
269 | }
270 |
271 |
272 | class sort implements Comparator> {
273 |
274 | private String current;
275 |
276 |
277 | public sort(String current) {
278 | this.current = current;
279 | }
280 |
281 |
282 | @Override
283 | public int compare(Map t1, Map t2) {
284 | String s1 = t1.get("ssid");
285 | String s2 = t2.get("ssid");
286 | if (s1.equals(s2)) return 0;
287 | if (s1.equals(current)) return -1;
288 | if (s2.equals(current)) return 1;
289 | return s1.compareToIgnoreCase(s2);
290 | }
291 |
292 |
293 | }
294 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zzz/wifiview/ViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.zzz.wifiview;
2 |
3 | import android.app.ActionBar;
4 | import android.app.Activity;
5 | import android.app.AlertDialog;
6 | import android.content.ClipData;
7 | import android.content.ClipboardManager;
8 | import android.content.Context;
9 | import android.content.DialogInterface;
10 | import android.content.Intent;
11 | import android.net.Uri;
12 | import android.os.Bundle;
13 | import android.provider.Settings;
14 | import android.view.Menu;
15 | import android.view.MenuItem;
16 | import android.view.View;
17 | import android.widget.AdapterView;
18 | import android.widget.ListView;
19 | import android.widget.PopupMenu;
20 | import android.widget.Toast;
21 | import java.io.BufferedReader;
22 | import java.io.DataOutputStream;
23 | import java.io.FileOutputStream;
24 | import java.io.IOException;
25 | import java.io.InputStreamReader;
26 | import java.io.OutputStreamWriter;
27 | import java.util.ArrayList;
28 | import java.util.Map;
29 |
30 | public class ViewActivity extends Activity {
31 | ArrayList> mainList;
32 | PopupMenu popup;
33 | Context context = this;
34 | String backupPath; // 备份目录 (/AppData/files/Backup/AutoBackup)
35 | String sPath; // 源文件
36 | boolean isRead = false; // 读取备份模式
37 | boolean isMore = false; // 显示更多 WiFi
38 |
39 | @Override
40 | protected void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | setContentView(R.layout.list);
43 |
44 | // 缓存目录(/AppData/cache/bk)
45 | //bkPath = this.getExternalCacheDir().getPath() + "/bk";
46 |
47 | // 备份目录 (/AppData/files/Backup/AutoBackup)
48 | backupPath = this.getExternalFilesDir("Backup").getPath() + "/AutoBackup";
49 |
50 | /* 获取启动来源 */
51 | try {
52 | Intent intent = getIntent();
53 | Bundle bundle = intent.getExtras();
54 | isRead = bundle.getBoolean("read");
55 | isMore = bundle.getBoolean("more");
56 | } catch (Exception e) {
57 | e.printStackTrace();
58 | //Toast.makeText(this, "VAoC: " + e.getMessage(), Toast.LENGTH_LONG).show();
59 | }
60 |
61 | start();
62 | }
63 |
64 |
65 | private void start() {
66 | Intent intent = getIntent();
67 | Bundle bundle = intent.getExtras();
68 |
69 | /* 判断启动来源 */
70 | if (isRead) { // 读取备份模式
71 | setTitle(bundle.getString("name"));
72 | sPath = bundle.getString("path");
73 | mainList = get(sPath, 1);
74 | } else if (isMore) { // 显示更多 WiFi
75 | setTitle("更多 WiFi");
76 | sPath = bundle.getString("path");
77 | mainList = get(sPath, 2);
78 | } else { // 读取系统文件
79 | if (android.os.Build.VERSION.SDK_INT >= 26) {
80 | if (android.os.Build.VERSION.SDK_INT >= 30) {
81 | sPath = "/data/misc/apexdata/com.android.wifi/WifiConfigStore.xml";
82 | } else {
83 | sPath = "/data/misc/wifi/WifiConfigStore.xml";
84 | }
85 | } else {
86 | sPath = "/data/misc/wifi/wpa_supplicant.conf";
87 | }
88 | mainList = get(sPath, 1);
89 | }
90 |
91 |
92 | if (mainList == null) {
93 | Toast.makeText(ViewActivity.this, "获取列表失败", Toast.LENGTH_LONG).show();
94 | } else {
95 | if (mainList.size() == 0) {
96 | Toast.makeText(ViewActivity.this, "列表为空", Toast.LENGTH_LONG).show();
97 | } else {
98 | final ListView lv = findViewById(R.id.lv);
99 | lv.setAdapter(new WiFiAdapter(this, mainList));
100 | lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
101 | @Override
102 | public void onItemClick(AdapterView> parent, View view, final int position, long id) {
103 | popup = new PopupMenu(ViewActivity.this, view);
104 |
105 | if (isMore) {
106 | getMenuInflater().inflate(R.menu.more, popup.getMenu());
107 | } else {
108 | getMenuInflater().inflate(R.menu.copy, popup.getMenu());
109 | }
110 |
111 | popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
112 | @Override
113 | public boolean onMenuItemClick(MenuItem item) {
114 | final ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
115 | switch(item.getItemId()) {
116 | case R.id.menu_ssid:
117 | cm.setPrimaryClip(ClipData.newPlainText(null, mainList.get(position).get("ssid")));
118 | Toast.makeText(ViewActivity.this, "SSID已复制", Toast.LENGTH_SHORT).show();
119 | break;
120 | case R.id.menu_password:
121 | cm.setPrimaryClip(ClipData.newPlainText(null, mainList.get(position).get("psk")));
122 | Toast.makeText(ViewActivity.this, "密码已复制", Toast.LENGTH_SHORT).show();
123 | break;
124 | case R.id.menu_all:
125 | Map s = mainList.get(position);
126 | cm.setPrimaryClip(ClipData.newPlainText(null, "SSID: " + s.get("ssid") + "\n" + "密码: " + s.get("psk")));
127 | Toast.makeText(ViewActivity.this, "SSID和密码都已复制", Toast.LENGTH_SHORT).show();
128 | break;
129 | case R.id.menu_view:
130 | AlertDialog.Builder TextDialog = new AlertDialog.Builder(ViewActivity.this);
131 | TextDialog.setTitle("源信息浏览").setMessage(mainList.get(position).get("view")).setPositiveButton("关闭",null).setNeutralButton("复制", new DialogInterface.OnClickListener(){@Override public void onClick(DialogInterface dialog, int which) {
132 | cm.setPrimaryClip(ClipData.newPlainText(null, mainList.get(position).get("view")));
133 | }}).show();
134 | break;
135 | case R.id.menu_delete:
136 | delete(mainList.get(position).get("view"));
137 | cmd("cp -f " + backupPath + " " + sPath);
138 | if (!isRead) cmd("chmod 660 " + sPath);
139 | Toast.makeText(ViewActivity.this, "已删除", Toast.LENGTH_SHORT).show();
140 |
141 | mainList.clear();
142 | start();
143 |
144 | break;
145 | default:
146 | return false;
147 | }
148 | return true;
149 | }
150 | });
151 | popup.show();
152 | }
153 | });
154 | }
155 | }
156 |
157 | }
158 |
159 |
160 | public ArrayList> get(String path, int i) {
161 | try {
162 | ReadFile file = new ReadFile(path, i); // i为读取模式。1-常规模式,2-更多WiFi模式。
163 | return file.getList(this.context);
164 | } catch (Exception e) {
165 | Toast.makeText(this, "VAget: " + e.getMessage(), Toast.LENGTH_LONG).show();
166 | return null;
167 | }
168 | }
169 |
170 |
171 | @Override
172 | protected void onStart() {
173 | super.onStart();
174 | if (isMore) {
175 | ActionBar actionBar = this.getActionBar();
176 | actionBar.setDisplayHomeAsUpEnabled(true);
177 | }
178 |
179 | }
180 |
181 |
182 | @Override
183 | public boolean onCreateOptionsMenu(Menu menu) {
184 | super.onCreateOptionsMenu(menu);
185 | menu.add(0,0,0,"刷新列表");
186 | menu.add(0,1,0,"显示更多 WiFi");
187 | menu.add(0,2,0,"打开 WiFi 设置");
188 | menu.add(0,3,0,"备份与恢复");
189 | menu.add(0,4,0,"关于");
190 | menu.add(0,5,0,"获取列表出错");
191 | menu.getItem(5).setEnabled(false);
192 | if (mainList != null) menu.getItem(5).setTitle("共 " + mainList.size() + " 条WiFi");
193 | if (isRead || isMore) {
194 | menu.getItem(2).setVisible(false);
195 | menu.getItem(3).setVisible(false);
196 | menu.getItem(4).setVisible(false);
197 | }
198 | if (isRead) {
199 | menu.getItem(0).setVisible(false);
200 | menu.add(0,6,0,"返回");
201 | }
202 | if (isMore) menu.getItem(1).setVisible(false);
203 | return true;
204 | }
205 |
206 |
207 | @Override
208 | public boolean onPrepareOptionsMenu(Menu menu) {
209 | super.onPrepareOptionsMenu(menu);
210 | if (mainList != null) menu.getItem(5).setTitle("共 " + mainList.size() + " 条WiFi");
211 | return super.onPrepareOptionsMenu(menu);
212 | }
213 |
214 |
215 | @Override
216 | public boolean onOptionsItemSelected(MenuItem item) {
217 | switch (item.getItemId()) {
218 | case 0: // 刷新列表
219 | mainList.clear();
220 | start();
221 | Toast.makeText(this, "刷新成功", Toast.LENGTH_SHORT).show();
222 | return true;
223 | case 1: // 显示更多 WiFi
224 | Intent intent = new Intent();
225 | intent.setClass(ViewActivity.this, ViewActivity.class);
226 | intent.putExtra("path", sPath);
227 | intent.putExtra("more", true);
228 | startActivity(intent);
229 | return true;
230 | case 2: // 打开 WiFi 设置
231 | startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
232 | return true;
233 | case 3: // 备份与恢复
234 | startActivity(new Intent().setClassName("com.zzz.wifiview", "com.zzz.wifiview.FileActivity"));
235 | return true;
236 | case 4: // 关于
237 | showAboutDialog();
238 | return true;
239 | case 6: // 返回
240 | finish();
241 | return true;
242 | case android.R.id.home: // 左上角返回
243 | finish();
244 | return true;
245 | default:
246 | return super.onOptionsItemSelected(item);
247 | }
248 | }
249 |
250 |
251 | private void delete(String ss) {
252 | String s = "";
253 | Process process = null;
254 | DataOutputStream os = null;
255 | BufferedReader br = null;
256 | OutputStreamWriter pw = null;
257 | try {
258 | process = Runtime.getRuntime().exec("su");
259 | os = new DataOutputStream(process.getOutputStream());
260 | os.writeBytes("cat " + sPath + "\n");
261 | os.writeBytes("exit\n");
262 | os.flush();
263 |
264 | br = new BufferedReader(new InputStreamReader(process.getInputStream()));
265 | String line = null;
266 | while ((line = br.readLine()) != null) {
267 | s += line.trim() + "\n";
268 | }
269 | pw = new OutputStreamWriter(new FileOutputStream(backupPath), "UTF-8");
270 | s = s.replace(ss,"");
271 | pw.write(s);
272 | } catch (IOException e) {
273 | e.printStackTrace();
274 | Toast.makeText(ViewActivity.this, "VAdelete: " + e, Toast.LENGTH_LONG).show();
275 | } finally {
276 | try {
277 | if (os != null) {
278 | os.close();
279 | }
280 | if (br != null) {
281 | br.close();
282 | }
283 | if (pw != null) {
284 | pw.close();
285 | }
286 | process.destroy();
287 | } catch (Exception e) {
288 | e.printStackTrace();
289 | Toast.makeText(this, "VAdeleteF: " + e.getMessage(), Toast.LENGTH_LONG).show();
290 | }
291 | }
292 | }
293 |
294 |
295 | private void showAboutDialog() {
296 | final String[] items = {"版本: 12", "应用信息", "置顶当前连接的WiFi", "开放源代码", "Copyright © 2016 - 2021 JamGmilk."};
297 | AlertDialog.Builder AboutDialog = new AlertDialog.Builder(this)
298 | .setTitle("WiFi View")
299 | .setIcon(com.zzz.wifiview.R.drawable.ic)
300 | .setItems(items, new DialogInterface.OnClickListener() {
301 | @Override
302 | public void onClick(DialogInterface dialog, int which) {
303 | switch (which) {
304 | case 0:
305 | Toast.makeText(ViewActivity.this, "版本代号: 40", Toast.LENGTH_SHORT).show();
306 | break;
307 | case 1:
308 | Intent intent = new Intent();
309 | intent.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
310 | intent.setData(Uri.parse("package:com.zzz.wifiview"));
311 | startActivity(intent);
312 | break;
313 | case 2:
314 | showPermissionsDialog();
315 | break;
316 | case 3:
317 | Uri uri2 = Uri.parse("https://github.com/JamGmilk/WiFi-View");
318 | Intent intent2 = new Intent(Intent.ACTION_VIEW, uri2);
319 | startActivity(intent2);
320 | break;
321 | }
322 | }
323 | });
324 | AboutDialog.create().show();
325 | }
326 |
327 |
328 | private void showPermissionsDialog() {
329 | AlertDialog.Builder permissionsDialog = new AlertDialog.Builder(this);
330 | permissionsDialog.setTitle("置顶当前连接WiFi");
331 | permissionsDialog.setMessage("在 Android 8.0 以后,软件扫描 WLAN 需要满足以下所有条件:\n① 授予软件精确位置权限;\n② 设备已启用位置服务。\n\n仅用于置顶当前连接的WiFi。");
332 | permissionsDialog.setPositiveButton("前往授权",new DialogInterface.OnClickListener() {
333 | @Override
334 | public void onClick(DialogInterface dialog,int which) {
335 | Intent intent = new Intent();
336 | intent.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
337 | intent.setData(Uri.parse("package:com.zzz.wifiview"));
338 | startActivity(new Intent().setClassName("com.zzz.wifiview", "com.zzz.wifiview.ViewActivity"));
339 | startActivity(intent);
340 | finish();
341 | }
342 | });
343 | permissionsDialog.setNegativeButton("关闭", null);
344 | permissionsDialog.show();
345 | }
346 |
347 | public void cmd(String command) {
348 | Process process = null;
349 | DataOutputStream os = null;
350 | try {
351 | process = Runtime.getRuntime().exec("su");
352 | os = new DataOutputStream(process.getOutputStream());
353 | os.writeBytes(command + "\n");
354 | os.writeBytes("exit\n");
355 | os.flush();
356 | process.waitFor();
357 | } catch (Exception e) {
358 | e.printStackTrace();
359 | Toast.makeText(this, "VAcmd: " + e.getMessage(), Toast.LENGTH_LONG).show();
360 | } finally {
361 | try {
362 | if (os != null) {
363 | os.close();
364 | }
365 | process.destroy();
366 | } catch (Exception e) {
367 | e.printStackTrace();
368 | Toast.makeText(this, "VAcmdF: " + e.getMessage(), Toast.LENGTH_LONG).show();
369 | }
370 | }
371 | }
372 |
373 |
374 | }
375 |
--------------------------------------------------------------------------------