├── app
├── .gitignore
├── app-release.apk
├── src
│ └── main
│ │ ├── res
│ │ ├── layout
│ │ │ ├── buttons_view_divider.xml
│ │ │ ├── title_view.xml
│ │ │ ├── floating.xml
│ │ │ └── base_content.xml
│ │ ├── drawable
│ │ │ ├── icon.png
│ │ │ └── ic_dialog_menu_generic.png
│ │ ├── values-v14
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ ├── values-v11
│ │ │ ├── styles.xml
│ │ │ └── colors.xml
│ │ ├── values
│ │ │ ├── colors.xml
│ │ │ ├── styles.xml
│ │ │ └── strings.xml
│ │ ├── layout-v11
│ │ │ ├── buttons_view_divider.xml
│ │ │ └── title_view.xml
│ │ ├── values-ru
│ │ │ └── strings.xml
│ │ ├── values-zh-rCN
│ │ │ └── strings.xml
│ │ ├── values-zh-rTW
│ │ │ └── strings.xml
│ │ └── values-it
│ │ │ └── strings.xml
│ │ ├── java
│ │ └── com
│ │ │ └── farproc
│ │ │ └── wifi
│ │ │ └── connecter
│ │ │ ├── Version.java
│ │ │ ├── ConfigurationSecurities.java
│ │ │ ├── ChangingAwareEditText.java
│ │ │ ├── ReenableAllApsWhenNetworkStateChanged.java
│ │ │ ├── MainActivity.java
│ │ │ ├── NewNetworkContent.java
│ │ │ ├── ChangePasswordContent.java
│ │ │ ├── BaseContent.java
│ │ │ ├── Floating.java
│ │ │ ├── ConfiguredNetworkContent.java
│ │ │ ├── CurrentNetworkContent.java
│ │ │ ├── TestWifiScan.java
│ │ │ ├── ConfigurationSecuritiesV8.java
│ │ │ ├── ConfigurationSecuritiesOld.java
│ │ │ └── Wifi.java
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── .gitignore
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkch/android-wifi-connecter/HEAD/app/app-release.apk
--------------------------------------------------------------------------------
/app/src/main/res/layout/buttons_view_divider.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkch/android-wifi-connecter/HEAD/app/src/main/res/drawable/icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dialog_menu_generic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mkch/android-wifi-connecter/HEAD/app/src/main/res/drawable/ic_dialog_menu_generic.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v14/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @android:color/holo_blue_dark
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
11 | .idea/
12 | gradle/wrapper/
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @android:color/darker_gray
6 | @android:color/background_light
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v11/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | #6396f7
6 | @android:color/transparent
7 | @android:color/transparent
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v11/buttons_view_divider.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/title_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/yuanxiaohui/Documents/Android/android-sdk-mac_86/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.2"
6 | defaultConfig {
7 | applicationId "com.farproc.wifi.connecter"
8 | minSdkVersion 3
9 | targetSdkVersion 14
10 | versionCode 16
11 | versionName "2.0.3"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | lintOptions {
15 | abortOnError false
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | compile fileTree(dir: 'libs', include: ['*.jar'])
27 | }
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/Version.java:
--------------------------------------------------------------------------------
1 | package com.farproc.wifi.connecter;
2 |
3 | import java.lang.reflect.Field;
4 |
5 | import android.os.Build.VERSION;;
6 |
7 | /**
8 | * Get Android version in different Android versions. :)
9 | * @author yuanxiaohui
10 | *
11 | */
12 | public class Version {
13 |
14 | public final static int SDK = get();
15 |
16 | private static int get() {
17 | final Class versionClass = VERSION.class;
18 | try {
19 | // First try to read the recommended field android.os.Build.VERSION.SDK_INT.
20 | final Field sdkIntField = versionClass.getField("SDK_INT");
21 | return sdkIntField.getInt(null);
22 | }catch (NoSuchFieldException e) {
23 | // If SDK_INT does not exist, read the deprecated field SDK.
24 | return Integer.valueOf(VERSION.SDK);
25 | } catch (Exception e) {
26 | throw new RuntimeException(e);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v11/title_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
17 |
18 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/ConfigurationSecurities.java:
--------------------------------------------------------------------------------
1 | package com.farproc.wifi.connecter;
2 |
3 | import android.net.wifi.ScanResult;
4 | import android.net.wifi.WifiConfiguration;
5 |
6 | public abstract class ConfigurationSecurities {
7 | /**
8 | * @return The security of a given {@link WifiConfiguration}.
9 | */
10 | public abstract String getWifiConfigurationSecurity(WifiConfiguration wifiConfig);
11 | /**
12 | * @return The security of a given {@link ScanResult}.
13 | */
14 | public abstract String getScanResultSecurity(ScanResult scanResult);
15 | /**
16 | * Fill in the security fields of WifiConfiguration config.
17 | * @param config The object to fill.
18 | * @param security If is OPEN, password is ignored.
19 | * @param password Password of the network if security is not OPEN.
20 | */
21 | public abstract void setupSecurity(WifiConfiguration config, String security, final String password);
22 | public abstract String getDisplaySecirityString(final ScanResult scanResult);
23 | public abstract boolean isOpenNetwork(final String security);
24 |
25 | public static ConfigurationSecurities newInstance() {
26 | if(Version.SDK < 8) {
27 | return new ConfigurationSecuritiesOld();
28 | } else {
29 | return new ConfigurationSecuritiesV8();
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/ChangingAwareEditText.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import android.content.Context;
29 | import android.util.AttributeSet;
30 | import android.widget.EditText;
31 |
32 | public class ChangingAwareEditText extends EditText {
33 |
34 | public ChangingAwareEditText(Context context, AttributeSet attrs) {
35 | super(context, attrs);
36 | }
37 |
38 | private boolean mChanged = false;
39 |
40 | public boolean getChanged() {
41 | return mChanged;
42 | }
43 |
44 | protected void onTextChanged (CharSequence text, int start, int before, int after) {
45 | mChanged = true;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ru/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 | Ошибка!
10 | Больше…
11 | Подключить
12 | Подключение к %s
13 | IP-адрес
14 | Сила сигнала
15 | Забыть
16 | Статус
17 | Подключено
18 | Подключение…
19 | Скорость
20 | Отличная
21 | Хорошая
22 | Средняя
23 | Плохая
24 | Безопасность
25 | Открыто
26 | WEP
27 | WPA
28 | WPA2
29 | WPA-EAP
30 | IEEE8021X
31 | Пароль беспроводной сети
32 | Показывать пароль.
33 | Изменить пароль
34 | "Изменить пароль"
35 | (без изменений)
36 | Сохранить
37 | AdHoc еще не поддерживается платформой Android!
38 |
39 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
29 |
30 |
33 |
34 |
35 |
36 |
37 |
40 |
41 |
45 |
49 |
50 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/floating.xml:
--------------------------------------------------------------------------------
1 |
2 |
28 |
29 |
33 |
34 |
38 |
39 |
45 |
46 |
47 |
48 |
49 |
57 |
58 |
63 |
64 |
69 |
70 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
29 |
30 |
31 |
32 | 失败!
33 | 更多……
34 |
35 |
36 | 连接
37 |
38 | 连接到 %s
39 |
40 | IP 地址
41 |
42 | 信号强度
43 |
44 |
45 | 不保存
46 |
47 | 状态
48 |
49 | 已连接
50 | 正在连接……
51 |
52 | 速度
53 |
54 | 最强
55 |
56 | 正常
57 |
58 | 较弱
59 |
60 | 弱
61 |
62 | 安全性
63 |
64 | 开放
65 |
66 | 密码
67 | 显示密码。
68 |
69 | 修改密码
70 | 修改密码
71 |
72 | (未更改)
73 |
74 | 保存
75 |
76 | Android 平台目前不支持连接到 AdHoc!
77 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rTW/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
29 |
30 |
31 |
32 | 失敗!
33 | 更多……
34 |
35 |
36 | 連接
37 |
38 | 連接到 %s
39 |
40 | IP 地址
41 |
42 | 信號強度
43 |
44 |
45 | 清除
46 |
47 | 狀態
48 |
49 | 已連接
50 | 正在連接……
51 |
52 | 速度
53 |
54 | 最強
55 |
56 | 正常
57 |
58 | 較弱
59 |
60 | 弱
61 |
62 | 安全性
63 |
64 | 開放
65 |
66 | 密碼
67 | 顯示密碼。
68 |
69 | 修改密碼
70 | 修改密碼
71 |
72 | (未更改)
73 |
74 | 保存
75 |
76 | Android 平臺目前不支援連接到 AdHoc!
77 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
29 |
30 |
31 |
32 | Manqué!
33 | Plus…
34 |
35 |
36 | Connetti
37 |
38 | Connessione a %s
39 |
40 | Indirizzo IP
41 |
42 | Intensità segnale
43 |
44 |
45 | Elimina
46 |
47 | Stato
48 |
49 | Connesso
50 | Connessione…
51 |
52 | Velocità
53 |
54 | Eccellente
55 |
56 | Buona
57 |
58 | Discreta
59 |
60 | Scarsa
61 |
62 | Protezione
63 |
64 | Apri
65 |
66 | Password wireless
67 | "Mostra password.
68 |
69 | Cambia password
70 | Password
71 |
72 | (invariato)
73 |
74 | Salva
75 |
76 | AdHoc non è supportato da piattaforma Android ancora!
77 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/ReenableAllApsWhenNetworkStateChanged.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import java.util.List;
29 |
30 | import android.app.Service;
31 | import android.content.BroadcastReceiver;
32 | import android.content.Context;
33 | import android.content.Intent;
34 | import android.content.IntentFilter;
35 | import android.net.NetworkInfo;
36 | import android.net.wifi.WifiConfiguration;
37 | import android.net.wifi.WifiManager;
38 | import android.os.IBinder;
39 |
40 | public class ReenableAllApsWhenNetworkStateChanged {
41 | public static void schedule(final Context ctx) {
42 | ctx.startService(new Intent(ctx, BackgroundService.class));
43 | }
44 |
45 | private static void reenableAllAps(final Context ctx) {
46 | final WifiManager wifiMgr = (WifiManager)ctx.getSystemService(Context.WIFI_SERVICE);
47 | final List configurations = wifiMgr.getConfiguredNetworks();
48 | if(configurations != null) {
49 | for(final WifiConfiguration config:configurations) {
50 | wifiMgr.enableNetwork(config.networkId, false);
51 | }
52 | }
53 | }
54 |
55 | public static class BackgroundService extends Service {
56 |
57 | private boolean mReenabled;
58 |
59 | private BroadcastReceiver mReceiver = new BroadcastReceiver() {
60 |
61 | @Override
62 | public void onReceive(Context context, Intent intent) {
63 | final String action = intent.getAction();
64 | if(WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
65 | final NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
66 | final NetworkInfo.DetailedState detailed = networkInfo.getDetailedState();
67 | if(detailed != NetworkInfo.DetailedState.DISCONNECTED
68 | && detailed != NetworkInfo.DetailedState.DISCONNECTING
69 | && detailed != NetworkInfo.DetailedState.SCANNING) {
70 | if(!mReenabled) {
71 | mReenabled = true;
72 | reenableAllAps(context);
73 | stopSelf();
74 | }
75 | }
76 | }
77 | }
78 | };
79 |
80 | private IntentFilter mIntentFilter;
81 |
82 | @Override
83 | public IBinder onBind(Intent intent) {
84 | return null; // We need not bind to it at all.
85 | }
86 |
87 | @Override
88 | public void onCreate() {
89 | super.onCreate();
90 | mReenabled = false;
91 | mIntentFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION);
92 | registerReceiver(mReceiver, mIntentFilter);
93 | }
94 |
95 | @Override
96 | public void onDestroy() {
97 | super.onDestroy();
98 | unregisterReceiver(mReceiver);
99 | }
100 |
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import android.content.Intent;
29 | import android.net.wifi.ScanResult;
30 | import android.net.wifi.WifiConfiguration;
31 | import android.net.wifi.WifiInfo;
32 | import android.net.wifi.WifiManager;
33 | import android.os.Bundle;
34 | import android.widget.Toast;
35 |
36 | public class MainActivity extends Floating {
37 |
38 | public static final String EXTRA_HOTSPOT = "com.farproc.wifi.connecter.extra.HOTSPOT";
39 |
40 | private ScanResult mScanResult;
41 | private Floating.Content mContent;
42 | private WifiManager mWifiManager;
43 |
44 | @Override
45 | protected void onNewIntent (Intent intent) {
46 | setIntent(intent);
47 | // This activity has "singleInstance" launch mode.
48 | // Update content to reflect the newest intent.
49 | doNewIntent(intent);
50 | }
51 |
52 | @Override
53 | public void onCreate(Bundle savedInstanceState) {
54 | super.onCreate(savedInstanceState);
55 |
56 | mWifiManager = (WifiManager)getSystemService(WIFI_SERVICE);
57 |
58 | doNewIntent(getIntent());
59 | }
60 |
61 | private boolean isAdHoc(final ScanResult scanResule) {
62 | return scanResule.capabilities.indexOf("IBSS") != -1;
63 | }
64 |
65 | private void doNewIntent(final Intent intent) {
66 | mScanResult = intent.getParcelableExtra(EXTRA_HOTSPOT);
67 |
68 | if(mScanResult == null) {
69 | Toast.makeText(this, "No data in Intent!", Toast.LENGTH_LONG).show();
70 | finish();
71 | return;
72 | }
73 |
74 | if(isAdHoc(mScanResult)) {
75 | Toast.makeText(this, R.string.adhoc_not_supported_yet, Toast.LENGTH_LONG).show();
76 | finish();
77 | return;
78 | }
79 |
80 | final String security = Wifi.ConfigSec.getScanResultSecurity(mScanResult);
81 | final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, security);
82 |
83 | if(config == null) {
84 | mContent = new NewNetworkContent(this, mWifiManager, mScanResult);
85 | } else {
86 | final boolean isCurrentNetwork_ConfigurationStatus = config.status == WifiConfiguration.Status.CURRENT;
87 | final WifiInfo info = mWifiManager.getConnectionInfo();
88 | final boolean isCurrentNetwork_WifiInfo = info != null
89 | && android.text.TextUtils.equals(info.getSSID(), mScanResult.SSID)
90 | && android.text.TextUtils.equals(info.getBSSID(), mScanResult.BSSID);
91 | if(isCurrentNetwork_ConfigurationStatus || isCurrentNetwork_WifiInfo) {
92 | mContent = new CurrentNetworkContent(this, mWifiManager, mScanResult);
93 | } else {
94 | mContent = new ConfiguredNetworkContent(this, mWifiManager, mScanResult);
95 | }
96 | }
97 | setContent(mContent);
98 | }
99 |
100 | }
101 |
102 |
103 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/NewNetworkContent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import com.farproc.wifi.connecter.R;
29 |
30 | import android.net.wifi.ScanResult;
31 | import android.net.wifi.WifiManager;
32 | import android.view.ContextMenu;
33 | import android.view.MenuItem;
34 | import android.view.View;
35 | import android.view.ContextMenu.ContextMenuInfo;
36 | import android.view.View.OnClickListener;
37 | import android.widget.EditText;
38 | import android.widget.TextView;
39 | import android.widget.Toast;
40 |
41 | public class NewNetworkContent extends BaseContent {
42 |
43 | private boolean mIsOpenNetwork = false;
44 |
45 | public NewNetworkContent(final Floating floating, final WifiManager wifiManager, ScanResult scanResult) {
46 | super(floating, wifiManager, scanResult);
47 |
48 | mView.findViewById(R.id.Status).setVisibility(View.GONE);
49 | mView.findViewById(R.id.Speed).setVisibility(View.GONE);
50 | mView.findViewById(R.id.IPAddress).setVisibility(View.GONE);
51 | if(Wifi.ConfigSec.isOpenNetwork(mScanResultSecurity)) {
52 | mIsOpenNetwork = true;
53 | mView.findViewById(R.id.Password).setVisibility(View.GONE);
54 | } else {
55 | ((TextView)mView.findViewById(R.id.Password_TextView)).setText(R.string.please_type_passphrase);
56 | }
57 | }
58 |
59 | private OnClickListener mConnectOnClick = new OnClickListener() {
60 |
61 | @Override
62 | public void onClick(View v) {
63 | boolean connResult;
64 | if(mIsOpenNetwork) {
65 | connResult = Wifi.connectToNewNetwork(mFloating, mWifiManager, mScanResult, null, mNumOpenNetworksKept);
66 | } else {
67 | connResult = Wifi.connectToNewNetwork(mFloating, mWifiManager, mScanResult
68 | , ((EditText)mView.findViewById(R.id.Password_EditText)).getText().toString()
69 | , mNumOpenNetworksKept);
70 | }
71 |
72 | if(!connResult) {
73 | Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
74 | }
75 |
76 | mFloating.finish();
77 | }
78 | };
79 |
80 | private OnClickListener mOnClickListeners[] = {mConnectOnClick, mCancelOnClick};
81 |
82 | @Override
83 | public int getButtonCount() {
84 | return 2;
85 | }
86 |
87 | @Override
88 | public OnClickListener getButtonOnClickListener(int index) {
89 | return mOnClickListeners[index];
90 | }
91 |
92 |
93 | @Override
94 | public CharSequence getButtonText(int index) {
95 | switch(index) {
96 | case 0:
97 | return mFloating.getText(R.string.connect);
98 | case 1:
99 | return getCancelString();
100 | default:
101 | return null;
102 | }
103 | }
104 |
105 | @Override
106 | public CharSequence getTitle() {
107 | return mFloating.getString(R.string.wifi_connect_to, mScanResult.SSID);
108 | }
109 |
110 | @Override
111 | public boolean onContextItemSelected(MenuItem item) {
112 | return false;
113 | }
114 |
115 | @Override
116 | public void onCreateContextMenu(ContextMenu menu, View v,
117 | ContextMenuInfo menuInfo) {
118 |
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/ChangePasswordContent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import android.net.wifi.ScanResult;
29 | import android.net.wifi.WifiConfiguration;
30 | import android.net.wifi.WifiManager;
31 | import android.view.ContextMenu;
32 | import android.view.ContextMenu.ContextMenuInfo;
33 | import android.view.MenuItem;
34 | import android.view.View;
35 | import android.view.View.OnClickListener;
36 | import android.widget.EditText;
37 | import android.widget.TextView;
38 | import android.widget.Toast;
39 |
40 | public class ChangePasswordContent extends BaseContent {
41 |
42 | private ChangingAwareEditText mPasswordEditText;
43 |
44 | public ChangePasswordContent(Floating floating, WifiManager wifiManager,
45 | ScanResult scanResult) {
46 | super(floating, wifiManager, scanResult);
47 |
48 | mView.findViewById(R.id.Status).setVisibility(View.GONE);
49 | mView.findViewById(R.id.Speed).setVisibility(View.GONE);
50 | mView.findViewById(R.id.IPAddress).setVisibility(View.GONE);
51 |
52 | mPasswordEditText = ((ChangingAwareEditText)mView.findViewById(R.id.Password_EditText));
53 |
54 | ((TextView)mView.findViewById(R.id.Password_TextView)).setText(R.string.please_type_passphrase);
55 |
56 | ((EditText)mView.findViewById(R.id.Password_EditText)).setHint(R.string.wifi_password_unchanged);
57 | }
58 |
59 | @Override
60 | public int getButtonCount() {
61 | return 2;
62 | }
63 |
64 | @Override
65 | public OnClickListener getButtonOnClickListener(int index) {
66 | return mOnClickListeners[index];
67 | }
68 |
69 | @Override
70 | public CharSequence getButtonText(int index) {
71 | switch(index) {
72 | case 0:
73 | return mFloating.getString(R.string.wifi_save_config);
74 | case 1:
75 | return getCancelString();
76 | default:
77 | return null;
78 | }
79 | }
80 |
81 | @Override
82 | public CharSequence getTitle() {
83 | return mScanResult.SSID;
84 | }
85 |
86 | private OnClickListener mSaveOnClick = new OnClickListener() {
87 |
88 | @Override
89 | public void onClick(View v) {
90 | if(mPasswordEditText.getChanged()) {
91 | final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, mScanResultSecurity);
92 | boolean saveResult = false;
93 | if(config != null) {
94 | saveResult = Wifi.changePasswordAndConnect(mFloating, mWifiManager, config
95 | , mPasswordEditText.getText().toString()
96 | , mNumOpenNetworksKept);
97 | }
98 |
99 | if(!saveResult) {
100 | Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
101 | }
102 | }
103 |
104 | mFloating.finish();
105 | }
106 | };
107 |
108 | OnClickListener mOnClickListeners[] = {mSaveOnClick, mCancelOnClick};
109 |
110 | @Override
111 | public boolean onContextItemSelected(MenuItem item) {
112 | return false;
113 | }
114 |
115 | @Override
116 | public void onCreateContextMenu(ContextMenu menu, View v,
117 | ContextMenuInfo menuInfo) {
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
29 |
30 |
31 | Wifi Connecter Library
32 |
33 | Failed!
34 | More…
35 |
36 |
37 | Connect
38 |
39 | Connect to %s
40 |
41 | IP address
42 |
43 | Signal strength
44 |
45 |
46 | Forget
47 |
48 | Status
49 |
50 | Connected
51 | Connecting…
52 |
53 | Speed
54 |
55 | Excellent
56 |
57 | Good
58 |
59 | Fair
60 |
61 | Poor
62 |
63 | Security
64 |
65 | Open
66 |
67 | WEP
68 |
69 | WPA
70 |
71 | WPA2
72 |
73 | WPA-EAP
74 |
75 | IEEE8021X
76 |
77 |
78 | Wireless password
79 | Show password.
80 |
81 | Change password
82 | Modify
83 |
84 | (unchanged)
85 |
86 | Save
87 |
88 | AdHoc is not supported by Android platform yet!
89 |
90 | ""
91 |
92 |
93 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/BaseContent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import com.farproc.wifi.connecter.R;
29 |
30 | import android.net.wifi.ScanResult;
31 | import android.net.wifi.WifiManager;
32 | import android.provider.Settings;
33 | import android.text.InputType;
34 | import android.view.View;
35 | import android.view.View.OnClickListener;
36 | import android.widget.CheckBox;
37 | import android.widget.CompoundButton;
38 | import android.widget.EditText;
39 | import android.widget.TextView;
40 | import android.widget.CompoundButton.OnCheckedChangeListener;
41 |
42 | public abstract class BaseContent implements Floating.Content, OnCheckedChangeListener {
43 |
44 | protected final WifiManager mWifiManager;
45 | protected final Floating mFloating;
46 | protected final ScanResult mScanResult;
47 | protected final String mScanResultSecurity;
48 | protected final boolean mIsOpenNetwork ;
49 |
50 | protected int mNumOpenNetworksKept;
51 |
52 | protected View mView;
53 |
54 | protected OnClickListener mCancelOnClick = new OnClickListener() {
55 |
56 | @Override
57 | public void onClick(View v) {
58 | mFloating.finish();
59 | }
60 | };
61 |
62 | protected String getCancelString() {
63 | return mFloating.getString(android.R.string.cancel);
64 | }
65 |
66 | private static final int[] SIGNAL_LEVEL = {R.string.wifi_signal_0, R.string.wifi_signal_1,
67 | R.string.wifi_signal_2, R.string.wifi_signal_3};
68 |
69 | public BaseContent(final Floating floating, final WifiManager wifiManager, final ScanResult scanResult) {
70 | super();
71 | mWifiManager = wifiManager;
72 | mFloating = floating;
73 | mScanResult = scanResult;
74 | mScanResultSecurity = Wifi.ConfigSec.getScanResultSecurity(mScanResult);
75 | mIsOpenNetwork = Wifi.ConfigSec.isOpenNetwork(mScanResultSecurity);
76 |
77 | mView = View.inflate(mFloating, R.layout.base_content, null);
78 | ((TextView)mView.findViewById(R.id.SignalStrength_TextView)).setText(SIGNAL_LEVEL[WifiManager.calculateSignalLevel(mScanResult.level, SIGNAL_LEVEL.length)]);
79 | final String rawSecurity = Wifi.ConfigSec.getDisplaySecirityString(mScanResult);
80 | final String readableSecurity = Wifi.ConfigSec.isOpenNetwork(rawSecurity) ? mFloating.getString(R.string.wifi_security_open) : rawSecurity;
81 | ((TextView)mView.findViewById(R.id.Security_TextView)).setText(readableSecurity);
82 | ((CheckBox)mView.findViewById(R.id.ShowPassword_CheckBox)).setOnCheckedChangeListener(this);
83 |
84 | mNumOpenNetworksKept = Settings.Secure.getInt(floating.getContentResolver(),
85 | Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT, 10);
86 | }
87 |
88 |
89 | @Override
90 | public View getView() {
91 | return mView;
92 | }
93 |
94 | @Override
95 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
96 | ((EditText)mView.findViewById(R.id.Password_EditText)).setInputType(
97 | InputType.TYPE_CLASS_TEXT |
98 | (isChecked ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
99 | :InputType.TYPE_TEXT_VARIATION_PASSWORD));
100 | }
101 |
102 |
103 | public OnClickListener mChangePasswordOnClick = new OnClickListener() {
104 |
105 | @Override
106 | public void onClick(View v) {
107 | changePassword();
108 | }
109 |
110 | };
111 |
112 | public void changePassword() {
113 | mFloating.setContent(new ChangePasswordContent(mFloating, mWifiManager, mScanResult));
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/Floating.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import android.app.Activity;
29 | import android.os.Bundle;
30 | import android.util.DisplayMetrics;
31 | import android.view.ContextMenu;
32 | import android.view.MenuItem;
33 | import android.view.View;
34 | import android.view.View.OnClickListener;
35 | import android.view.ViewGroup;
36 | import android.view.ViewGroup.LayoutParams;
37 | import android.view.Window;
38 | import android.widget.Button;
39 | import android.widget.TextView;
40 |
41 | import java.util.Locale;
42 |
43 | /**
44 | * A dialog-like floating activity
45 | * @author Kevin Yuan
46 | *
47 | */
48 | public class Floating extends Activity {
49 |
50 | private static final int[] BUTTONS = {R.id.button1, R.id.button2, R.id.button3};
51 |
52 | private View mView;
53 | private ViewGroup mContentViewContainer;
54 | private Content mContent;
55 |
56 | @Override
57 | public void onCreate(Bundle savedInstanceState) {
58 | // It will not work if we setTheme here.
59 | // Please add android:theme="@android:style/Theme.Dialog" to any descendant class in AndroidManifest.xml!
60 | // See http://code.google.com/p/android/issues/detail?id=4394
61 | // setTheme(android.R.style.Theme_Dialog);
62 | getWindow().requestFeature(Window.FEATURE_NO_TITLE);
63 |
64 | super.onCreate(savedInstanceState);
65 |
66 | mView = View.inflate(this, R.layout.floating, null);
67 | final DisplayMetrics dm = new DisplayMetrics();
68 | getWindowManager().getDefaultDisplay().getMetrics(dm);
69 | mView.setMinimumWidth(Math.min(dm.widthPixels, dm.heightPixels) - 20);
70 | setContentView(mView);
71 |
72 | mContentViewContainer = (ViewGroup) mView.findViewById(R.id.content);
73 | }
74 |
75 | private void setDialogContentView(final View contentView) {
76 | mContentViewContainer.removeAllViews();
77 | mContentViewContainer.addView(contentView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
78 | }
79 |
80 | public void setContent(Content content) {
81 | mContent = content;
82 | refreshContent();
83 | }
84 |
85 | public void refreshContent() {
86 | setDialogContentView(mContent.getView());
87 | ((TextView)findViewById(R.id.title)).setText(mContent.getTitle());
88 |
89 | final int btnCount = mContent.getButtonCount();
90 | if(btnCount > BUTTONS.length) {
91 | throw new RuntimeException(String.format(Locale.US, "%d exceeds maximum button count: %d!", btnCount, BUTTONS.length));
92 | }
93 | findViewById(R.id.buttons_view).setVisibility(btnCount > 0 ? View.VISIBLE : View.GONE);
94 | for(int buttonId:BUTTONS) {
95 | final Button btn = (Button) findViewById(buttonId);
96 | btn.setOnClickListener(null);
97 | btn.setVisibility(View.GONE);
98 | }
99 |
100 | for(int btnIndex = 0; btnIndex < btnCount; btnIndex++){
101 | final Button btn = (Button)findViewById(BUTTONS[btnIndex]);
102 | btn.setText(mContent.getButtonText(btnIndex));
103 | btn.setVisibility(View.VISIBLE);
104 | btn.setOnClickListener(mContent.getButtonOnClickListener(btnIndex));
105 | }
106 | }
107 |
108 | public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
109 | if(mContent != null) {
110 | mContent.onCreateContextMenu(menu, v, menuInfo);
111 | }
112 | }
113 |
114 | public boolean onContextItemSelected (MenuItem item) {
115 | if(mContent != null) {
116 | return mContent.onContextItemSelected(item);
117 | }
118 | return false;
119 | }
120 |
121 |
122 | public interface Content {
123 | CharSequence getTitle();
124 | View getView();
125 | int getButtonCount();
126 | CharSequence getButtonText(int index);
127 | OnClickListener getButtonOnClickListener(int index);
128 | void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo);
129 | boolean onContextItemSelected (MenuItem item);
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/ConfiguredNetworkContent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import android.net.wifi.ScanResult;
29 | import android.net.wifi.WifiConfiguration;
30 | import android.net.wifi.WifiManager;
31 | import android.view.ContextMenu;
32 | import android.view.ContextMenu.ContextMenuInfo;
33 | import android.view.Menu;
34 | import android.view.MenuItem;
35 | import android.view.View;
36 | import android.view.View.OnClickListener;
37 | import android.widget.Toast;
38 |
39 | public class ConfiguredNetworkContent extends BaseContent {
40 |
41 | public ConfiguredNetworkContent(Floating floating, WifiManager wifiManager,
42 | ScanResult scanResult) {
43 | super(floating, wifiManager, scanResult);
44 |
45 | mView.findViewById(R.id.Status).setVisibility(View.GONE);
46 | mView.findViewById(R.id.Speed).setVisibility(View.GONE);
47 | mView.findViewById(R.id.IPAddress).setVisibility(View.GONE);
48 | mView.findViewById(R.id.Password).setVisibility(View.GONE);
49 | }
50 |
51 | @Override
52 | public int getButtonCount() {
53 | return 3;
54 | }
55 |
56 | @Override
57 | public OnClickListener getButtonOnClickListener(int index) {
58 | switch(index) {
59 | case 0:
60 | return mConnectOnClick;
61 | case 1:
62 | if(mIsOpenNetwork) {
63 | return mForgetOnClick;
64 | } else {
65 | return mOpOnClick;
66 | }
67 | case 2:
68 | return mCancelOnClick;
69 | default:
70 | return null;
71 | }
72 | }
73 |
74 | @Override
75 | public CharSequence getButtonText(int index) {
76 | switch(index) {
77 | case 0:
78 | return mFloating.getString(R.string.connect);
79 | case 1:
80 | if(mIsOpenNetwork) {
81 | return mFloating.getString(R.string.forget_network);
82 | } else {
83 | return mFloating.getString(R.string.buttonOp);
84 | }
85 | case 2:
86 | return getCancelString();
87 | default:
88 | return null;
89 | }
90 | }
91 |
92 | @Override
93 | public CharSequence getTitle() {
94 | return mFloating.getString(R.string.wifi_connect_to, mScanResult.SSID);
95 | }
96 |
97 | private OnClickListener mConnectOnClick = new OnClickListener() {
98 |
99 | @Override
100 | public void onClick(View v) {
101 | final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, mScanResultSecurity);
102 | boolean connResult = false;
103 | if(config != null) {
104 | connResult = Wifi.connectToConfiguredNetwork(mFloating, mWifiManager, config, false);
105 | }
106 | if(!connResult) {
107 | Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
108 | }
109 |
110 | mFloating.finish();
111 | }
112 | };
113 |
114 | private OnClickListener mOpOnClick = new OnClickListener() {
115 |
116 | @Override
117 | public void onClick(View v) {
118 | mFloating.registerForContextMenu(v);
119 | mFloating.openContextMenu(v);
120 | mFloating.unregisterForContextMenu(v);
121 | }
122 | };
123 |
124 | private OnClickListener mForgetOnClick = new OnClickListener() {
125 |
126 | @Override
127 | public void onClick(View v) {
128 | forget();
129 | }
130 | };
131 |
132 | private void forget() {
133 | final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, mScanResultSecurity);
134 | boolean result = false;
135 | if(config != null) {
136 | result = mWifiManager.removeNetwork(config.networkId)
137 | && mWifiManager.saveConfiguration();
138 | }
139 | if(!result) {
140 | Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
141 | }
142 |
143 | mFloating.finish();
144 | }
145 |
146 | private static final int MENU_FORGET = 0;
147 | private static final int MENU_CHANGE_PASSWORD = 1;
148 |
149 | @Override
150 | public boolean onContextItemSelected(MenuItem item) {
151 | switch(item.getItemId()) {
152 | case MENU_FORGET:
153 | forget();
154 | break;
155 | case MENU_CHANGE_PASSWORD:
156 | changePassword();
157 | break;
158 | }
159 | return false;
160 | }
161 |
162 | @Override
163 | public void onCreateContextMenu(ContextMenu menu, View v,
164 | ContextMenuInfo menuInfo) {
165 | menu.add(Menu.NONE, MENU_FORGET, Menu.NONE, R.string.forget_network);
166 | menu.add(Menu.NONE, MENU_CHANGE_PASSWORD, Menu.NONE, R.string.wifi_change_password);
167 | }
168 |
169 | }
170 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/base_content.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
29 |
30 |
36 |
37 |
41 |
42 |
48 |
49 |
57 |
58 |
59 |
60 |
64 |
65 |
71 |
72 |
80 |
81 |
82 |
83 |
87 |
88 |
94 |
95 |
103 |
104 |
105 |
106 |
110 |
111 |
117 |
118 |
126 |
127 |
128 |
129 |
133 |
134 |
140 |
141 |
149 |
150 |
151 |
152 |
156 |
157 |
164 |
165 |
169 |
170 |
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/CurrentNetworkContent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import android.net.NetworkInfo;
29 | import android.net.wifi.ScanResult;
30 | import android.net.wifi.SupplicantState;
31 | import android.net.wifi.WifiConfiguration;
32 | import android.net.wifi.WifiInfo;
33 | import android.net.wifi.WifiManager;
34 | import android.view.ContextMenu;
35 | import android.view.ContextMenu.ContextMenuInfo;
36 | import android.view.MenuItem;
37 | import android.view.View;
38 | import android.view.View.OnClickListener;
39 | import android.widget.TextView;
40 | import android.widget.Toast;
41 |
42 | public class CurrentNetworkContent extends BaseContent {
43 |
44 | public CurrentNetworkContent(Floating floating, WifiManager wifiManager,
45 | ScanResult scanResult) {
46 | super(floating, wifiManager, scanResult);
47 |
48 | mView.findViewById(R.id.Status).setVisibility(View.GONE);
49 | mView.findViewById(R.id.Speed).setVisibility(View.GONE);
50 | mView.findViewById(R.id.IPAddress).setVisibility(View.GONE);
51 | mView.findViewById(R.id.Password).setVisibility(View.GONE);
52 |
53 | final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
54 | if(wifiInfo == null) {
55 | Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
56 | } else {
57 | final SupplicantState state = wifiInfo.getSupplicantState();
58 | final NetworkInfo.DetailedState detailedState = WifiInfo.getDetailedStateOf(state);
59 | if(detailedState == NetworkInfo.DetailedState.CONNECTED
60 | || (detailedState == NetworkInfo.DetailedState.OBTAINING_IPADDR && wifiInfo.getIpAddress() != 0)) {
61 | mView.findViewById(R.id.Status).setVisibility(View.VISIBLE);
62 | mView.findViewById(R.id.Speed).setVisibility(View.VISIBLE);
63 | mView.findViewById(R.id.IPAddress).setVisibility(View.VISIBLE);
64 |
65 | ((TextView)mView.findViewById(R.id.Status_TextView)).setText(R.string.status_connected);
66 | ((TextView)mView.findViewById(R.id.LinkSpeed_TextView)).setText(wifiInfo.getLinkSpeed() + " " + WifiInfo.LINK_SPEED_UNITS);
67 | ((TextView)mView.findViewById(R.id.IPAddress_TextView)).setText(getIPAddress(wifiInfo.getIpAddress()));
68 | } else if(detailedState == NetworkInfo.DetailedState.AUTHENTICATING
69 | || detailedState == NetworkInfo.DetailedState.CONNECTING
70 | || detailedState == NetworkInfo.DetailedState.OBTAINING_IPADDR) {
71 | mView.findViewById(R.id.Status).setVisibility(View.VISIBLE);
72 | ((TextView)mView.findViewById(R.id.Status_TextView)).setText(R.string.status_connecting);
73 | }
74 | }
75 | }
76 |
77 | @Override
78 | public int getButtonCount() {
79 | // No Modify button for open network.
80 | return mIsOpenNetwork ? 2 : 3;
81 | }
82 |
83 | @Override
84 | public OnClickListener getButtonOnClickListener(int index) {
85 | if(mIsOpenNetwork && index == 1) {
86 | // No Modify button for open network.
87 | // index 1 is Cancel(index 2).
88 | return mOnClickListeners[2];
89 | }
90 | return mOnClickListeners[index];
91 | }
92 |
93 | @Override
94 | public CharSequence getButtonText(int index) {
95 | switch(index) {
96 | case 0:
97 | return mFloating.getString(R.string.forget_network);
98 | case 1:
99 | if(mIsOpenNetwork) {
100 | // No Modify button for open network.
101 | // index 1 is Cancel.
102 | return getCancelString();
103 | }
104 | return mFloating.getString(R.string.button_change_password);
105 | case 2:
106 | return getCancelString();
107 | default:
108 | return null;
109 | }
110 | }
111 |
112 | @Override
113 | public CharSequence getTitle() {
114 | return mScanResult.SSID;
115 | }
116 |
117 | private OnClickListener mForgetOnClick = new OnClickListener() {
118 |
119 | @Override
120 | public void onClick(View v) {
121 | final WifiConfiguration config = Wifi.getWifiConfiguration(mWifiManager, mScanResult, mScanResultSecurity);
122 | boolean result = false;
123 | if(config != null) {
124 | result = mWifiManager.removeNetwork(config.networkId)
125 | && mWifiManager.saveConfiguration();
126 | }
127 | if(!result) {
128 | Toast.makeText(mFloating, R.string.toastFailed, Toast.LENGTH_LONG).show();
129 | }
130 |
131 | mFloating.finish();
132 | }
133 | };
134 |
135 |
136 | private OnClickListener mOnClickListeners[] = {mForgetOnClick, mChangePasswordOnClick, mCancelOnClick};
137 |
138 | private String getIPAddress(int address) {
139 | StringBuilder sb = new StringBuilder();
140 | sb.append(address & 0x000000FF).append(".")
141 | .append((address & 0x0000FF00) >> 8).append(".")
142 | .append((address & 0x00FF0000) >> 16).append(".")
143 | .append((address & 0xFF000000L) >> 24);
144 | return sb.toString();
145 | }
146 |
147 | @Override
148 | public boolean onContextItemSelected(MenuItem item) {
149 | return false;
150 | }
151 |
152 | @Override
153 | public void onCreateContextMenu(ContextMenu menu, View v,
154 | ContextMenuInfo menuInfo) {
155 | }
156 |
157 | }
158 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/TestWifiScan.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import java.util.List;
29 |
30 | import android.app.Activity;
31 | import android.app.ListActivity;
32 | import android.content.ActivityNotFoundException;
33 | import android.content.BroadcastReceiver;
34 | import android.content.Context;
35 | import android.content.Intent;
36 | import android.content.IntentFilter;
37 | import android.net.Uri;
38 | import android.net.wifi.ScanResult;
39 | import android.net.wifi.WifiManager;
40 | import android.os.Bundle;
41 | import android.view.View;
42 | import android.view.ViewGroup;
43 | import android.widget.AdapterView;
44 | import android.widget.BaseAdapter;
45 | import android.widget.Toast;
46 | import android.widget.TwoLineListItem;
47 | import android.widget.AdapterView.OnItemClickListener;
48 |
49 | public class TestWifiScan extends ListActivity {
50 |
51 | private WifiManager mWifiManager;
52 | private List mScanResults;
53 |
54 |
55 | @Override
56 | public void onCreate(Bundle savedInstanceState) {
57 | super.onCreate(savedInstanceState);
58 |
59 | mWifiManager = (WifiManager)getSystemService(WIFI_SERVICE);
60 |
61 | setListAdapter(mListAdapter);
62 |
63 | getListView().setOnItemClickListener(mItemOnClick);
64 | }
65 |
66 | @Override
67 | public void onResume() {
68 | super.onResume();
69 | final IntentFilter filter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
70 | registerReceiver(mReceiver, filter);
71 | mWifiManager.startScan();
72 | }
73 |
74 | @Override
75 | public void onPause() {
76 | super.onPause();
77 | unregisterReceiver(mReceiver);
78 | }
79 |
80 | private BroadcastReceiver mReceiver = new BroadcastReceiver() {
81 |
82 | @Override
83 | public void onReceive(Context context, Intent intent) {
84 | final String action = intent.getAction();
85 | if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
86 | mScanResults = mWifiManager.getScanResults();
87 | mListAdapter.notifyDataSetChanged();
88 |
89 | mWifiManager.startScan();
90 | }
91 |
92 | }
93 | };
94 |
95 | private BaseAdapter mListAdapter = new BaseAdapter() {
96 |
97 | @Override
98 | public View getView(int position, View convertView, ViewGroup parent) {
99 | if(convertView == null || !(convertView instanceof TwoLineListItem)) {
100 | convertView = View.inflate(getApplicationContext(),
101 | android.R.layout.simple_list_item_2, null);
102 | }
103 |
104 | final ScanResult result = mScanResults.get(position);
105 | ((TwoLineListItem)convertView).getText1().setText(result.SSID);
106 | ((TwoLineListItem)convertView).getText2().setText(
107 | String.format("%s %d", result.BSSID, result.level)
108 | );
109 | return convertView;
110 | }
111 |
112 | @Override
113 | public long getItemId(int position) {
114 | return position;
115 | }
116 |
117 | @Override
118 | public Object getItem(int position) {
119 | return null;
120 | }
121 |
122 | @Override
123 | public int getCount() {
124 | return mScanResults == null ? 0 : mScanResults.size();
125 | }
126 | };
127 |
128 | private OnItemClickListener mItemOnClick = new OnItemClickListener() {
129 |
130 | @Override
131 | public void onItemClick(AdapterView> parent, View view, int position,
132 | long id) {
133 | final ScanResult result = mScanResults.get(position);
134 | launchWifiConnecter(TestWifiScan.this, result);
135 | }
136 | };
137 |
138 | /**
139 | * Try to launch Wifi Connecter with {@link #hostspot}. Prompt user to download if Wifi Connecter is not installed.
140 | * @param activity
141 | * @param hotspot
142 | */
143 | private static void launchWifiConnecter(final Activity activity, final ScanResult hotspot) {
144 | final Intent intent = new Intent("com.farproc.wifi.connecter.action.CONNECT_OR_EDIT");
145 | intent.putExtra("com.farproc.wifi.connecter.extra.HOTSPOT", hotspot);
146 | try {
147 | activity.startActivity(intent);
148 | } catch(ActivityNotFoundException e) {
149 | // Wifi Connecter Library is not installed.
150 | Toast.makeText(activity, "Wifi Connecter is not installed.", Toast.LENGTH_LONG).show();
151 | downloadWifiConnecter(activity);
152 | }
153 | }
154 |
155 | private static void downloadWifiConnecter(final Activity activity) {
156 | Intent downloadIntent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse("market://details?id=com.farproc.wifi.connecter"));
157 | try {
158 | activity.startActivity(downloadIntent);
159 | Toast.makeText(activity, "Please install this app.", Toast.LENGTH_LONG).show();
160 | } catch (ActivityNotFoundException e) {
161 | // Market app is not available in this device.
162 | // Show download page of this project.
163 | try {
164 | downloadIntent.setData(Uri.parse("http://code.google.com/p/android-wifi-connecter/downloads/list"));
165 | activity.startActivity(downloadIntent);
166 | Toast.makeText(activity, "Please download the apk and install it manully.", Toast.LENGTH_LONG).show();
167 | } catch (ActivityNotFoundException e2) {
168 | // Even the Browser app is not available!!!!!
169 | // Show a error message!
170 | Toast.makeText(activity, "Fatel error! No web browser app in your device!!!", Toast.LENGTH_LONG).show();
171 | }
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/ConfigurationSecuritiesV8.java:
--------------------------------------------------------------------------------
1 | package com.farproc.wifi.connecter;
2 |
3 | import android.net.wifi.ScanResult;
4 | import android.net.wifi.WifiConfiguration;
5 | import android.net.wifi.WifiConfiguration.AuthAlgorithm;
6 | import android.net.wifi.WifiConfiguration.KeyMgmt;
7 | import android.util.Log;
8 |
9 | public class ConfigurationSecuritiesV8 extends ConfigurationSecurities {
10 |
11 | static final int SECURITY_NONE = 0;
12 | static final int SECURITY_WEP = 1;
13 | static final int SECURITY_PSK = 2;
14 | static final int SECURITY_EAP = 3;
15 |
16 | enum PskType {
17 | UNKNOWN,
18 | WPA,
19 | WPA2,
20 | WPA_WPA2
21 | }
22 |
23 | private static final String TAG = "ConfigurationSecuritiesV14";
24 |
25 | private static int getSecurity(WifiConfiguration config) {
26 | if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
27 | return SECURITY_PSK;
28 | }
29 | if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
30 | config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
31 | return SECURITY_EAP;
32 | }
33 | return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
34 | }
35 |
36 | private static int getSecurity(ScanResult result) {
37 | if (result.capabilities.contains("WEP")) {
38 | return SECURITY_WEP;
39 | } else if (result.capabilities.contains("PSK")) {
40 | return SECURITY_PSK;
41 | } else if (result.capabilities.contains("EAP")) {
42 | return SECURITY_EAP;
43 | }
44 | return SECURITY_NONE;
45 | }
46 |
47 | @Override
48 | public String getWifiConfigurationSecurity(WifiConfiguration wifiConfig) {
49 | return String.valueOf(getSecurity(wifiConfig));
50 | }
51 |
52 | @Override
53 | public String getScanResultSecurity(ScanResult scanResult) {
54 | return String.valueOf(getSecurity(scanResult));
55 | }
56 |
57 | @Override
58 | public void setupSecurity(WifiConfiguration config, String security, String password) {
59 | config.allowedAuthAlgorithms.clear();
60 | config.allowedGroupCiphers.clear();
61 | config.allowedKeyManagement.clear();
62 | config.allowedPairwiseCiphers.clear();
63 | config.allowedProtocols.clear();
64 |
65 | final int sec = security == null ? SECURITY_NONE : Integer.valueOf(security);
66 | final int passwordLen = password == null ? 0 : password.length();
67 | switch (sec) {
68 | case SECURITY_NONE:
69 | config.allowedKeyManagement.set(KeyMgmt.NONE);
70 | break;
71 |
72 | case SECURITY_WEP:
73 | config.allowedKeyManagement.set(KeyMgmt.NONE);
74 | config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
75 | config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
76 | if (passwordLen != 0) {
77 | // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
78 | if ((passwordLen == 10 || passwordLen == 26 || passwordLen == 58) &&
79 | password.matches("[0-9A-Fa-f]*")) {
80 | config.wepKeys[0] = password;
81 | } else {
82 | config.wepKeys[0] = '"' + password + '"';
83 | }
84 | }
85 | break;
86 |
87 | case SECURITY_PSK:
88 | config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
89 | if (passwordLen != 0) {
90 | if (password.matches("[0-9A-Fa-f]{64}")) {
91 | config.preSharedKey = password;
92 | } else {
93 | config.preSharedKey = '"' + password + '"';
94 | }
95 | }
96 | break;
97 |
98 | case SECURITY_EAP:
99 | config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
100 | config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
101 | // config.eap.setValue((String) mEapMethodSpinner.getSelectedItem());
102 | //
103 | // config.phase2.setValue((mPhase2Spinner.getSelectedItemPosition() == 0) ? "" :
104 | // "auth=" + mPhase2Spinner.getSelectedItem());
105 | // config.ca_cert.setValue((mEapCaCertSpinner.getSelectedItemPosition() == 0) ? "" :
106 | // KEYSTORE_SPACE + Credentials.CA_CERTIFICATE +
107 | // (String) mEapCaCertSpinner.getSelectedItem());
108 | // config.client_cert.setValue((mEapUserCertSpinner.getSelectedItemPosition() == 0) ?
109 | // "" : KEYSTORE_SPACE + Credentials.USER_CERTIFICATE +
110 | // (String) mEapUserCertSpinner.getSelectedItem());
111 | // config.private_key.setValue((mEapUserCertSpinner.getSelectedItemPosition() == 0) ?
112 | // "" : KEYSTORE_SPACE + Credentials.USER_PRIVATE_KEY +
113 | // (String) mEapUserCertSpinner.getSelectedItem());
114 | // config.identity.setValue((mEapIdentityView.length() == 0) ? "" :
115 | // mEapIdentityView.getText().toString());
116 | // config.anonymous_identity.setValue((mEapAnonymousView.length() == 0) ? "" :
117 | // mEapAnonymousView.getText().toString());
118 | // if (mPasswordView.length() != 0) {
119 | // config.password.setValue(mPasswordView.getText().toString());
120 | // }
121 | break;
122 |
123 | default:
124 | Log.e(TAG, "Invalid security type: " + sec);
125 | }
126 |
127 | // config.proxySettings = mProxySettings;
128 | // config.ipAssignment = mIpAssignment;
129 | // config.linkProperties = new LinkProperties(mLinkProperties);
130 |
131 | }
132 |
133 | private static PskType getPskType(ScanResult result) {
134 | boolean wpa = result.capabilities.contains("WPA-PSK");
135 | boolean wpa2 = result.capabilities.contains("WPA2-PSK");
136 | if (wpa2 && wpa) {
137 | return PskType.WPA_WPA2;
138 | } else if (wpa2) {
139 | return PskType.WPA2;
140 | } else if (wpa) {
141 | return PskType.WPA;
142 | } else {
143 | Log.w(TAG, "Received abnormal flag string: " + result.capabilities);
144 | return PskType.UNKNOWN;
145 | }
146 | }
147 |
148 | @Override
149 | public String getDisplaySecirityString(final ScanResult scanResult) {
150 | final int security = getSecurity(scanResult);
151 | if(security == SECURITY_PSK) {
152 | switch(getPskType(scanResult)) {
153 | case WPA:
154 | return "WPA";
155 | case WPA_WPA2:
156 | case WPA2:
157 | return "WPA2";
158 | default:
159 | return "?";
160 | }
161 | } else {
162 | switch(security) {
163 | case SECURITY_NONE:
164 | return "OPEN";
165 | case SECURITY_WEP:
166 | return "WEP";
167 | case SECURITY_EAP:
168 | return "EAP";
169 | }
170 | }
171 |
172 | return "?";
173 | }
174 |
175 | @Override
176 | public boolean isOpenNetwork(String security) {
177 | return String.valueOf(SECURITY_NONE).equals(security);
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/ConfigurationSecuritiesOld.java:
--------------------------------------------------------------------------------
1 | package com.farproc.wifi.connecter;
2 |
3 | import android.net.wifi.ScanResult;
4 | import android.net.wifi.WifiConfiguration;
5 | import android.net.wifi.WifiConfiguration.AuthAlgorithm;
6 | import android.net.wifi.WifiConfiguration.GroupCipher;
7 | import android.net.wifi.WifiConfiguration.KeyMgmt;
8 | import android.net.wifi.WifiConfiguration.PairwiseCipher;
9 | import android.net.wifi.WifiConfiguration.Protocol;
10 | import android.text.TextUtils;
11 | import android.util.Log;
12 |
13 | public class ConfigurationSecuritiesOld extends ConfigurationSecurities {
14 |
15 | // Constants used for different security types
16 | public static final String WPA2 = "WPA2";
17 | public static final String WPA = "WPA";
18 | public static final String WEP = "WEP";
19 | public static final String OPEN = "Open";
20 | // For EAP Enterprise fields
21 | public static final String WPA_EAP = "WPA-EAP";
22 | public static final String IEEE8021X = "IEEE8021X";
23 |
24 | public static final String[] EAP_METHOD = { "PEAP", "TLS", "TTLS" };
25 |
26 | public static final int WEP_PASSWORD_AUTO = 0;
27 | public static final int WEP_PASSWORD_ASCII = 1;
28 | public static final int WEP_PASSWORD_HEX = 2;
29 |
30 | static final String[] SECURITY_MODES = { WEP, WPA, WPA2, WPA_EAP, IEEE8021X };
31 |
32 | private static final String TAG = "ConfigurationSecuritiesOld";
33 |
34 | @Override
35 | public String getWifiConfigurationSecurity(WifiConfiguration wifiConfig) {
36 |
37 | if (wifiConfig.allowedKeyManagement.get(KeyMgmt.NONE)) {
38 | // If we never set group ciphers, wpa_supplicant puts all of them.
39 | // For open, we don't set group ciphers.
40 | // For WEP, we specifically only set WEP40 and WEP104, so CCMP
41 | // and TKIP should not be there.
42 | if (!wifiConfig.allowedGroupCiphers.get(GroupCipher.CCMP)
43 | &&
44 | (wifiConfig.allowedGroupCiphers.get(GroupCipher.WEP40)
45 | || wifiConfig.allowedGroupCiphers.get(GroupCipher.WEP104))) {
46 | return WEP;
47 | } else {
48 | return OPEN;
49 | }
50 | } else if (wifiConfig.allowedProtocols.get(Protocol.RSN)) {
51 | return WPA2;
52 | } else if (wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
53 | return WPA_EAP;
54 | } else if (wifiConfig.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
55 | return IEEE8021X;
56 | } else if (wifiConfig.allowedProtocols.get(Protocol.WPA)) {
57 | return WPA;
58 | } else {
59 | Log.w(TAG, "Unknown security type from WifiConfiguration, falling back on open.");
60 | return OPEN;
61 | }
62 | }
63 |
64 | @Override
65 | public String getScanResultSecurity(ScanResult scanResult) {
66 | final String cap = scanResult.capabilities;
67 | for (int i = SECURITY_MODES.length - 1; i >= 0; i--) {
68 | if (cap.contains(SECURITY_MODES[i])) {
69 | return SECURITY_MODES[i];
70 | }
71 | }
72 |
73 | return OPEN;
74 | }
75 | @Override
76 | public String getDisplaySecirityString(final ScanResult scanResult) {
77 | return getScanResultSecurity(scanResult);
78 | }
79 |
80 | private static boolean isHexWepKey(String wepKey) {
81 | final int len = wepKey.length();
82 |
83 | // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
84 | if (len != 10 && len != 26 && len != 58) {
85 | return false;
86 | }
87 |
88 | return isHex(wepKey);
89 | }
90 |
91 | private static boolean isHex(String key) {
92 | for (int i = key.length() - 1; i >= 0; i--) {
93 | final char c = key.charAt(i);
94 | if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f')) {
95 | return false;
96 | }
97 | }
98 |
99 | return true;
100 | }
101 |
102 | @Override
103 | public void setupSecurity(WifiConfiguration config, String security, final String password) {
104 | config.allowedAuthAlgorithms.clear();
105 | config.allowedGroupCiphers.clear();
106 | config.allowedKeyManagement.clear();
107 | config.allowedPairwiseCiphers.clear();
108 | config.allowedProtocols.clear();
109 |
110 | if (TextUtils.isEmpty(security)) {
111 | security = OPEN;
112 | Log.w(TAG, "Empty security, assuming open");
113 | }
114 |
115 | if (security.equals(WEP)) {
116 | int wepPasswordType = WEP_PASSWORD_AUTO;
117 | // If password is empty, it should be left untouched
118 | if (!TextUtils.isEmpty(password)) {
119 | if (wepPasswordType == WEP_PASSWORD_AUTO) {
120 | if (isHexWepKey(password)) {
121 | config.wepKeys[0] = password;
122 | } else {
123 | config.wepKeys[0] = Wifi.convertToQuotedString(password);
124 | }
125 | } else {
126 | config.wepKeys[0] = wepPasswordType == WEP_PASSWORD_ASCII
127 | ? Wifi.convertToQuotedString(password)
128 | : password;
129 | }
130 | }
131 |
132 | config.wepTxKeyIndex = 0;
133 |
134 | config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
135 | config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
136 |
137 | config.allowedKeyManagement.set(KeyMgmt.NONE);
138 |
139 | config.allowedGroupCiphers.set(GroupCipher.WEP40);
140 | config.allowedGroupCiphers.set(GroupCipher.WEP104);
141 |
142 | } else if (security.equals(WPA) || security.equals(WPA2)){
143 | config.allowedGroupCiphers.set(GroupCipher.TKIP);
144 | config.allowedGroupCiphers.set(GroupCipher.CCMP);
145 |
146 | config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
147 |
148 | config.allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
149 | config.allowedPairwiseCiphers.set(PairwiseCipher.TKIP);
150 |
151 | config.allowedProtocols.set(security.equals(WPA2) ? Protocol.RSN : Protocol.WPA);
152 |
153 | // If password is empty, it should be left untouched
154 | if (!TextUtils.isEmpty(password)) {
155 | if (password.length() == 64 && isHex(password)) {
156 | // Goes unquoted as hex
157 | config.preSharedKey = password;
158 | } else {
159 | // Goes quoted as ASCII
160 | config.preSharedKey = Wifi.convertToQuotedString(password);
161 | }
162 | }
163 |
164 | } else if (security.equals(OPEN)) {
165 | config.allowedKeyManagement.set(KeyMgmt.NONE);
166 | } else if (security.equals(WPA_EAP) || security.equals(IEEE8021X)) {
167 | config.allowedGroupCiphers.set(GroupCipher.TKIP);
168 | config.allowedGroupCiphers.set(GroupCipher.CCMP);
169 | if (security.equals(WPA_EAP)) {
170 | config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
171 | } else {
172 | config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
173 | }
174 | if (!TextUtils.isEmpty(password)) {
175 | config.preSharedKey = Wifi.convertToQuotedString(password);
176 | }
177 | }
178 | }
179 |
180 | @Override
181 | public boolean isOpenNetwork(String security) {
182 | return OPEN.equals(security);
183 | }
184 |
185 | }
186 |
--------------------------------------------------------------------------------
/app/src/main/java/com/farproc/wifi/connecter/Wifi.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Wifi Connecter
3 | *
4 | * Copyright (c) 2011 Kevin Yuan (farproc@gmail.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | *
24 | **/
25 |
26 | package com.farproc.wifi.connecter;
27 |
28 | import android.content.Context;
29 | import android.net.wifi.ScanResult;
30 | import android.net.wifi.WifiConfiguration;
31 | import android.net.wifi.WifiManager;
32 | import android.text.TextUtils;
33 | import android.util.Log;
34 |
35 | import java.util.Comparator;
36 | import java.util.List;
37 |
38 | public class Wifi {
39 |
40 | public static final ConfigurationSecurities ConfigSec = ConfigurationSecurities.newInstance();
41 |
42 | private static final String TAG = "Wifi Connecter";
43 |
44 | /**
45 | * Change the password of an existing configured network and connect to it
46 | * @param wifiMgr
47 | * @param config
48 | * @param newPassword
49 | * @return
50 | */
51 | public static boolean changePasswordAndConnect(final Context ctx, final WifiManager wifiMgr, final WifiConfiguration config, final String newPassword, final int numOpenNetworksKept) {
52 | ConfigSec.setupSecurity(config, ConfigSec.getWifiConfigurationSecurity(config), newPassword);
53 | final int networkId = wifiMgr.updateNetwork(config);
54 | if(networkId == -1) {
55 | // Update failed.
56 | return false;
57 | }
58 | // Force the change to apply.
59 | wifiMgr.disconnect();
60 | return connectToConfiguredNetwork(ctx, wifiMgr, config, true);
61 | }
62 |
63 | /**
64 | * Configure a network, and connect to it.
65 | * @param wifiMgr
66 | * @param scanResult
67 | * @param password Password for secure network or is ignored.
68 | * @return
69 | */
70 | public static boolean connectToNewNetwork(final Context ctx, final WifiManager wifiMgr, final ScanResult scanResult, final String password, final int numOpenNetworksKept) {
71 | final String security = ConfigSec.getScanResultSecurity(scanResult);
72 |
73 | if(ConfigSec.isOpenNetwork(security)) {
74 | checkForExcessOpenNetworkAndSave(wifiMgr, numOpenNetworksKept);
75 | }
76 |
77 | WifiConfiguration config = new WifiConfiguration();
78 | config.SSID = convertToQuotedString(scanResult.SSID);
79 | config.BSSID = scanResult.BSSID;
80 | ConfigSec.setupSecurity(config, security, password);
81 |
82 | int id = -1;
83 | try {
84 | id = wifiMgr.addNetwork(config);
85 | } catch(NullPointerException e) {
86 | Log.e(TAG, "Weird!! Really!! What's wrong??", e);
87 | // Weird!! Really!!
88 | // This exception is reported by user to Android Developer Console(https://market.android.com/publish/Home)
89 | }
90 | if(id == -1) {
91 | return false;
92 | }
93 |
94 | if(!wifiMgr.saveConfiguration()) {
95 | return false;
96 | }
97 |
98 | config = getWifiConfiguration(wifiMgr, config, security);
99 | if(config == null) {
100 | return false;
101 | }
102 |
103 | return connectToConfiguredNetwork(ctx, wifiMgr, config, true);
104 | }
105 |
106 | /**
107 | * Connect to a configured network.
108 | * @return
109 | */
110 | public static boolean connectToConfiguredNetwork(final Context ctx, final WifiManager wifiMgr, WifiConfiguration config, boolean reassociate) {
111 | if(Version.SDK >= 23) {
112 | return connectToConfiguredNetworkV23(ctx, wifiMgr, config, reassociate);
113 | }
114 | final String security = ConfigSec.getWifiConfigurationSecurity(config);
115 |
116 | int oldPri = config.priority;
117 | // Make it the highest priority.
118 | int newPri = getMaxPriority(wifiMgr) + 1;
119 | if(newPri > MAX_PRIORITY) {
120 | newPri = shiftPriorityAndSave(wifiMgr);
121 | config = getWifiConfiguration(wifiMgr, config, security);
122 | if(config == null) {
123 | return false;
124 | }
125 | }
126 |
127 | // Set highest priority to this configured network
128 | config.priority = newPri;
129 | int networkId = wifiMgr.updateNetwork(config);
130 | if(networkId == -1) {
131 | return false;
132 | }
133 |
134 | // Do not disable others
135 | if(!wifiMgr.enableNetwork(networkId, false)) {
136 | config.priority = oldPri;
137 | return false;
138 | }
139 |
140 | if(!wifiMgr.saveConfiguration()) {
141 | config.priority = oldPri;
142 | return false;
143 | }
144 |
145 | // We have to retrieve the WifiConfiguration after save.
146 | config = getWifiConfiguration(wifiMgr, config, security);
147 | if(config == null) {
148 | return false;
149 | }
150 |
151 | ReenableAllApsWhenNetworkStateChanged.schedule(ctx);
152 |
153 | // Disable others, but do not save.
154 | // Just to force the WifiManager to connect to it.
155 | if(!wifiMgr.enableNetwork(config.networkId, true)) {
156 | return false;
157 | }
158 |
159 | final boolean connect = reassociate ? wifiMgr.reassociate() : wifiMgr.reconnect();
160 | if(!connect) {
161 | return false;
162 | }
163 |
164 | return true;
165 | }
166 |
167 | private static boolean connectToConfiguredNetworkV23(final Context ctx, final WifiManager wifiMgr, WifiConfiguration config, boolean reassociate) {
168 | if(!wifiMgr.enableNetwork(config.networkId, true)) {
169 | return false;
170 | }
171 |
172 | return reassociate ? wifiMgr.reassociate() : wifiMgr.reconnect();
173 | }
174 |
175 | private static void sortByPriority(final List configurations) {
176 | java.util.Collections.sort(configurations, new Comparator() {
177 |
178 | @Override
179 | public int compare(WifiConfiguration object1,
180 | WifiConfiguration object2) {
181 | return object1.priority - object2.priority;
182 | }
183 | });
184 | }
185 |
186 | /**
187 | * Ensure no more than numOpenNetworksKept open networks in configuration list.
188 | * @param wifiMgr
189 | * @param numOpenNetworksKept
190 | * @return Operation succeed or not.
191 | */
192 | private static boolean checkForExcessOpenNetworkAndSave(final WifiManager wifiMgr, final int numOpenNetworksKept) {
193 | final List configurations = wifiMgr.getConfiguredNetworks();
194 | sortByPriority(configurations);
195 |
196 | boolean modified = false;
197 | int tempCount = 0;
198 | for(int i = configurations.size() - 1; i >= 0; i--) {
199 | final WifiConfiguration config = configurations.get(i);
200 | if(ConfigSec.isOpenNetwork(ConfigSec.getWifiConfigurationSecurity(config))) {
201 | tempCount++;
202 | if(tempCount >= numOpenNetworksKept) {
203 | modified = true;
204 | wifiMgr.removeNetwork(config.networkId);
205 | }
206 | }
207 | }
208 | if(modified) {
209 | return wifiMgr.saveConfiguration();
210 | }
211 |
212 | return true;
213 | }
214 |
215 | private static final int MAX_PRIORITY = 99999;
216 |
217 | private static int shiftPriorityAndSave(final WifiManager wifiMgr) {
218 | final List configurations = wifiMgr.getConfiguredNetworks();
219 | sortByPriority(configurations);
220 | final int size = configurations.size();
221 | for(int i = 0; i < size; i++) {
222 | final WifiConfiguration config = configurations.get(i);
223 | config.priority = i;
224 | wifiMgr.updateNetwork(config);
225 | }
226 | wifiMgr.saveConfiguration();
227 | return size;
228 | }
229 |
230 | private static int getMaxPriority(final WifiManager wifiManager) {
231 | final List configurations = wifiManager.getConfiguredNetworks();
232 | int pri = 0;
233 | for(final WifiConfiguration config : configurations) {
234 | if(config.priority > pri) {
235 | pri = config.priority;
236 | }
237 | }
238 | return pri;
239 | }
240 |
241 | private static final String BSSID_ANY = "any";
242 |
243 | public static WifiConfiguration getWifiConfiguration(final WifiManager wifiMgr, final ScanResult hotsopt, String hotspotSecurity) {
244 | final String ssid = convertToQuotedString(hotsopt.SSID);
245 | if(ssid.length() == 0) {
246 | return null;
247 | }
248 |
249 | final String bssid = hotsopt.BSSID;
250 | if(bssid == null) {
251 | return null;
252 | }
253 |
254 | if(hotspotSecurity == null) {
255 | hotspotSecurity = ConfigSec.getScanResultSecurity(hotsopt);
256 | }
257 |
258 | final List configurations = wifiMgr.getConfiguredNetworks();
259 | if(configurations == null) {
260 | return null;
261 | }
262 |
263 | for(final WifiConfiguration config : configurations) {
264 | if(config.SSID == null || !ssid.equals(config.SSID)) {
265 | continue;
266 | }
267 | if(config.BSSID == null || BSSID_ANY.equals(config.BSSID) || bssid.equals(config.BSSID)) {
268 | final String configSecurity = ConfigSec.getWifiConfigurationSecurity(config);
269 | if(hotspotSecurity.equals(configSecurity)) {
270 | return config;
271 | }
272 | }
273 | }
274 | return null;
275 | }
276 |
277 | public static WifiConfiguration getWifiConfiguration(final WifiManager wifiMgr, final WifiConfiguration configToFind, String security) {
278 | final String ssid = configToFind.SSID;
279 | if(ssid.length() == 0) {
280 | return null;
281 | }
282 |
283 | final String bssid = configToFind.BSSID;
284 |
285 |
286 | if(security == null) {
287 | security = ConfigSec.getWifiConfigurationSecurity(configToFind);
288 | }
289 |
290 | final List configurations = wifiMgr.getConfiguredNetworks();
291 |
292 | for(final WifiConfiguration config : configurations) {
293 | if(config.SSID == null || !ssid.equals(config.SSID)) {
294 | continue;
295 | }
296 | if(config.BSSID == null || BSSID_ANY.equals(config.BSSID) || bssid == null || bssid.equals(config.BSSID)) {
297 | final String configSecurity = ConfigSec.getWifiConfigurationSecurity(config);
298 | if(security.equals(configSecurity)) {
299 | return config;
300 | }
301 | }
302 | }
303 | return null;
304 | }
305 |
306 | public static String convertToQuotedString(String string) {
307 | if (TextUtils.isEmpty(string)) {
308 | return "";
309 | }
310 |
311 | final int lastPos = string.length() - 1;
312 | if(lastPos > 0 && (string.charAt(0) == '"' && string.charAt(lastPos) == '"')) {
313 | return string;
314 | }
315 |
316 | return "\"" + string + "\"";
317 | }
318 |
319 | }
320 |
--------------------------------------------------------------------------------