From 65d361cb776a90961562af38635ee340a2ccf7f5 Mon Sep 17 00:00:00 2001 From: xiaowusky Date: Wed, 12 Jul 2023 16:15:50 +0800 Subject: [PATCH] =?UTF-8?q?desc:wifi=20=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 23 +- .../com/yinuo/safetywatcher/watcher/App.kt | 14 +- .../watcher/ui/NetSettingActivity.kt | 5 +- .../watcher/ui/SettingActivity.kt | 2 +- .../watcher/ui/view/CommonTopBar.kt | 7 +- .../watcher/ui/view/ConfirmDialog.kt | 4 +- .../watcher/wifi/WiFiConfig.java | 33 + .../watcher/wifi/WiFiModule.java | 203 +++++++ .../wifi/info/WiFiCreateConfigStatusInfo.java | 18 + .../wifi/info/WiFiRemoveStatusInfo.java | 11 + .../watcher/wifi/info/WiFiScanInfo.java | 105 ++++ .../watcher/wifi/info/action/IWiFiAction.java | 38 ++ .../wifi/info/action/WiFiConnectAction.java | 70 +++ .../info/action/WiFiDirectConnectAction.java | 28 + .../wifi/info/action/WiFiDisableAction.java | 7 + .../wifi/info/action/WiFiEnableAction.java | 7 + .../info/action/WiFiNormalConnectAction.java | 29 + .../wifi/info/action/WiFiRemoveAction.java | 26 + .../wifi/info/action/WiFiScanAction.java | 16 + .../interfaces/ConnectWiFiActionListener.java | 13 + .../wifi/interfaces/IActionListener.java | 7 + .../interfaces/RemoveWiFiActionListener.java | 8 + .../interfaces/ScanWiFiActionListener.java | 13 + .../watcher/wifi/interfaces/WiFiListener.java | 61 ++ .../wifi/interfaces/WiFiStatusListener.java | 30 + .../wifi/interfaces/WiFiSupportListener.java | 36 ++ .../interfaces/impl/WiFiListenerImpl.java | 55 ++ .../wifi/interfaces/impl/WiFiStatusImpl.java | 193 ++++++ .../wifi/receiver/WiFiStatusReceiver.java | 52 ++ .../watcher/wifi/type/Types.java | 77 +++ .../watcher/wifi/type/WiFiCipherType.java | 13 + .../wifi/type/WiFiConnectFailType.java | 10 + .../watcher/wifi/type/WiFiConnectType.java | 20 + .../watcher/wifi/type/WiFiGetListType.java | 11 + .../watcher/wifi/ui/GlobalMonitorActivity.kt | 271 +++++++++ .../wifi/ui/InputWiFiPasswordDialog.kt | 123 ++++ .../watcher/wifi/ui/WiFIAdapter.kt | 84 +++ .../watcher/wifi/utils/WiFiLogUtils.java | 32 + .../watcher/wifi/utils/WiFiModuleService.java | 574 ++++++++++++++++++ .../watcher/wifi/utils/WiFiUtils.java | 456 ++++++++++++++ .../main/res/drawable-xhdpi/ic_password.png | Bin 0 -> 471 bytes .../main/res/drawable-xhdpi/ic_progress.png | Bin 0 -> 685 bytes .../main/res/drawable-xhdpi/ic_select_s.png | Bin 0 -> 502 bytes app/src/main/res/drawable/bg_cursor.xml | 9 + app/src/main/res/drawable/bg_input.xml | 9 + app/src/main/res/drawable/loading_img.xml | 11 + app/src/main/res/layout/activity_monitor.xml | 42 ++ .../res/layout/dialog_input_wifi_password.xml | 86 +++ .../main/res/layout/item_network_config.xml | 55 ++ .../main/res/layout/layout_confirm_dialog.xml | 1 + app/src/main/res/values/colors.xml | 3 + 51 files changed, 2982 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/WiFiConfig.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/WiFiModule.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiCreateConfigStatusInfo.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiRemoveStatusInfo.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiScanInfo.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/IWiFiAction.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiConnectAction.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiDirectConnectAction.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiDisableAction.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiEnableAction.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiNormalConnectAction.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiRemoveAction.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiScanAction.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/ConnectWiFiActionListener.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/IActionListener.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/RemoveWiFiActionListener.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/ScanWiFiActionListener.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiListener.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiStatusListener.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiSupportListener.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/impl/WiFiListenerImpl.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/impl/WiFiStatusImpl.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/receiver/WiFiStatusReceiver.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/Types.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiCipherType.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiConnectFailType.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiConnectType.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiGetListType.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/GlobalMonitorActivity.kt create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/InputWiFiPasswordDialog.kt create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/WiFIAdapter.kt create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiLogUtils.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiModuleService.java create mode 100644 app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiUtils.java create mode 100644 app/src/main/res/drawable-xhdpi/ic_password.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_progress.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_select_s.png create mode 100644 app/src/main/res/drawable/bg_cursor.xml create mode 100644 app/src/main/res/drawable/bg_input.xml create mode 100644 app/src/main/res/drawable/loading_img.xml create mode 100644 app/src/main/res/layout/activity_monitor.xml create mode 100644 app/src/main/res/layout/dialog_input_wifi_password.xml create mode 100644 app/src/main/res/layout/item_network_config.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a3b2e5c..07765cb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - @@ -23,6 +22,12 @@ tools:ignore="ProtectedPermissions" /> + + + + + + @@ -51,6 +56,7 @@ android:screenOrientation="landscape"> + @@ -80,7 +86,7 @@ android:name=".watcher.ui.SensorSettingActivity" android:exported="false" android:screenOrientation="landscape" - android:windowSoftInputMode="adjustPan"/> + android:windowSoftInputMode="adjustPan" /> + \ No newline at end of file diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/App.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/App.kt index 05fa2fe..4f014d1 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/App.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/App.kt @@ -1,16 +1,17 @@ package com.yinuo.safetywatcher.watcher import com.common.commonlib.CommonApplication -import com.lztek.toolkit.Lztek -import com.yinuo.safetywatcher.TestUtils import com.common.commonlib.db.DBUtils import com.common.commonlib.db.dao.WarningDao import com.common.commonlib.db.entity.Warning +import com.yinuo.safetywatcher.TestUtils import com.yinuo.safetywatcher.watcher.constant.CAMERA_DNS import com.yinuo.safetywatcher.watcher.constant.CAMERA_GATEWAY import com.yinuo.safetywatcher.watcher.constant.CAMERA_IP import com.yinuo.safetywatcher.watcher.constant.CAMERA_NETMASK import com.yinuo.safetywatcher.watcher.utils.LztekUtil +import com.yinuo.safetywatcher.watcher.wifi.WiFiConfig +import com.yinuo.safetywatcher.watcher.wifi.WiFiModule import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async @@ -23,10 +24,19 @@ class App : CommonApplication() { super.onCreate() LztekUtil.setObject(Lztek.create(this)) ipConfig() + wifiConfig() tryFixDbData() TestUtils.insertData() } + private fun wifiConfig() { + //初始化 + val config: WiFiConfig = WiFiConfig.Builder() + .setTimeOut(1000 * 20) + .build() + WiFiModule.getInstance().setConfig(config).init(this) + } + private fun ipConfig() { LztekUtil.getLztek() ?.setEthIpAddress(CAMERA_IP, CAMERA_NETMASK, CAMERA_GATEWAY, CAMERA_DNS) diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/NetSettingActivity.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/NetSettingActivity.kt index 761aede..dad8a04 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/NetSettingActivity.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/NetSettingActivity.kt @@ -10,6 +10,7 @@ import com.yinuo.safetywatcher.databinding.ActivityNetSettingBinding import com.yinuo.safetywatcher.watcher.base.NoOptionsActivity import com.yinuo.safetywatcher.watcher.utils.NetworkStatsHelper import com.yinuo.safetywatcher.watcher.utils.TrafficFormat +import com.yinuo.safetywatcher.watcher.wifi.ui.GlobalMonitorActivity class NetSettingActivity : NoOptionsActivity() { @@ -29,8 +30,8 @@ class NetSettingActivity : NoOptionsActivity() { override fun initView() { mBinding.apply { itemWifi.setOnClickListener { - Intent.ACTION_FACTORY_TEST - startActivity(Intent(Settings.ACTION_WIFI_SETTINGS)) +// startActivity(Intent(Settings.ACTION_WIFI_SETTINGS)) + startActivity(Intent(this@NetSettingActivity, GlobalMonitorActivity::class.java)) } } diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/SettingActivity.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/SettingActivity.kt index d065d46..2e1af4b 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/SettingActivity.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/SettingActivity.kt @@ -12,7 +12,7 @@ import com.yinuo.safetywatcher.watcher.ui.view.ConfirmDialog class SettingActivity : NoOptionsActivity() { private val resetFactoryDialog by lazy { - ConfirmDialog() { + ConfirmDialog(getString(R.string.confirm_clear_data_tip)) { resetEverything() } } diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/view/CommonTopBar.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/view/CommonTopBar.kt index 7a5acb4..7e3cfe0 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/view/CommonTopBar.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/view/CommonTopBar.kt @@ -71,15 +71,10 @@ class CommonTopBar : LinearLayout { private val wifiCallback = object : WifiHelper.OnWifiLevelCallback { override fun onEnable(enable: Boolean) { Log.i(this@CommonTopBar.javaClass.name, "wifiCallback onEnable = $enable") -// if (enable) { -// mBinding?.wifi?.visibility = VISIBLE -// } else { -// mBinding?.wifi?.visibility = GONE -// } if (!enable) { mBinding?.wifi?.visibility = GONE } else { - mBinding?.wifi?.visibility = VISIBLE +// mBinding?.wifi?.visibility = VISIBLE } } diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/view/ConfirmDialog.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/view/ConfirmDialog.kt index f4a80a0..26fe7e1 100644 --- a/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/view/ConfirmDialog.kt +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/ui/view/ConfirmDialog.kt @@ -12,7 +12,7 @@ import com.yinuo.safetywatcher.R import com.yinuo.safetywatcher.databinding.LayoutConfirmDialogBinding class ConfirmDialog( - private val tipResID: Int = R.string.confirm_clear_data_tip, + private val tipStr: String = "", private val onConfirmClick: (() -> Unit?)? = null ) : DialogFragment() { @@ -25,7 +25,7 @@ class ConfirmDialog( savedInstanceState: Bundle? ): View? { dialogBinding = LayoutConfirmDialogBinding.inflate(inflater, container, false) - dialogBinding!!.tip.text = getString(tipResID) + dialogBinding!!.tip.text = tipStr dialogBinding!!.tvConfirm.setOnClickListener { onConfirmClick?.invoke() } diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/WiFiConfig.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/WiFiConfig.java new file mode 100644 index 0000000..9237c68 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/WiFiConfig.java @@ -0,0 +1,33 @@ +package com.yinuo.safetywatcher.watcher.wifi; + +/** + * WiFi配置 + */ +public class WiFiConfig { + + //默认超时时间 + private static final long DEFAULT_TIME_OUT = 1000 * 15; + + public long timeOut = DEFAULT_TIME_OUT; + + private WiFiConfig() { + } + + public static class Builder { + private WiFiConfig config; + + public Builder() { + config = new WiFiConfig(); + } + + public Builder setTimeOut(long time) { + config.timeOut = time; + return this; + } + + public WiFiConfig build() { + return config; + } + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/WiFiModule.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/WiFiModule.java new file mode 100644 index 0000000..e5dafd2 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/WiFiModule.java @@ -0,0 +1,203 @@ +package com.yinuo.safetywatcher.watcher.wifi; + +import android.content.Context; +import android.net.wifi.WifiConfiguration; + +import androidx.annotation.Nullable; + +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiDirectConnectAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiDisableAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiNormalConnectAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiRemoveAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiScanAction; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.ConnectWiFiActionListener; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.RemoveWiFiActionListener; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.ScanWiFiActionListener; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.WiFiListener; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiCipherType; +import com.yinuo.safetywatcher.watcher.wifi.utils.WiFiLogUtils; +import com.yinuo.safetywatcher.watcher.wifi.utils.WiFiModuleService; + +/** + * WiFi支持类,使用之前先调用{@link #init}方法初始化 + */ +public class WiFiModule { + + private WiFiModuleService mWiFiSupportService; + private WiFiConfig mWiFiConfig = new WiFiConfig.Builder().build(); + private boolean isInit = false; + + private WiFiModule() { + } + + private static class WiFiSupportInner { + private static WiFiModule instance = new WiFiModule(); + } + + public static WiFiModule getInstance() { + return WiFiModule.WiFiSupportInner.instance; + } + + /** + * 设置配置,在{@link #init 之前调用} + */ + public WiFiModule setConfig(WiFiConfig config) { + this.mWiFiConfig = config; + return this; + } + + /** + * 初始化 + */ + public void init(Context context) { + if (isInit) { + return; + } + + this.mWiFiSupportService = new WiFiModuleService(context); + + WiFiLogUtils.d("初始化"); + + isInit = true; + } + + /** + * 添加WiFi状态监听 + * + * @param key 唯一标识 + * @param listener 监听回调 + */ + public void addWiFiListener(String key, WiFiListener listener) { + if (null == mWiFiSupportService) { + WiFiLogUtils.d("请先初始化!"); + return; + } + + mWiFiSupportService.addWiFiListener(key, listener); + } + + /** + * 移除WiFi状态监听 + * + * @param key 唯一标识 + */ + public void removeWiFiListener(String key) { + if (null == mWiFiSupportService) { + WiFiLogUtils.d("请先初始化!"); + return; + } + + mWiFiSupportService.removeWiFiListener(key); + } + + /** + * 扫描WiFi + */ + public void startScan() { + this.startScan(null); + } + + /** + * 扫描WiFi + */ + public void startScan(@Nullable ScanWiFiActionListener listener) { + if (null == mWiFiSupportService) { + WiFiLogUtils.d("请先初始化!"); + return; + } + + WiFiScanAction action = new WiFiScanAction(listener); + mWiFiSupportService.addAction(action); + } + + /** + * 关闭WiFi + */ + public void disableWifi() { + if (null == mWiFiSupportService) { + WiFiLogUtils.d("请先初始化!"); + return; + } + + WiFiDisableAction action = new WiFiDisableAction(); + mWiFiSupportService.addAction(action); + } + + /** + * 通过密码连接WiFi + */ + public void connectWiFi(String SSID, WiFiCipherType type, @Nullable String password) { + this.connectWiFi(SSID, type, password, null); + } + + /** + * 通过密码连接WiFi + */ + public void connectWiFi(String SSID, WiFiCipherType type, @Nullable String password, @Nullable ConnectWiFiActionListener listener) { + if (null == mWiFiSupportService) { + WiFiLogUtils.d("请先初始化!"); + return; + } + + WiFiNormalConnectAction action = new WiFiNormalConnectAction(SSID, type, password, listener); + action.timeout = (null == mWiFiConfig) ? -1 : mWiFiConfig.timeOut; + mWiFiSupportService.addAction(action); + } + + /** + * 通过已经存在的配置连接WiFi + */ + public void connectWiFi(WifiConfiguration configuration) { + this.connectWiFi(configuration, null); + } + + /** + * 通过已经存在的配置连接WiFi + */ + public void connectWiFi(WifiConfiguration configuration, @Nullable ConnectWiFiActionListener listener) { + if (null == mWiFiSupportService) { + return; + } + + String SSID = configuration.SSID; + int size = SSID.length(); + SSID = SSID.substring(1, size - 1); + + WiFiDirectConnectAction action = new WiFiDirectConnectAction(SSID, configuration, listener); + action.timeout = mWiFiConfig.timeOut; + mWiFiSupportService.addAction(action); + } + + /** + * 移除WiFi + */ + public void removeWiFi(final String SSID) { + this.removeWiFi(SSID, null); + } + + /** + * 移除WiFi + */ + public void removeWiFi(final String SSID, @Nullable RemoveWiFiActionListener listener) { + if (null == mWiFiSupportService) { + WiFiLogUtils.d("请先初始化!"); + return; + } + + WiFiRemoveAction action = new WiFiRemoveAction(SSID, listener); + mWiFiSupportService.addAction(action); + } + + /** + * 销毁资源 + */ + public void destroy() { + if (null != mWiFiSupportService) { + mWiFiSupportService.destroy(); + } + + isInit = false; + mWiFiSupportService = null; + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiCreateConfigStatusInfo.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiCreateConfigStatusInfo.java new file mode 100644 index 0000000..f3df127 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiCreateConfigStatusInfo.java @@ -0,0 +1,18 @@ +package com.yinuo.safetywatcher.watcher.wifi.info; + +import android.net.wifi.WifiConfiguration; + +/** + * 创建WiFi配置状态 + */ +public class WiFiCreateConfigStatusInfo { + + public String SSID; + public WifiConfiguration configuration; + public boolean isSuccess; + + public boolean isSuccess() { + return isSuccess && null != configuration; + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiRemoveStatusInfo.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiRemoveStatusInfo.java new file mode 100644 index 0000000..146e562 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiRemoveStatusInfo.java @@ -0,0 +1,11 @@ +package com.yinuo.safetywatcher.watcher.wifi.info; + +/** + * 删除WiFi状态 + */ +public class WiFiRemoveStatusInfo { + + public String SSID; + public boolean isSuccess; + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiScanInfo.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiScanInfo.java new file mode 100644 index 0000000..34304e1 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/WiFiScanInfo.java @@ -0,0 +1,105 @@ +package com.yinuo.safetywatcher.watcher.wifi.info; + +import android.net.wifi.ScanResult; +import android.net.wifi.WifiConfiguration; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import androidx.annotation.NonNull; + +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiCipherType; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiConnectType; + +/** + * WiFi扫描信息 + */ +public class WiFiScanInfo implements Comparable, Parcelable { + + //扫描结果 + public ScanResult scanResult; + //连接过的WiFi配置,可能为空 + public WifiConfiguration configuration; + //WiFi型号强度(1~4) + public int level; + //连接状态:0 未连接,1 正在连接,2 已连接 + public int connectType = WiFiConnectType.DISCONNECTED.type; + + @Override + public int compareTo(WiFiScanInfo o) { + //按照信号强度从大到小排序 + return o.level - level; + } + + @NonNull + @Override + public String toString() { + return "{" + + "\"SSID\":\"" + scanResult.SSID + "\"," + + "\"type\":" + getCipherType().ordinal() + "," + + "\"level\":" + level + + "}"; + } + + /** + * 返回WiFi加密类型 + * + * @return WiFiCipherType + */ + public WiFiCipherType getCipherType() { + if (null == scanResult) { + return WiFiCipherType.WIFI_CIPHER_INVALID; + } + + String capabilities = scanResult.capabilities; + + if (TextUtils.isEmpty(capabilities)) { + return WiFiCipherType.WIFI_CIPHER_INVALID; + } + + if (capabilities.contains("WPA") || capabilities.contains("wpa") || capabilities.contains("WPA2") || capabilities.contains("WPS")) { + return WiFiCipherType.WIFI_CIPHER_WPA; + } + + if (capabilities.contains("WEP") || capabilities.contains("wep")) { + return WiFiCipherType.WIFI_CIPHER_WEP; + } + + return WiFiCipherType.WIFI_CIPHER_NO_PASS; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(this.scanResult, flags); + dest.writeParcelable(this.configuration, flags); + dest.writeInt(this.level); + dest.writeInt(this.connectType); + } + + public WiFiScanInfo() { + } + + protected WiFiScanInfo(Parcel in) { + this.scanResult = in.readParcelable(ScanResult.class.getClassLoader()); + this.configuration = in.readParcelable(WifiConfiguration.class.getClassLoader()); + this.level = in.readInt(); + this.connectType = in.readInt(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public WiFiScanInfo createFromParcel(Parcel source) { + return new WiFiScanInfo(source); + } + + @Override + public WiFiScanInfo[] newArray(int size) { + return new WiFiScanInfo[size]; + } + }; +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/IWiFiAction.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/IWiFiAction.java new file mode 100644 index 0000000..7660ce9 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/IWiFiAction.java @@ -0,0 +1,38 @@ +package com.yinuo.safetywatcher.watcher.wifi.info.action; + +import androidx.annotation.NonNull; + +import com.yinuo.safetywatcher.watcher.wifi.type.Types; + +public abstract class IWiFiAction { + + @Types.ActionStateType + private int actionState; + + IWiFiAction() { + setState(Types.ActionStateType.WAITING); + } + + private String getActionName() { + return getClass().getSimpleName(); + } + + public int getActionState() { + return actionState; + } + + public void setState(@Types.ActionStateType int state) { + this.actionState = state; + } + + public void end() { + this.actionState = Types.ActionStateType.END; + } + + @NonNull + @Override + public String toString() { + return getActionName() + " | actionState:" + actionState; + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiConnectAction.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiConnectAction.java new file mode 100644 index 0000000..4d744a9 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiConnectAction.java @@ -0,0 +1,70 @@ +package com.yinuo.safetywatcher.watcher.wifi.info.action; + +import android.os.Handler; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.yinuo.safetywatcher.watcher.wifi.interfaces.ConnectWiFiActionListener; +import com.yinuo.safetywatcher.watcher.wifi.utils.WiFiLogUtils; + +import java.lang.ref.WeakReference; + +/** + * 连接WiFi + */ +public abstract class WiFiConnectAction extends IWiFiAction { + + public String SSID; + public ConnectWiFiActionListener listener; + public long timeout = 1000 * 15;//超时时间,默认15s + private WeakReference mHandler; + private Runnable mDelayRunnable; + + WiFiConnectAction(@NonNull String SSID, @Nullable ConnectWiFiActionListener listener) { + this.SSID = SSID; + this.listener = listener; + } + + @Override + public void end() { + super.end(); + + stopDelayCheck(); + } + + /** + * 开始延时检测 + */ + public void startDelayCheck(Handler handler, Runnable runnable) { + this.mHandler = new WeakReference<>(handler); + this.mDelayRunnable = runnable; + + try { + handler.postDelayed(runnable, this.timeout); + WiFiLogUtils.d("开启超时检测," + toString()); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + } + + /** + * 结束延时检测 + */ + private void stopDelayCheck() { + try { + if (null == this.mDelayRunnable) { + return; + } + + this.mHandler.get().removeCallbacks(this.mDelayRunnable); + this.mDelayRunnable = null; + WiFiLogUtils.d("超时检测关闭," + toString()); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiDirectConnectAction.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiDirectConnectAction.java new file mode 100644 index 0000000..288dfe6 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiDirectConnectAction.java @@ -0,0 +1,28 @@ +package com.yinuo.safetywatcher.watcher.wifi.info.action; + +import android.net.wifi.WifiConfiguration; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.yinuo.safetywatcher.watcher.wifi.interfaces.ConnectWiFiActionListener; + +/** + * 通过配置直接连接 + */ +public class WiFiDirectConnectAction extends WiFiConnectAction { + + public WifiConfiguration configuration; + + public WiFiDirectConnectAction(@NonNull String SSID, @NonNull WifiConfiguration configuration, @Nullable ConnectWiFiActionListener listener) { + super(SSID, listener); + this.configuration = configuration; + } + + @NonNull + @Override + public String toString() { + return super.toString() + " | " + SSID; + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiDisableAction.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiDisableAction.java new file mode 100644 index 0000000..3189b22 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiDisableAction.java @@ -0,0 +1,7 @@ +package com.yinuo.safetywatcher.watcher.wifi.info.action; + +/** + * 禁用WiFi + */ +public class WiFiDisableAction extends IWiFiAction { +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiEnableAction.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiEnableAction.java new file mode 100644 index 0000000..3c34daf --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiEnableAction.java @@ -0,0 +1,7 @@ +package com.yinuo.safetywatcher.watcher.wifi.info.action; + +/** + * 启用WiFi + */ +public class WiFiEnableAction extends IWiFiAction { +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiNormalConnectAction.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiNormalConnectAction.java new file mode 100644 index 0000000..06512be --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiNormalConnectAction.java @@ -0,0 +1,29 @@ +package com.yinuo.safetywatcher.watcher.wifi.info.action; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.yinuo.safetywatcher.watcher.wifi.interfaces.ConnectWiFiActionListener; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiCipherType; + +/** + * 通过密码连接WiFi + */ +public class WiFiNormalConnectAction extends WiFiConnectAction { + + public WiFiCipherType cipherType; + public String password; + + public WiFiNormalConnectAction(@NonNull String SSID, @NonNull WiFiCipherType cipherType, @Nullable String password, @Nullable ConnectWiFiActionListener listener) { + super(SSID, listener); + + this.cipherType = cipherType; + this.password = password; + } + + @NonNull + @Override + public String toString() { + return super.toString() + " | " + SSID + " | " + cipherType.name(); + } +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiRemoveAction.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiRemoveAction.java new file mode 100644 index 0000000..b2a9720 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiRemoveAction.java @@ -0,0 +1,26 @@ +package com.yinuo.safetywatcher.watcher.wifi.info.action; + +import androidx.annotation.NonNull; + +import com.yinuo.safetywatcher.watcher.wifi.interfaces.RemoveWiFiActionListener; + +/** + * 移除 + */ +public class WiFiRemoveAction extends IWiFiAction { + + public String SSID; + public RemoveWiFiActionListener listener; + + public WiFiRemoveAction(String SSID, RemoveWiFiActionListener listener) { + this.SSID = SSID; + this.listener = listener; + } + + @NonNull + @Override + public String toString() { + return super.toString() + " | " + SSID; + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiScanAction.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiScanAction.java new file mode 100644 index 0000000..9516a6f --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/info/action/WiFiScanAction.java @@ -0,0 +1,16 @@ +package com.yinuo.safetywatcher.watcher.wifi.info.action; + +import com.yinuo.safetywatcher.watcher.wifi.interfaces.ScanWiFiActionListener; + +/** + * 扫描WiFi + */ +public class WiFiScanAction extends IWiFiAction { + + public ScanWiFiActionListener listener; + + public WiFiScanAction(ScanWiFiActionListener listener) { + this.listener = listener; + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/ConnectWiFiActionListener.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/ConnectWiFiActionListener.java new file mode 100644 index 0000000..8120e22 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/ConnectWiFiActionListener.java @@ -0,0 +1,13 @@ +package com.yinuo.safetywatcher.watcher.wifi.interfaces; + +import android.net.wifi.WifiConfiguration; + +import com.yinuo.safetywatcher.watcher.wifi.type.Types; + +public interface ConnectWiFiActionListener extends IActionListener { + + void onCreateConfig(WifiConfiguration configuration); + + void onResult(@Types.ConnectResultType int type); + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/IActionListener.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/IActionListener.java new file mode 100644 index 0000000..070b117 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/IActionListener.java @@ -0,0 +1,7 @@ +package com.yinuo.safetywatcher.watcher.wifi.interfaces; + +public interface IActionListener { + + void onStart(); + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/RemoveWiFiActionListener.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/RemoveWiFiActionListener.java new file mode 100644 index 0000000..a8beaed --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/RemoveWiFiActionListener.java @@ -0,0 +1,8 @@ +package com.yinuo.safetywatcher.watcher.wifi.interfaces; + +import com.yinuo.safetywatcher.watcher.wifi.type.Types; + +public interface RemoveWiFiActionListener extends IActionListener { + + void onResult(@Types.RemoveResultType int type); +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/ScanWiFiActionListener.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/ScanWiFiActionListener.java new file mode 100644 index 0000000..7e597d0 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/ScanWiFiActionListener.java @@ -0,0 +1,13 @@ +package com.yinuo.safetywatcher.watcher.wifi.interfaces; + +import androidx.annotation.Nullable; + +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiScanInfo; +import com.yinuo.safetywatcher.watcher.wifi.type.Types; + +import java.util.List; + +public interface ScanWiFiActionListener extends IActionListener { + + void onResult(@Types.ScanResultType int type, @Nullable List list); +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiListener.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiListener.java new file mode 100644 index 0000000..193349f --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiListener.java @@ -0,0 +1,61 @@ +package com.yinuo.safetywatcher.watcher.wifi.interfaces; + +import android.net.wifi.WifiConfiguration; + +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiRemoveStatusInfo; +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiScanInfo; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiConnectFailType; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiGetListType; + +import java.util.List; + +/** + * WiFi全局相关状态监听 + */ +public interface WiFiListener { + + /** + * 开始扫描WiFi + */ + void onStartScan(); + + /** + * 通知WiFi关闭 + */ + void onCloseWiFi(); + + /** + * WiFi数据更新 + */ + void onDataChange(WiFiGetListType type, List list); + + /** + * 开始连接WiFi + */ + void onWiFiStartConnect(String SSID); + + /** + * 创建WiFi配置 + */ + void onWiFiCreateConfig(String SSID, WifiConfiguration configuration); + + /** + * WiFi连接成功 + * + * @param isInit 标识是否是初始连接成功 + */ + void onWiFiConnected(String SSID, boolean isInit); + + /** + * WiFi连接失败 + * + * @param type 失败类型 + */ + void onWiFiConnectFail(String SSID, WiFiConnectFailType type); + + /** + * 删除WiFi状态 + */ + void onWiFiRemoveResult(WiFiRemoveStatusInfo info); + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiStatusListener.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiStatusListener.java new file mode 100644 index 0000000..4ede0b1 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiStatusListener.java @@ -0,0 +1,30 @@ +package com.yinuo.safetywatcher.watcher.wifi.interfaces; + +import android.content.Intent; + +/** + * WiFi状态回调 + */ +public interface WiFiStatusListener { + + /** + * 处理扫描列表 + */ + void handleScanResultsChanged(Intent intent); + + /** + * 处理WiFi状态 + */ + void handleWiFiStateChanged(Intent intent); + + /** + * 处理网络状态 + */ + void handleNetStateChanged(Intent intent); + + /** + * 处理WiFi状态(密码错误回调) + */ + void handleSupplicantStateChanged(Intent intent); + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiSupportListener.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiSupportListener.java new file mode 100644 index 0000000..7e84473 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/WiFiSupportListener.java @@ -0,0 +1,36 @@ +package com.yinuo.safetywatcher.watcher.wifi.interfaces; + +import android.net.wifi.WifiInfo; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.yinuo.safetywatcher.watcher.wifi.info.action.IWiFiAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiConnectAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiScanAction; +import com.yinuo.safetywatcher.watcher.wifi.type.Types; + +public interface WiFiSupportListener { + + /** + * 获取当前执行的action + */ + @Nullable + IWiFiAction getCurrentAction(); + + /** + * 获取当前了解的WiFi信息 + */ + WifiInfo getConnectedWifiInfo(); + + void onWiFiClose(); + + void onWiFiListChange(); + + void doneScanAction(@NonNull WiFiScanAction action); + + void doneConnectSuccess(@NonNull String SSID, @Types.ConnectSuccessType int type); + + void doneConnectFail(@NonNull WiFiConnectAction action); + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/impl/WiFiListenerImpl.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/impl/WiFiListenerImpl.java new file mode 100644 index 0000000..b969ea9 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/impl/WiFiListenerImpl.java @@ -0,0 +1,55 @@ +package com.yinuo.safetywatcher.watcher.wifi.interfaces.impl; + +import android.net.wifi.WifiConfiguration; + +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiRemoveStatusInfo; +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiScanInfo; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.WiFiListener; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiConnectFailType; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiGetListType; + +import java.util.List; + +public class WiFiListenerImpl implements WiFiListener { + + @Override + public void onStartScan() { + + } + + @Override + public void onCloseWiFi() { + + } + + @Override + public void onDataChange(WiFiGetListType type, List list) { + + } + + @Override + public void onWiFiStartConnect(String SSID) { + + } + + @Override + public void onWiFiCreateConfig(String SSID, WifiConfiguration configuration) { + + } + + @Override + public void onWiFiConnected(String SSID, boolean isInit) { + + } + + @Override + public void onWiFiConnectFail(String SSID, WiFiConnectFailType type) { + + } + + @Override + public void onWiFiRemoveResult(WiFiRemoveStatusInfo info) { + + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/impl/WiFiStatusImpl.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/impl/WiFiStatusImpl.java new file mode 100644 index 0000000..658d961 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/interfaces/impl/WiFiStatusImpl.java @@ -0,0 +1,193 @@ +package com.yinuo.safetywatcher.watcher.wifi.interfaces.impl; + +import android.content.Intent; +import android.net.NetworkInfo; +import android.net.wifi.SupplicantState; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; + +import com.yinuo.safetywatcher.watcher.wifi.info.action.IWiFiAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiConnectAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiDirectConnectAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiDisableAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiEnableAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiScanAction; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.WiFiStatusListener; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.WiFiSupportListener; +import com.yinuo.safetywatcher.watcher.wifi.type.Types; +import com.yinuo.safetywatcher.watcher.wifi.utils.WiFiLogUtils; + +public class WiFiStatusImpl implements WiFiStatusListener { + + private WiFiSupportListener mSupportListener; + + public WiFiStatusImpl(WiFiSupportListener listener) { + this.mSupportListener = listener; + } + + @Override + public void handleScanResultsChanged(Intent intent) { + if (null == mSupportListener) { + return; + } + + IWiFiAction action = mSupportListener.getCurrentAction(); + if (action instanceof WiFiScanAction) { + //扫描结束 + WiFiLogUtils.d("扫描结束," + action.toString()); + mSupportListener.doneScanAction((WiFiScanAction) action); + return; + } + + //WiFi列表发生变动 + mSupportListener.onWiFiListChange(); + } + + @Override + public void handleWiFiStateChanged(Intent intent) { + if (null == intent) { + return; + } + + int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, -1); + + switch (state) { + case WifiManager.WIFI_STATE_DISABLED: { + //WIFI处于关闭状态 + WiFiLogUtils.d("WIFI已关闭"); + + IWiFiAction action = (null == mSupportListener) ? null : mSupportListener.getCurrentAction(); + if (action instanceof WiFiDisableAction) { + action.end(); + } + + if (null != mSupportListener) { + mSupportListener.onWiFiClose(); + } + break; + } + + case WifiManager.WIFI_STATE_DISABLING: { + //正在关闭 + WiFiLogUtils.d("WIFI关闭中"); + break; + } + + case WifiManager.WIFI_STATE_ENABLED: { + //已经打开 + WiFiLogUtils.d("WIFI已打开"); + + //判断当前执行的action是否是WiFiScanAction + IWiFiAction action = (null == mSupportListener) ? null : mSupportListener.getCurrentAction(); + if (action instanceof WiFiEnableAction) { + action.end(); + } + break; + } + + case WifiManager.WIFI_STATE_ENABLING: { + //正在打开 + WiFiLogUtils.d("打开WIFI中..."); + break; + } + + default: + break; + } + } + + @Override + public void handleNetStateChanged(Intent intent) { + if (null == intent) { + return; + } + + NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); + NetworkInfo.DetailedState state = info.getDetailedState(); + + if (NetworkInfo.DetailedState.CONNECTED == state) { + if (null == mSupportListener) { + return; + } + + WifiInfo wifiInfo = mSupportListener.getConnectedWifiInfo(); + if (null == wifiInfo) { + WiFiLogUtils.d("当前连接的 WifiInfo 为空"); + return; + } + + String SSID = wifiInfo.getSSID(); + int size = SSID.length(); + SSID = SSID.substring(1, size - 1); + + //连接成功 + IWiFiAction action = mSupportListener.getCurrentAction(); + + if (action instanceof WiFiConnectAction) { + WiFiConnectAction wiFiConnectAction = (WiFiConnectAction) action; + + if (!wiFiConnectAction.SSID.equals(SSID)) { + WiFiLogUtils.d("当前" + wiFiConnectAction.SSID + "与" + SSID + "不一致!"); + mSupportListener.doneConnectSuccess(SSID, Types.ConnectSuccessType.NOT_MATCH); + + return; + } + + if (null != wiFiConnectAction.listener) { + wiFiConnectAction.listener.onResult(Types.ConnectResultType.SUCCESS); + } + + mSupportListener.doneConnectSuccess(SSID, Types.ConnectSuccessType.NORMAL); + + WiFiLogUtils.d("WiFi连接成功," + action.toString()); + action.end(); + + return; + } + + WiFiLogUtils.d("WiFi连接成功," + SSID); + mSupportListener.doneConnectSuccess(SSID, Types.ConnectSuccessType.SYSTEM); + } + } + + @Override + public void handleSupplicantStateChanged(Intent intent) { + if (null == intent) { + return; + } + + SupplicantState state = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE); + int errorResult = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1); + + if (null != state && state == SupplicantState.DISCONNECTED && errorResult == WifiManager.ERROR_AUTHENTICATING) { + + if (null == mSupportListener) { + return; + } + + //密码错误 + IWiFiAction action = mSupportListener.getCurrentAction(); + + if (action instanceof WiFiConnectAction) { + + if (Types.ActionStateType.END == action.getActionState()) { + return; + } + + if (null != ((WiFiConnectAction) action).listener) { + if (action instanceof WiFiDirectConnectAction) { + ((WiFiConnectAction) action).listener.onResult(Types.ConnectResultType.DIRECT_PASSWORD_ERROR); + + } else { + ((WiFiConnectAction) action).listener.onResult(Types.ConnectResultType.PASSWORD_ERROR); + } + } + + mSupportListener.doneConnectFail(((WiFiConnectAction) action)); + WiFiLogUtils.d("WiFi连接失败,密码错误," + action.toString()); + action.end(); + } + } + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/receiver/WiFiStatusReceiver.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/receiver/WiFiStatusReceiver.java new file mode 100644 index 0000000..d8ace76 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/receiver/WiFiStatusReceiver.java @@ -0,0 +1,52 @@ +package com.yinuo.safetywatcher.watcher.wifi.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.wifi.WifiManager; +import android.text.TextUtils; + +import com.yinuo.safetywatcher.watcher.wifi.interfaces.WiFiStatusListener; + +/** + * WiFi状态接受 + */ +public class WiFiStatusReceiver extends BroadcastReceiver { + + private WiFiStatusListener mCallback; + + public WiFiStatusReceiver(WiFiStatusListener callback) { + this.mCallback = callback; + } + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (null == mCallback || null == action || TextUtils.isEmpty(action)) { + return; + } + + switch (action) { + case WifiManager.SCAN_RESULTS_AVAILABLE_ACTION: + mCallback.handleScanResultsChanged(intent); + break; + + case WifiManager.WIFI_STATE_CHANGED_ACTION: + mCallback.handleWiFiStateChanged(intent); + break; + + case WifiManager.NETWORK_STATE_CHANGED_ACTION: + mCallback.handleNetStateChanged(intent); + break; + + case WifiManager.SUPPLICANT_STATE_CHANGED_ACTION: + mCallback.handleSupplicantStateChanged(intent); + break; + + default: + break; + } + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/Types.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/Types.java new file mode 100644 index 0000000..f7dfe55 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/Types.java @@ -0,0 +1,77 @@ +package com.yinuo.safetywatcher.watcher.wifi.type; + +import androidx.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +public class Types { + + @IntDef({ + ScanResultType.UNKNOWN, + ScanResultType.FREQUENTLY_SCAN_ERROR, + ScanResultType.OPEN_WIFI_ERROR, + ScanResultType.SUCCESS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ScanResultType { + int UNKNOWN = -1;//未知错误 + int FREQUENTLY_SCAN_ERROR = 0;//频繁扫描 + int OPEN_WIFI_ERROR = 1;//开启WiFi失败 + int SUCCESS = 2;//扫描成功 + } + + @IntDef({ + RemoveResultType.SYSTEM_LIMIT_ERROR, + RemoveResultType.SUCCESS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RemoveResultType { + int SYSTEM_LIMIT_ERROR = 0;//系统限制,删除失败 + int SUCCESS = 1;//删除成功 + } + + @IntDef({ + ConnectResultType.UNKNOWN, + ConnectResultType.SYSTEM_LIMIT_ERROR, + ConnectResultType.TIMEOUT_ERROR, + ConnectResultType.PASSWORD_ERROR, + ConnectResultType.DIRECT_PASSWORD_ERROR, + ConnectResultType.SUCCESS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ConnectResultType { + int UNKNOWN = -1;//未知错误 + int SYSTEM_LIMIT_ERROR = 0;//系统限制,删除失败 + int TIMEOUT_ERROR = 1;//连接超时 + int PASSWORD_ERROR = 2;//密码错误 + int DIRECT_PASSWORD_ERROR = 3;//直连密码错误 + int SUCCESS = 5;//连接成功 + } + + @IntDef({ + ActionStateType.WAITING, + ActionStateType.PROCESS, + ActionStateType.END, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ActionStateType { + int WAITING = 0;//待执行 + int PROCESS = 1;//执行中 + int END = 2;//执行完成 + } + + + @IntDef({ + ConnectSuccessType.NOT_MATCH, + ConnectSuccessType.NORMAL, + ConnectSuccessType.SYSTEM, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ConnectSuccessType { + int NOT_MATCH = 1;//不匹配 + int NORMAL = 2;//正常处理 + int SYSTEM = 3;//没有执行操作时连接成功 + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiCipherType.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiCipherType.java new file mode 100644 index 0000000..e8a4e90 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiCipherType.java @@ -0,0 +1,13 @@ +package com.yinuo.safetywatcher.watcher.wifi.type; + +/** + * WiFi加密方式 + */ +public enum WiFiCipherType { + + WIFI_CIPHER_WEP, + WIFI_CIPHER_WPA,//默认都是这种 + WIFI_CIPHER_NO_PASS, + WIFI_CIPHER_INVALID + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiConnectFailType.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiConnectFailType.java new file mode 100644 index 0000000..4628b0d --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiConnectFailType.java @@ -0,0 +1,10 @@ +package com.yinuo.safetywatcher.watcher.wifi.type; + +public enum WiFiConnectFailType { + + PASSWORD_ERROR,//密码错误 + DIRECT_PASSWORD_ERROR,//直接连接,密码错误 + TIMEOUT_ERROR,//连接超时 + SYSTEM_LIMIT_ERROR,//系统限制 + UNKNOWN,//未知 +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiConnectType.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiConnectType.java new file mode 100644 index 0000000..8029d1d --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiConnectType.java @@ -0,0 +1,20 @@ +package com.yinuo.safetywatcher.watcher.wifi.type; + +/** + * WiFi连接状态 + */ +public enum WiFiConnectType { + + DISCONNECTED(0, "未连接"), + CONNECTING(1, "连接中"), + CONNECTED(2, "已连接"); + + public int type; + public String state; + + WiFiConnectType(int type, String state) { + this.type = type; + this.state = state; + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiGetListType.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiGetListType.java new file mode 100644 index 0000000..0ba5554 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/type/WiFiGetListType.java @@ -0,0 +1,11 @@ +package com.yinuo.safetywatcher.watcher.wifi.type; + +/** + * 获取列表的类型 + */ +public enum WiFiGetListType { + + TYPE_SCAN,//扫描 + TYPE_SORT//排序 + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/GlobalMonitorActivity.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/GlobalMonitorActivity.kt new file mode 100644 index 0000000..3b67a81 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/GlobalMonitorActivity.kt @@ -0,0 +1,271 @@ +package com.yinuo.safetywatcher.watcher.wifi.ui + +import android.content.Context +import android.content.Intent +import android.net.wifi.WifiConfiguration +import android.net.wifi.WifiManager +import android.os.Bundle +import android.provider.Settings +import android.text.TextUtils +import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import com.yinuo.safetywatcher.R +import com.yinuo.safetywatcher.databinding.ActivityMonitorBinding +import com.yinuo.safetywatcher.watcher.base.NoOptionsActivity +import com.yinuo.safetywatcher.watcher.ui.view.ConfirmDialog +import com.yinuo.safetywatcher.watcher.wifi.WiFiModule +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiRemoveStatusInfo +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiScanInfo +import com.yinuo.safetywatcher.watcher.wifi.interfaces.ConnectWiFiActionListener +import com.yinuo.safetywatcher.watcher.wifi.interfaces.RemoveWiFiActionListener +import com.yinuo.safetywatcher.watcher.wifi.interfaces.ScanWiFiActionListener +import com.yinuo.safetywatcher.watcher.wifi.interfaces.WiFiListener +import com.yinuo.safetywatcher.watcher.wifi.interfaces.impl.WiFiListenerImpl +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiCipherType +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiConnectFailType +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiConnectType +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiGetListType +import com.yinuo.safetywatcher.watcher.wifi.utils.WiFiUtils + +class GlobalMonitorActivity : NoOptionsActivity() { + var mData: MutableList? = null + var mAdapter: WiFIAdapter? = null + + private var delDialog: ConfirmDialog? = null + private var delErrorDialog: ConfirmDialog? = null + + override fun initView() { + initSwitch() + initParams() + initEvents() + } + + private fun initSwitch() { + val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager + val wiFiEnable = WiFiUtils.isWiFiEnable(wifiManager) + mBinding.wifiSwitch.isChecked = wiFiEnable + if (wiFiEnable) { + WiFiModule.getInstance().startScan(scanActionListener) + } + mBinding.tvStatus.text = if (wiFiEnable) "WiFi已开启" else "WiFi已关闭" + mBinding.areaSwitch.setOnClickListener { + mBinding.wifiSwitch.performClick() + } + } + + private fun initEvents() { + mBinding.wifiSwitch!!.setOnCheckedChangeListener { _, isChecked -> + if (isChecked) { + WiFiModule.getInstance().startScan(scanActionListener) + } else { + WiFiModule.getInstance().disableWifi() + } + } + } + + private fun initParams() { + mData = ArrayList() + mAdapter = WiFIAdapter(onItemClick = { wifiInfo -> + if (wifiInfo.connectType != WiFiConnectType.CONNECTED.type) { + //输入密码,连接 + if (null != wifiInfo.configuration) { + WiFiModule.getInstance() + .connectWiFi(wifiInfo.configuration, getConnectActionListener(wifiInfo)) + } else { + showInputDialog(wifiInfo, 0) + } + } else { + showDelDialog(wifiInfo) + } + }, onItemLongClick = { info -> + if (null != info.configuration) { + showDelDialog(info) + } + }) + mBinding.rvData.adapter = mAdapter + mBinding.rvData.layoutManager = LinearLayoutManager(this@GlobalMonitorActivity) + + //添加监听 + WiFiModule.getInstance().addWiFiListener(TAG, mListener) + } + + private val mListener: WiFiListener = object : WiFiListenerImpl() { + override fun onStartScan() { + mBinding.tvStatus!!.text = "扫描中..." + mBinding.wifiSwitch!!.isEnabled = false + } + + override fun onCloseWiFi() { + mBinding.tvStatus!!.text = "WiFi已关闭" + mData!!.clear() + mAdapter?.setData(mData!!) + } + + override fun onDataChange(type: WiFiGetListType, list: List) { + if (type == WiFiGetListType.TYPE_SCAN) { + mBinding.wifiSwitch!!.isEnabled = true + mBinding.tvStatus!!.text = "扫描结束" + } + mData!!.clear() + mData!!.addAll(list) + mAdapter?.setData(mData!!) + } + + override fun onWiFiStartConnect(SSID: String) { + mBinding.tvStatus!!.text = SSID + "连接中..." + refreshData(SSID, WiFiConnectType.CONNECTING) + } + + override fun onWiFiCreateConfig(SSID: String, configuration: WifiConfiguration) { + for (info in mData!!) { + if (!TextUtils.isEmpty(SSID) && SSID == info.scanResult.SSID) { + info.configuration = configuration + break + } + } + refreshData(SSID, WiFiConnectType.CONNECTING) + } + + override fun onWiFiConnected(SSID: String, isInit: Boolean) { + mBinding.tvStatus!!.text = isInit.toString() + " || " + SSID + "已连接" + refreshData(SSID, WiFiConnectType.CONNECTED) + } + + override fun onWiFiConnectFail(SSID: String, type: WiFiConnectFailType) { + if (TextUtils.isEmpty(SSID)) { + return + } + mBinding.tvStatus!!.text = SSID + "连接失败," + type.name + refreshData(SSID, WiFiConnectType.DISCONNECTED) + if (type == WiFiConnectFailType.DIRECT_PASSWORD_ERROR) { + //直连密码错误,提示用户修改密码 + val scanInfo = findScanInfo(SSID) + if (null != scanInfo) { + showInputDialog(scanInfo, 1) + } + } + } + + override fun onWiFiRemoveResult(info: WiFiRemoveStatusInfo) { + if (!info.isSuccess) { + mBinding.tvStatus!!.text = info.SSID + "删除失败!" + showDelErrorDialog() + return + } + mBinding.tvStatus!!.text = info.SSID + "删除成功!" + for (connectInfo in mData!!) { + if (!TextUtils.isEmpty(info.SSID) && info.SSID == connectInfo.scanResult.SSID) { + connectInfo.configuration = null + break + } + } + refreshData(info.SSID, WiFiConnectType.DISCONNECTED) + } + } + private val scanActionListener: ScanWiFiActionListener? + get() = null + + private fun getConnectActionListener(info: WiFiScanInfo?): ConnectWiFiActionListener? { + return null + } + + private fun getRemoveActionListener(SSID: String?): RemoveWiFiActionListener? { + return null + } + + /** + * 删除wifi + */ + private fun showDelDialog(info: WiFiScanInfo) { + delDialog = ConfirmDialog("确定要删除${info.scanResult.SSID}吗?删除后需要重新输入密码") { + delDialog?.dismiss() + WiFiModule.getInstance() + .removeWiFi(info.scanResult.SSID, getRemoveActionListener(info.scanResult.SSID)) + } + delDialog?.show(supportFragmentManager, "del") + } + + /** + * 输入密码连接wifi + */ + fun showInputDialog(info: WiFiScanInfo, type: Int) { + if (WiFiCipherType.WIFI_CIPHER_NO_PASS == info.cipherType) { + WiFiModule.getInstance() + .connectWiFi(info.scanResult.SSID, WiFiCipherType.WIFI_CIPHER_NO_PASS, null) + } else { + val dialog = InputWiFiPasswordDialog() + val bundle = Bundle() + bundle.putParcelable("info", info) + bundle.putInt("connectType", type) + dialog.arguments = bundle + dialog.show(supportFragmentManager, TAG_FRAG) + dialog.setConnectListener(getConnectActionListener(info)) + } + } + + /** + * 删除失败,提示用户去系统设置操作 + */ + fun showDelErrorDialog() { + hideInputWiFiPasswordDialog() + delErrorDialog = ConfirmDialog("由于系统限制,需要到系统设置->WiFi/WLAN中忘记网络") { + delErrorDialog?.dismiss() + val intent = Intent(Settings.ACTION_WIFI_SETTINGS) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + startActivity(intent) + } + delErrorDialog?.show(supportFragmentManager, "error") + } + + private fun hideInputWiFiPasswordDialog() { + val fragment = supportFragmentManager.findFragmentByTag(TAG_FRAG) + if (null != fragment && fragment.isVisible && fragment is InputWiFiPasswordDialog) { + fragment.dismissAllowingStateLoss() + } + } + + fun findScanInfo(SSID: String): WiFiScanInfo? { + for (scanInfo in mData!!) { + if (SSID == scanInfo.scanResult.SSID) { + return scanInfo + } + } + return null + } + + fun refreshData(SSID: String, connectType: WiFiConnectType) { + if (TextUtils.isEmpty(SSID)) { + return + } + for (info in mData!!) { + if (!TextUtils.isEmpty(SSID) && SSID == info.scanResult.SSID) { + info.connectType = connectType.type + } else { + info.connectType = WiFiConnectType.DISCONNECTED.type + } + } + mAdapter?.setData(mData!!) + } + + override fun onDestroy() { + super.onDestroy() + WiFiModule.getInstance().removeWiFiListener(TAG) + } + + override fun getTopBarTitle(): String { + return getString(R.string.wifi_setting) + } + + override fun generateContentView(): View { + return mBinding.root + } + + private val mBinding: ActivityMonitorBinding by lazy { + ActivityMonitorBinding.inflate(layoutInflater) + } + + companion object { + const val TAG = "BaseMonitorActivity" + const val TAG_FRAG = "InputWiFiPasswordDialog" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/InputWiFiPasswordDialog.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/InputWiFiPasswordDialog.kt new file mode 100644 index 0000000..f455827 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/InputWiFiPasswordDialog.kt @@ -0,0 +1,123 @@ +package com.yinuo.safetywatcher.watcher.wifi.ui + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.text.TextUtils +import android.view.Gravity +import android.view.KeyEvent +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.Window +import android.view.WindowManager +import androidx.fragment.app.DialogFragment +import com.yinuo.safetywatcher.databinding.DialogInputWifiPasswordBinding +import com.yinuo.safetywatcher.watcher.utils.hideIme +import com.yinuo.safetywatcher.watcher.utils.showIme +import com.yinuo.safetywatcher.watcher.wifi.WiFiModule +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiScanInfo +import com.yinuo.safetywatcher.watcher.wifi.interfaces.ConnectWiFiActionListener + +/** + * wifi密码输入框 + */ +class InputWiFiPasswordDialog : DialogFragment() { + private var mInfo: WiFiScanInfo? = null + private var mConnectType = 0 + + private var mBinding: DialogInputWifiPasswordBinding? = null + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + dialog?.requestWindowFeature(Window.FEATURE_NO_TITLE) + mBinding = DialogInputWifiPasswordBinding.inflate(inflater, container, false) + return mBinding!!.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val bundle = arguments + if (null != bundle) { + mInfo = bundle.getParcelable("info") + mConnectType = bundle.getInt("connectType", 0) + } + if (null == mInfo) { + dismissAllowingStateLoss() + return + } + if (mConnectType == 1) { + mBinding?.tvTitle?.text = "修改" + mInfo!!.scanResult.SSID + } else { + mBinding?.tvTitle?.text = mInfo!!.scanResult.SSID + } + setListener() + } + + private fun setListener() { + mBinding?.etPassword?.setOnKeyListener { _, keyCode, event -> + if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { + if (event.action == KeyEvent.ACTION_DOWN) { + mBinding?.tvCancel?.requestFocus() + } + return@setOnKeyListener true + } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) { + if (event.action == KeyEvent.ACTION_DOWN) { + mBinding?.etPassword?.showIme() + } + return@setOnKeyListener true + } + return@setOnKeyListener false + } + mBinding?.etPassword?.setOnFocusChangeListener { v, hasFocus -> + if (!hasFocus) { + mBinding?.etPassword?.hideIme() + } else { + mBinding?.etPassword?.showIme() + } + } + + + mBinding?.tvCancel?.setOnClickListener { + dismissAllowingStateLoss() + } + + mBinding?.tvConnect?.setOnClickListener { + val trimPass = mBinding?.etPassword?.text.toString().trim { it <= ' ' } + //连接 + if (TextUtils.isEmpty(trimPass)) { + return@setOnClickListener + } + WiFiModule.getInstance().connectWiFi( + mInfo!!.scanResult.SSID, + mInfo!!.cipherType, + trimPass, + mConnectActionListener + ) + dismissAllowingStateLoss() + } + } + + override fun onStart() { + super.onStart() + val dialog = dialog + dialog?.setCanceledOnTouchOutside(true) + val window = dialog?.window + if (null != window) { + window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + val lp = window.attributes + lp.gravity = Gravity.CENTER + lp.width = 480 + lp.height = WindowManager.LayoutParams.WRAP_CONTENT + window.attributes = lp + } + } + + private var mConnectActionListener: ConnectWiFiActionListener? = null + fun setConnectListener(actionListener: ConnectWiFiActionListener?) { + mConnectActionListener = actionListener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/WiFIAdapter.kt b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/WiFIAdapter.kt new file mode 100644 index 0000000..def43d6 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/ui/WiFIAdapter.kt @@ -0,0 +1,84 @@ +package com.yinuo.safetywatcher.watcher.wifi.ui + +import android.graphics.Color +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.yinuo.safetywatcher.R +import com.yinuo.safetywatcher.databinding.ItemNetworkConfigBinding +import com.yinuo.safetywatcher.watcher.base.BaseRvAdapter +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiScanInfo +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiCipherType +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiConnectType + +class WiFIAdapter( + private val onItemClick: ((WiFiScanInfo) -> Unit)? = null, + private val onItemLongClick: ((WiFiScanInfo) -> Unit)? = null +) : + BaseRvAdapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WiFiViewHolder { + return WiFiViewHolder( + ItemNetworkConfigBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ), onItemClick, onItemLongClick + ); + } + + class WiFiViewHolder( + private val binding: ItemNetworkConfigBinding, + private val onItemClick: ((WiFiScanInfo) -> Unit)?, + private val onItemLongClick: ((WiFiScanInfo) -> Unit)? + ) : + BaseViewHolder(binding) { + + override fun bindView(info: WiFiScanInfo) { + val context = binding.root.context + binding.root.setOnClickListener { + onItemClick?.invoke(info) + } + binding.root.setOnLongClickListener { + onItemLongClick?.invoke(info) + return@setOnLongClickListener true + } + + if (null != info.configuration) { + if (info.connectType == WiFiConnectType.CONNECTED.type) { + binding.tvNetName.text = info.scanResult.SSID + } else { + binding.tvNetName.text = info.scanResult.SSID + "(已保存)" + } + } else { + binding.tvNetName.text = info.scanResult.SSID + } + + val noPass = WiFiCipherType.WIFI_CIPHER_NO_PASS == info.cipherType + if (noPass) { + binding.ivStatusLock.visibility = View.GONE + } else { + binding.ivStatusLock.visibility = View.VISIBLE + } + binding.ivStatusLock.setColorFilter(Color.WHITE) + + if (info.connectType == WiFiConnectType.CONNECTED.type) { + binding.ivStatusConnect.visibility = View.VISIBLE + binding.progressBar.visibility = View.GONE + } else if (info.connectType == WiFiConnectType.CONNECTING.type) { + //连接中 + binding.ivStatusConnect.visibility = View.GONE + binding.progressBar.visibility = View.VISIBLE + } else { + binding.ivStatusConnect.visibility = View.GONE + binding.progressBar.visibility = View.GONE + } + + when (info.level) { + 1 -> binding.ivStatusWifi.setImageResource(R.drawable.wifi_1) + 2 -> binding.ivStatusWifi.setImageResource(R.drawable.wifi_2) + else -> binding.ivStatusWifi.setImageResource(R.drawable.wifi_3) + } + } + } +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiLogUtils.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiLogUtils.java new file mode 100644 index 0000000..bc825a5 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiLogUtils.java @@ -0,0 +1,32 @@ +package com.yinuo.safetywatcher.watcher.wifi.utils; + +import android.util.Log; + +public final class WiFiLogUtils { + + private static final String TAG = "WiFiTool-log"; + + private static int log_level = 0; + + /** + * 设置日志级别 + * + * @param level 级别 + */ + public static void setLogLevel(int level) { + log_level = level; + } + + public static void d(String msg) { + if (log_level < 2) { + Log.d(TAG, msg); + } + } + + public static void e(Throwable throwable) { + if (log_level < 7) { + Log.e(TAG, "", throwable); + } + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiModuleService.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiModuleService.java new file mode 100644 index 0000000..9b3d556 --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiModuleService.java @@ -0,0 +1,574 @@ +package com.yinuo.safetywatcher.watcher.wifi.utils; + +import android.content.Context; +import android.content.IntentFilter; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.Looper; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiCreateConfigStatusInfo; +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiRemoveStatusInfo; +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiScanInfo; +import com.yinuo.safetywatcher.watcher.wifi.info.action.IWiFiAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiConnectAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiDirectConnectAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiDisableAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiEnableAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiNormalConnectAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiRemoveAction; +import com.yinuo.safetywatcher.watcher.wifi.info.action.WiFiScanAction; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.WiFiListener; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.WiFiSupportListener; +import com.yinuo.safetywatcher.watcher.wifi.interfaces.impl.WiFiStatusImpl; +import com.yinuo.safetywatcher.watcher.wifi.receiver.WiFiStatusReceiver; +import com.yinuo.safetywatcher.watcher.wifi.type.Types; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiConnectFailType; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiGetListType; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 处理WiFiAction + */ +public class WiFiModuleService { + + private WeakReference mContext; + private WifiManager mWifiManager; + private final List actionList = Collections.synchronizedList(new ArrayList<>()); + private final HashMap mListeners = new HashMap<>();//存放WiFi状态监听回调 + private boolean stopFlag = false; + private Handler mHandler; + private WiFiStatusReceiver mStatusReceiver; + private WiFiStatusImpl mWiFiStatusImpl; + + public WiFiModuleService(Context context) { + this.mContext = new WeakReference<>(context); + this.mWifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); + + this.mHandler = new Handler(Looper.getMainLooper()); + this.mWiFiStatusImpl = new WiFiStatusImpl(getWiFiSupportListener()); + + registerReceiver(); + + new WorkThread(mHandler).start(); + } + + /** + * 注册监听广播 + */ + private void registerReceiver() { + try { + this.mStatusReceiver = new WiFiStatusReceiver(mWiFiStatusImpl); + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);//监听wifi列表变化(开启一个热点或者关闭一个热点) + intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);//监听wifi是开关变化的状态 + intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);//监听wifi连接状态广播,是否连接了一个有效路由 + intentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);//监听wifi连接失败 + this.mContext.get().registerReceiver(this.mStatusReceiver, intentFilter); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + } + + /** + * 取消广播注册 + */ + private void unregisterReceiver() { + try { + if (null != this.mContext.get()) { + this.mContext.get().unregisterReceiver(this.mStatusReceiver); + } + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + } + + /** + * 添加操作 + */ + public void addAction(IWiFiAction action) { + synchronized (actionList) { + boolean absent = !actionList.contains(action); + if (absent) { + actionList.add(action); + WiFiLogUtils.d("已加入待执行队列中," + action.toString()); + } + } + } + + /** + * 添加WiFi状态监听 + * + * @param key 唯一标识 + * @param listener 监听回调 + */ + public void addWiFiListener(String key, WiFiListener listener) { + try { + if (mListeners.containsKey(key)) { + return; + } + + mListeners.put(key, listener); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + } + + /** + * 移除WiFi状态监听 + * + * @param key 唯一标识 + */ + public void removeWiFiListener(String key) { + try { + if (!mListeners.containsKey(key)) { + return; + } + + mListeners.remove(key); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + } + + private WiFiSupportListener getWiFiSupportListener() { + return new WiFiSupportListener() { + + @Nullable + @Override + public IWiFiAction getCurrentAction() { + synchronized (actionList) { + for (IWiFiAction action : actionList) { + if (Types.ActionStateType.PROCESS == action.getActionState()) { + return action; + } + } + + return null; + } + } + + @Override + public WifiInfo getConnectedWifiInfo() { + return WiFiUtils.getConnectedWifiInfo(mWifiManager); + } + + @Override + public void onWiFiClose() { + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onCloseWiFi(); + } + } + + @Override + public void onWiFiListChange() { + //TODO 在子线程查询 + List list = WiFiUtils.getScanList(mWifiManager); + + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onDataChange(WiFiGetListType.TYPE_SORT, list); + } + } + + @Override + public void doneScanAction(@NonNull WiFiScanAction action) { + //TODO 在子线程查询 + List list = WiFiUtils.getScanList(mWifiManager); + + if (null != action.listener) { + action.listener.onResult(Types.ScanResultType.SUCCESS, list); + } + + action.end(); + + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onDataChange(WiFiGetListType.TYPE_SCAN, list); + } + } + + @Override + public void doneConnectSuccess(@NonNull String SSID, int type) { + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiConnected(SSID, Types.ConnectSuccessType.SYSTEM == type); + } + } + + @Override + public void doneConnectFail(@NonNull WiFiConnectAction action) { + if (action instanceof WiFiDirectConnectAction) { + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiConnectFail(action.SSID, WiFiConnectFailType.DIRECT_PASSWORD_ERROR); + } + + return; + } + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiConnectFail(action.SSID, WiFiConnectFailType.PASSWORD_ERROR); + } + } + }; + } + + private class WorkThread extends Thread { + + Handler mHandler; + + WorkThread(Handler handler) { + this.mHandler = handler; + } + + @Override + public void run() { + super.run(); + + while (!stopFlag) { + synchronized (actionList) { + if (actionList.isEmpty()) { + continue; + } + + //始终获取第一个操作 + IWiFiAction action = actionList.get(0); + + if (Types.ActionStateType.WAITING == action.getActionState()) { + dispatchAction(action, mHandler); + continue; + } + + if (Types.ActionStateType.END == action.getActionState()) { + actionList.remove(action); + WiFiLogUtils.d("执行完毕,移除," + action.toString()); + } + } + } + } + } + + /** + * 分发WiFi操作事件 + */ + private void dispatchAction(IWiFiAction action, Handler handler) { + // 检测WiFi是否开启 + boolean isWiFiEnable = WiFiUtils.isWiFiEnable(mWifiManager); + + if (action instanceof WiFiDisableAction) { + action.setState(Types.ActionStateType.PROCESS); + WiFiLogUtils.d("开始执行," + action.toString()); + + if (!isWiFiEnable) { + //不可用 + action.end(); + return; + } + + //禁用WiFi + WiFiUtils.setWifiEnabled(mWifiManager, false); + return; + } + + if (action instanceof WiFiEnableAction) { + action.setState(Types.ActionStateType.PROCESS); + WiFiLogUtils.d("开始执行," + action.toString()); + + if (isWiFiEnable) { + //可用 + action.end(); + return; + } + + //启用WiFi + WiFiUtils.setWifiEnabled(mWifiManager, true); + return; + } + + if (!isWiFiEnable) { + //插入打开WiFi事件,阻塞后续WiFi操作 + insertOpenWiFiAction(); + return; + } + + action.setState(Types.ActionStateType.PROCESS); + WiFiLogUtils.d("开始执行," + action.toString()); + + if (action instanceof WiFiScanAction) { + handleWiFiScanAction((WiFiScanAction) action, handler); + + } else if (action instanceof WiFiNormalConnectAction) { + handleWiFiNormalConnectAction((WiFiNormalConnectAction) action, handler); + + } else if (action instanceof WiFiDirectConnectAction) { + handleWiFiDirectConnectAction((WiFiDirectConnectAction) action, handler); + + } else if (action instanceof WiFiRemoveAction) { + handleWiFiRemoveAction((WiFiRemoveAction) action, handler); + + } else { + WiFiLogUtils.d("不支持此操作," + action.toString()); + action.end(); + } + } + + /** + * 插入打开WiFi事件 + */ + private void insertOpenWiFiAction() { + synchronized (actionList) { + WiFiEnableAction openAction = new WiFiEnableAction(); + + if (actionList.isEmpty()) { + actionList.add(0, openAction); + + return; + } + + IWiFiAction action = actionList.get(0); + if (action instanceof WiFiEnableAction) { + return; + } + + actionList.add(0, openAction); + } + } + + private void handleWiFiScanAction(final WiFiScanAction action, Handler handler) { + handler.post(() -> { + if (null != action.listener) { + action.listener.onStart(); + } + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onStartScan(); + } + }); + + boolean success = WiFiUtils.startScan(mWifiManager); + if (!success) { + final List list = WiFiUtils.getScanList(mWifiManager); + + handler.post(() -> { + if (null != action.listener) { + action.listener.onResult(Types.ScanResultType.FREQUENTLY_SCAN_ERROR, list); + } + + action.end(); + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onDataChange(WiFiGetListType.TYPE_SCAN, list); + } + }); + } + } + + private void handleWiFiNormalConnectAction(final WiFiNormalConnectAction action, Handler handler) { + handler.post(() -> { + if (null != action.listener) { + action.listener.onStart(); + } + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiStartConnect(action.SSID); + } + }); + + startDelayCheck(action); + + final WiFiCreateConfigStatusInfo statusInfo = WiFiUtils.connectWiFi(mWifiManager, action.SSID, + action.cipherType, action.password, mContext.get()); + + if (!statusInfo.isSuccess()) { + handler.post(() -> { + WiFiLogUtils.d("配置创建失败," + action.toString()); + + if (null != action.listener) { + action.listener.onResult(Types.ConnectResultType.SYSTEM_LIMIT_ERROR); + } + + action.end(); + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiConnectFail(action.SSID, WiFiConnectFailType.SYSTEM_LIMIT_ERROR); + } + }); + + return; + } + + //配置创建成功 + handler.post(() -> { + WiFiLogUtils.d("配置创建成功," + action.toString()); + + if (null != action.listener) { + action.listener.onCreateConfig(statusInfo.configuration); + } + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiCreateConfig(action.SSID, statusInfo.configuration); + } + + //连接WiFi + boolean success = WiFiUtils.enableNetwork(mWifiManager, statusInfo.configuration.networkId); + + if (!success) { + //连接失败 + WiFiLogUtils.d("连接WiFi失败," + action.toString()); + + if (null != action.listener) { + action.listener.onResult(Types.ConnectResultType.UNKNOWN); + } + + action.end(); + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiConnectFail(action.SSID, WiFiConnectFailType.UNKNOWN); + } + } + }); + } + + private void handleWiFiDirectConnectAction(final WiFiDirectConnectAction action, Handler handler) { + handler.post(new Runnable() { + @Override + public void run() { + if (null != action.listener) { + action.listener.onStart(); + } + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiStartConnect(action.SSID); + } + } + }); + + startDelayCheck(action); + + WiFiUtils.closeAllConnect(mWifiManager); + boolean success = WiFiUtils.enableNetwork(mWifiManager, action.configuration.networkId); + + if (!success) { + //连接失败 + handler.post(new Runnable() { + @Override + public void run() { + WiFiLogUtils.d("直连WiFi失败," + action.toString()); + + if (null != action.listener) { + action.listener.onResult(Types.ConnectResultType.UNKNOWN); + } + + action.end(); + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiConnectFail(action.SSID, WiFiConnectFailType.UNKNOWN); + } + } + }); + } + } + + private void handleWiFiRemoveAction(final WiFiRemoveAction action, Handler handler) { + handler.post(() -> { + if (null != action.listener) { + action.listener.onStart(); + } + }); + + final WiFiRemoveStatusInfo statusInfo = WiFiUtils.removeWiFi(mWifiManager, action.SSID, mContext.get()); + + handler.post(() -> { + WiFiLogUtils.d("删除WiFi " + statusInfo.isSuccess + " | " + action.toString()); + + if (null != action.listener) { + if (statusInfo.isSuccess) { + action.listener.onResult(Types.RemoveResultType.SUCCESS); + + } else { + action.listener.onResult(Types.RemoveResultType.SYSTEM_LIMIT_ERROR); + } + } + action.end(); + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiRemoveResult(statusInfo); + } + }); + } + + /** + * 开始超时检测 + */ + private void startDelayCheck(final WiFiConnectAction action) { + if (action.timeout <= 1000 * 3) { + WiFiLogUtils.d("超时时间设置小于3秒,不予超时检测," + action.toString()); + return; + } + + action.startDelayCheck(mHandler, () -> { + if (Types.ActionStateType.END == action.getActionState()) { + WiFiLogUtils.d("已经结束掉了,忽略连接WiFi超时," + action.toString()); + return; + } + + WiFiLogUtils.d("连接WiFi超时," + action.toString()); + WiFiUtils.closeAllConnect(mWifiManager); + + if (null != action.listener) { + action.listener.onResult(Types.ConnectResultType.TIMEOUT_ERROR); + } + action.end(); + + // 回调全局监听 + for (Map.Entry entry : mListeners.entrySet()) { + entry.getValue().onWiFiConnectFail(action.SSID, WiFiConnectFailType.TIMEOUT_ERROR); + } + }); + } + + /** + * 销毁资源 + */ + public void destroy() { + try { + stopFlag = true; + unregisterReceiver(); + mHandler.removeCallbacksAndMessages(null); + + synchronized (actionList) { + actionList.clear(); + } + + mWifiManager = null; + + WiFiLogUtils.d("销毁资源结束"); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + } + +} diff --git a/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiUtils.java b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiUtils.java new file mode 100644 index 0000000..61d0d8c --- /dev/null +++ b/app/src/main/java/com/yinuo/safetywatcher/watcher/wifi/utils/WiFiUtils.java @@ -0,0 +1,456 @@ +package com.yinuo.safetywatcher.watcher.wifi.utils; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.net.wifi.ScanResult; +import android.net.wifi.SupplicantState; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; +import android.os.Build; +import android.text.TextUtils; + +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiCreateConfigStatusInfo; +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiRemoveStatusInfo; +import com.yinuo.safetywatcher.watcher.wifi.info.WiFiScanInfo; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiCipherType; +import com.yinuo.safetywatcher.watcher.wifi.type.WiFiConnectType; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * WiFi工具类 + */ +public final class WiFiUtils { + + /** + * WiFi是否可用 + * + * @return 是否执行成功 + */ + public static boolean isWiFiEnable(WifiManager manager) { + try { + if (null == manager) { + return false; + } + + return manager.isWifiEnabled(); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + + return false; + } + + /** + * 开始扫描 + * + * @return 是否执行成功 + */ + public static boolean startScan(WifiManager manager) { + try { + if (null == manager) { + return false; + } + + return manager.startScan(); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + + return false; + } + + /** + * 设置WiFi状态 + * + * @return 是否执行成功 + */ + public static boolean setWifiEnabled(WifiManager manager, boolean isOpen) { + try { + if (null == manager) { + return false; + } + + return manager.setWifiEnabled(isOpen); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + + return false; + } + + /** + * 获取扫描到的WiFi列表 + */ + public static List getScanList(WifiManager manager) { + if (null == manager) { + return new ArrayList<>(); + } + + String curSSID = isActiveWifi(manager) ? manager.getConnectionInfo().getSSID() : ""; + + List results = noSameName(manager.getScanResults()); + List list = new ArrayList<>(); + boolean isCur; + WiFiScanInfo curInfo = null;//当前连接上的wifi + List normalList = new ArrayList<>();//不存在配置的列表 + List existConfigList = new ArrayList<>();//存在配置的列表 + + for (ScanResult result : results) { + WiFiScanInfo connectInfo = new WiFiScanInfo(); + connectInfo.scanResult = result; + connectInfo.configuration = getExistConfig(manager, result.SSID); + + isCur = (!TextUtils.isEmpty(curSSID) && curSSID.equals("\"" + result.SSID + "\"")); + connectInfo.connectType = (isCur ? WiFiConnectType.CONNECTED.type : WiFiConnectType.DISCONNECTED.type); + connectInfo.level = WifiManager.calculateSignalLevel(result.level, 4) + 1; + + if (isCur) { + //当前已连接 + curInfo = connectInfo; + + } else { + if (null != connectInfo.configuration) { + //存在配置 + existConfigList.add(connectInfo); + + } else { + normalList.add(connectInfo); + } + } + } + + //优先把保存了配置的放在上面 + if (null != curInfo) { + list.add(curInfo); + } + + Collections.sort(existConfigList); + list.addAll(existConfigList); + + Collections.sort(normalList); + list.addAll(normalList); + + return list; + } + + /** + * 获取当前连接的WiFi + */ + public static WifiInfo getConnectedWifiInfo(WifiManager manager) { + boolean isActive = isActiveWifi(manager); + + if (isActive) { + return manager.getConnectionInfo(); + } + + return null; + } + + /** + * 是否有当前可用的WiFi连接 + */ + public static boolean isActiveWifi(WifiManager manager) { + if (null == manager) { + return false; + } + + WifiInfo info = manager.getConnectionInfo(); + if (null == info) { + return false; + } + + String ssid = info.getSSID(); + + return SupplicantState.COMPLETED == info.getSupplicantState() + && !TextUtils.isEmpty(ssid) + && !ssid.equalsIgnoreCase("0x") + && !"".equals(ssid); + } + + /** + * 关闭所有连接 + */ + public static void closeAllConnect(WifiManager manager) { + if (null == manager) { + return; + } + + // FIXME: 2019/4/16 防止自动连接,小米等手机会弹出权限框 + for (WifiConfiguration c : manager.getConfiguredNetworks()) { + manager.disableNetwork(c.networkId); + } + + // 断开后会自动连接WiFi +// manager.disconnect(); + } + + /** + * 连接WiFi + */ + public static WiFiCreateConfigStatusInfo connectWiFi(WifiManager manager, String SSID, WiFiCipherType type, String pwd, Context context) { + WiFiCreateConfigStatusInfo info = new WiFiCreateConfigStatusInfo(); + info.SSID = SSID; + info.isSuccess = false; + + //先关闭当前所有已连接的网络 + closeAllConnect(manager); + + WifiConfiguration config = getExistConfig(manager, SSID); + + if (null == config) { + //不存在旧的配置,添加WiFi + return addWifi(manager, SSID, type, pwd); + } + + //存在旧的配置,先尝试移除WiFi + if (removeWiFi(manager, SSID, context).isSuccess) { + //移除成功,重新添加WiFi + return addWifi(manager, SSID, type, pwd); + } + + return info; + } + + /** + * 根据networkId连接WiFi + */ + public static boolean enableNetwork(WifiManager manager, int networkId) { + return null != manager && manager.enableNetwork(networkId, true); + } + + /** + * 移除WiFi + *

Android6.0 之后应用只能删除自己创建的WIFI网络

+ */ + public static WiFiRemoveStatusInfo removeWiFi(WifiManager manager, String SSID, Context context) { + WiFiRemoveStatusInfo info = new WiFiRemoveStatusInfo(); + info.SSID = SSID; + + if (null == manager) { + return info; + } + + WifiConfiguration config = getExistConfig(manager, SSID); + + if (null == config) { + //如果不存在配置,默认是删除成功 + info.isSuccess = true; + return info; + } + + if (config.networkId == -1) { + info.isSuccess = false; + WiFiLogUtils.d("networkId 非法!"); + return info; + } + + boolean isSystemApp = isSystemApplication(context); + if (isSystemApp) { + WiFiLogUtils.d("是系统App,可以直接删除!"); + info.isSuccess = manager.disableNetwork(config.networkId) + && manager.removeNetwork(config.networkId) + && manager.saveConfiguration(); + + return info; + } + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + //6.0之前 + info.isSuccess = manager.disableNetwork(config.networkId) + && manager.removeNetwork(config.networkId) + && manager.saveConfiguration(); + + return info; + } + + try { + //获取当前WiFi的创建者 + Field field = config.getClass().getDeclaredField("creatorName"); + field.setAccessible(true); + Object creatorName = field.get(config); + + WiFiLogUtils.d("field:" + field + "||creatorName:" + creatorName); + + if (context.getPackageName().equals(creatorName)) { + WiFiLogUtils.d("是当前app创建的WiFi,可以直接删除!"); + info.isSuccess = manager.disableNetwork(config.networkId) + && manager.removeNetwork(config.networkId) + && manager.saveConfiguration(); + } + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + + return info; + } + + /** + * 添加WiFi到系统 + */ + private static WiFiCreateConfigStatusInfo addWifi(WifiManager manager, String SSID, WiFiCipherType type, String pwd) { + WiFiCreateConfigStatusInfo configInfo = new WiFiCreateConfigStatusInfo(); + configInfo.SSID = SSID; + + try { + WifiConfiguration configuration = createConfiguration(SSID, type, pwd); + configuration.networkId = manager.addNetwork(configuration); + + configInfo.configuration = configuration; + configInfo.isSuccess = (configuration.networkId != -1); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + + return configInfo; + } + + /** + * 创建配置 + */ + private static WifiConfiguration createConfiguration(String SSID, WiFiCipherType type, String password) { + WifiConfiguration config = new WifiConfiguration(); + + config.allowedAuthAlgorithms.clear(); + config.allowedGroupCiphers.clear(); + config.allowedKeyManagement.clear(); + config.allowedPairwiseCiphers.clear(); + config.allowedProtocols.clear(); + + config.SSID = "\"" + SSID + "\""; + + switch (type) { + case WIFI_CIPHER_NO_PASS: + // config.wepKeys[0] = ""; + config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + // config.wepTxKeyIndex = 0; + break; + + case WIFI_CIPHER_WEP: + if (!TextUtils.isEmpty(password)) { + if (isHexWepKey(password)) { + config.wepKeys[0] = password; + + } else { + config.wepKeys[0] = "\"" + password + "\""; + } + } + + config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); + config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); + config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + config.wepTxKeyIndex = 0; + break; + + case WIFI_CIPHER_WPA: + config.preSharedKey = "\"" + password + "\""; + config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); + config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); + config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); + config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); + config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); + config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); + config.allowedProtocols.set(WifiConfiguration.Protocol.RSN); + config.allowedProtocols.set(WifiConfiguration.Protocol.WPA); + config.status = WifiConfiguration.Status.ENABLED; + + default: + break; + } + + return config; + } + + /** + * 获取是否已经存在的配置 + */ + private static WifiConfiguration getExistConfig(WifiManager manager, String SSID) { + if (null == manager) { + return null; + } + + try { + List existingConfigs = manager.getConfiguredNetworks(); + + for (WifiConfiguration existingConfig : existingConfigs) { + if (existingConfig.SSID.equals("\"" + SSID + "\"")) { + return existingConfig; + } + } + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + + return null; + } + + /** + * 去除同名WIFI + */ + private static List noSameName(List oldSr) { + List newSr = new ArrayList<>(); + for (ScanResult result : oldSr) { + if (!TextUtils.isEmpty(result.SSID) && !containName(newSr, result.SSID)) { + newSr.add(result); + } + } + return newSr; + } + + /** + * 判断一个扫描结果中,是否包含了某个名称的WIFI + */ + private static boolean containName(List sr, String name) { + for (ScanResult result : sr) { + if (!TextUtils.isEmpty(result.SSID) && result.SSID.equals(name)) { + return true; + } + } + + return false; + } + + private static boolean isHexWepKey(String wepKey) { + final int len = wepKey.length(); + + // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?) + return (len == 10 || len == 26 || len == 58) && isHex(wepKey); + } + + private static boolean isHex(String key) { + for (int i = key.length() - 1; i >= 0; i--) { + final char c = key.charAt(i); + if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' + && c <= 'f')) { + return false; + } + } + return true; + } + + private static boolean isSystemApplication(Context context) { + try { + PackageManager packageManager = context.getPackageManager(); + + ApplicationInfo app = packageManager.getApplicationInfo(context.getPackageName(), 0); + return (app != null && (app.flags & ApplicationInfo.FLAG_SYSTEM) > 0); + + } catch (Exception e) { + WiFiLogUtils.e(e); + } + + return false; + } + +} diff --git a/app/src/main/res/drawable-xhdpi/ic_password.png b/app/src/main/res/drawable-xhdpi/ic_password.png new file mode 100644 index 0000000000000000000000000000000000000000..2635644a176e44819f61dead82a730deb6268130 GIT binary patch literal 471 zcmeAS@N?(olHy`uVBq!ia0vp^7C>yq!VDx67P-d)Dct~{5LfpCA6W%ONqJQXAd*!9 zlA;OO)N+$E zg>8YyslCJH@UiJImkCJ8+}!{k^@86ML$^pJOm#X4jLwXis#Q&Jf|BJ-^Ql|T4u>5GU{E)}}O{Duuqx-Md z|8KSYTC4ngz5R~H{DHsybGZCfsQZ@1|BA!>SgHJLv;2s{{9dj4h{F7a!TeUK{8+2| zOr!f!r~5)P?Uw)m048)&PE!Ci$JXx}hXdpYA}r~>vOx6t524R^QErys6-k$>Uujuo zO*(?8AhmiD0005RNkllIn3-|Z>X?+4? zY!n3l_amhcG?=DDoAQEYg;JbmrPiv$*3OfRF=ywFnIs+UESGcFnUr9e=Ceb@jz_e7 z_O7VQ743W}FE_Mmekvq+4wezp?{ENnBqU(6L_2?>fmklVmV~6&C$t5D)+ex6f)x8b zSWTJl87<{}Hyf}yrKr>!u$1@)rx+|{slg@&%PBMt!Ac6vLa?OTyFg2#8CueW!v$DU zm>ve~okCk<7Fkx4vS|gjqR{&qEhSEJg|_iNq`foth`@T!xZekx2(9M<5d9u1R%ktk z9roXLi`Hvv<*@%25!%or$O8L*`uodvht^}t+}#;^`(y3bl;W=M_eqED%xm1m zr@j1H`(ztU+T>dwE!x$nEqyAGXddRx*4n#si+f!?!Y)+txjHn8_HO{*Gx7Wf^Jyrm T^!hc#00000NkvXXu0mjfQsHC0 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_select_s.png b/app/src/main/res/drawable-xhdpi/ic_select_s.png new file mode 100644 index 0000000000000000000000000000000000000000..e90dca29a0ec37439df0fef23cb775ece6d3e747 GIT binary patch literal 502 zcmVmHjc5`7)OJF`54|misc6`!kmNGM4)P|Nm8}`-Q;#@Av=t{Qq^h z{9&&9qR;)??f%Z@{zISp_h$kE0000CbW%=J0Lhvqeil&i2;;3e)hL2#0003|Nkln}BRRFx$ikLR(5h3zZ2r!i(8y-)h8 zOh244+cnprmb-v3lxuo&X1&&x)pAqNuoT4sB^t$nCKAPgBsdNr0+-$FYng*E)%E?w zc`b4>EY4<5GRxWG&=hFNJZGOHXn=8cWS+AP5VqXn$UJ9TE^6`%dB@o%kH^X*r`!sN z2l+?da_>P-t&XL{eO5 + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_input.xml b/app/src/main/res/drawable/bg_input.xml new file mode 100644 index 0000000..4014c3d --- /dev/null +++ b/app/src/main/res/drawable/bg_input.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/loading_img.xml b/app/src/main/res/drawable/loading_img.xml new file mode 100644 index 0000000..9ac705b --- /dev/null +++ b/app/src/main/res/drawable/loading_img.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_monitor.xml b/app/src/main/res/layout/activity_monitor.xml new file mode 100644 index 0000000..2cee94a --- /dev/null +++ b/app/src/main/res/layout/activity_monitor.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_input_wifi_password.xml b/app/src/main/res/layout/dialog_input_wifi_password.xml new file mode 100644 index 0000000..7a66eae --- /dev/null +++ b/app/src/main/res/layout/dialog_input_wifi_password.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_network_config.xml b/app/src/main/res/layout/item_network_config.xml new file mode 100644 index 0000000..9000319 --- /dev/null +++ b/app/src/main/res/layout/item_network_config.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_confirm_dialog.xml b/app/src/main/res/layout/layout_confirm_dialog.xml index 8417331..2d266a1 100644 --- a/app/src/main/res/layout/layout_confirm_dialog.xml +++ b/app/src/main/res/layout/layout_confirm_dialog.xml @@ -11,6 +11,7 @@ android:layout_height="0dp" android:layout_gravity="center" android:layout_marginTop="@dimen/_36dp" + android:paddingHorizontal="@dimen/_12dp" android:layout_weight="1" android:gravity="center" android:text="@string/sync_data_tip" diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 78eee84..63095ab 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -23,4 +23,7 @@ #01E41C #999999 #E40101 + + #191F25 + #BFBFBF