├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── arrays.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── strings.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── layout
│ │ │ │ ├── settings_activity.xml
│ │ │ │ ├── activity_main.xml
│ │ │ │ └── content_main.xml
│ │ │ ├── menu
│ │ │ │ └── menu_main.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── xml
│ │ │ │ └── root_preferences.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── net
│ │ │ └── mobilewebprint
│ │ │ └── nan
│ │ │ ├── SettingsActivity.java
│ │ │ └── MainActivity.java
│ ├── test
│ │ └── java
│ │ │ └── net
│ │ │ └── mobilewebprint
│ │ │ └── nan
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── net
│ │ └── mobilewebprint
│ │ └── nan
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── README.md
├── gradlew.bat
├── .gitignore
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 16dp
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anagramrice/NAN/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/settings_activity.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
9 |
--------------------------------------------------------------------------------
/app/src/test/java/net/mobilewebprint/nan/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package net.mobilewebprint.nan;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Open
5 | - Pre-shared Key
6 | - Pairwise Master Key
7 |
8 |
9 |
10 | - open
11 | - psk
12 | - pmk
13 |
14 |
15 |
16 | - unsolicited
17 | - solicited
18 |
19 |
20 |
21 | - passive
22 | - active
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/net/mobilewebprint/nan/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package net.mobilewebprint.nan;
2 |
3 | import android.content.Context;
4 | import androidx.test.platform.app.InstrumentationRegistry;
5 | import androidx.test.ext.junit.runners.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("net.mobilewebprint.nan", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | android.useAndroidX=true
11 | android.enableJetifier=true
12 | android.defaults.buildfeatures.buildconfig=true
13 | android.nonTransitiveRClass=false
14 | android.nonFinalResIds=false
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 33
5 | defaultConfig {
6 | applicationId "net.mobilewebprint.nan"
7 | minSdkVersion 23
8 | targetSdkVersion 33
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | namespace 'net.mobilewebprint.nan'
20 | }
21 |
22 | dependencies {
23 | implementation fileTree(dir: 'libs', include: ['*.jar'])
24 | implementation 'androidx.appcompat:appcompat:1.0.0'
25 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
26 | implementation 'com.google.android.material:material:1.0.0'
27 | implementation 'androidx.preference:preference:1.1.1'
28 | testImplementation 'junit:junit:4.12'
29 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WifiAware
2 |
3 | <<<<<<< HEAD
4 | Please use [DataTransfer Branch](https://github.com/anagramrice/NAN/tree/DataTransfer-feature) for android 11 API update (R)
5 | =======
6 | Helpful Links
7 |
8 | https://developer.android.com/reference/android/net/wifi/aware/package-summary
9 | https://developer.android.com/guide/topics/connectivity/wifi-aware
10 | https://source.android.com/devices/tech/connect/wifi-aware
11 |
12 |
13 | https://android.googlesource.com/platform/hardware/interfaces/+/master/wifi/1.2/README-NAN.md
14 | https://android.googlesource.com/platform/hardware/interfaces/+/master/wifi/1.2/default/
15 |
16 |
17 | https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/refs/heads/master/service/java/com/android/server/wifi/aware/
18 | https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/refs/heads/master/tests/wifitests/src/com/android/server/wifi/aware
19 |
20 |
21 |
22 | https://android.googlesource.com/kernel/msm-modules/qcacld/+/android-msm-crosshatch-4.9-pie-qpr1/core/
23 | wlan/qcacld-3.0/core/hdd/src/wlan_hdd_nan_datapath.c
24 | wlan/qcacld-3.0/core/mac/inc/sir_api.h
25 | wlan/qcacld-3.0/core/mac/src/pe/nan/nan_datapath.c
26 | wlan/qcacld-3.0/core/sme/inc/csr_api.h
27 | wlan/qcacld-3.0/core/sme/inc/sme_inside.h
28 | wlan/qcacld-3.0/core/sme/inc/sme_nan_datapath.h
29 | wlan/qcacld-3.0/core/sme/src/common/sme_api.c
30 | wlan/qcacld-3.0/core/sme/src/csr/csr_api_roam.c
31 | wlan/qcacld-3.0/core/sme/src/nan/nan_datapath_api.c
32 | wlan/qcacld-3.0/core/wma/src/wma_main.c
33 | wlan/qcacld-3.0/core/wma/src/wma_nan_datapath.c
34 | wlan/qcacld-3.0/core/wma/src/wma_nan_datapath.h
35 | wlan/fw-api/fw/wmi_tlv_defs.h
36 | wlan/fw-api/fw/wmi_unified.h
37 | >>>>>>> DataTransfer-feature
38 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | NAN
3 | Settings
4 | this is the status !!
5 | step 4
6 | step 3 req Net
7 | Publish
8 | Subscribe
9 | Send File
10 | IPv6 addr
11 | ipv6_address
12 | Have Session
13 | Mac
14 | Other MAC
15 | MessageToSend
16 | Messaging
17 | close
18 | SettingsActivity
19 |
20 |
21 | Service
22 | Security
23 |
24 | Publish Type
25 | Subscribe Type
26 | service_name
27 | service_specific_info
28 | encryption
29 | encrypt_type
30 |
31 | open (non-encrypted)
32 | pairwise master key (byte[] pmk)
33 | pre-shared key (String psk)
34 | security_pass
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/root_preferences.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
13 |
20 |
25 |
26 |
31 |
32 |
33 |
34 |
35 |
42 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
24 |
28 |
31 |
32 |
33 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/android,androidstudio
3 | # Edit at https://www.gitignore.io/?templates=android,androidstudio
4 |
5 | ### Android ###
6 | # Built application files
7 | *.apk
8 | *.ap_
9 | *.aab
10 |
11 | # Files for the ART/Dalvik VM
12 | *.dex
13 |
14 | # Java class files
15 | *.class
16 |
17 | # Generated files
18 | bin/
19 | gen/
20 | out/
21 |
22 | # Gradle files
23 | .gradle/
24 | build/
25 |
26 | # Local configuration file (sdk path, etc)
27 | local.properties
28 |
29 | # Proguard folder generated by Eclipse
30 | proguard/
31 |
32 | # Log Files
33 | *.log
34 |
35 | # Android Studio Navigation editor temp files
36 | .navigation/
37 |
38 | # Android Studio captures folder
39 | captures/
40 |
41 | # IntelliJ
42 | *.iml
43 | .idea/workspace.xml
44 | .idea/tasks.xml
45 | .idea/gradle.xml
46 | .idea/assetWizardSettings.xml
47 | .idea/dictionaries
48 | .idea/libraries
49 | .idea/caches
50 |
51 | .idea/
52 |
53 | # Keystore files
54 | # Uncomment the following lines if you do not want to check your keystore files in.
55 | #*.jks
56 | #*.keystore
57 |
58 | # External native build folder generated in Android Studio 2.2 and later
59 | .externalNativeBuild
60 |
61 | # Google Services (e.g. APIs or Firebase)
62 | google-services.json
63 |
64 | # Freeline
65 | freeline.py
66 | freeline/
67 | freeline_project_description.json
68 |
69 | # fastlane
70 | fastlane/report.xml
71 | fastlane/Preview.html
72 | fastlane/screenshots
73 | fastlane/test_output
74 | fastlane/readme.md
75 |
76 | ### Android Patch ###
77 | gen-external-apklibs
78 |
79 | ### AndroidStudio ###
80 | # Covers files to be ignored for android development using Android Studio.
81 |
82 | # Built application files
83 |
84 | # Files for the ART/Dalvik VM
85 |
86 | # Java class files
87 |
88 | # Generated files
89 |
90 | # Gradle files
91 | .gradle
92 |
93 | # Signing files
94 | .signing/
95 |
96 | # Local configuration file (sdk path, etc)
97 |
98 | # Proguard folder generated by Eclipse
99 |
100 | # Log Files
101 |
102 | # Android Studio
103 | /*/build/
104 | /*/local.properties
105 | /*/out
106 | /*/*/build
107 | /*/*/production
108 | *.ipr
109 | *~
110 | *.swp
111 |
112 | # Android Patch
113 |
114 | # External native build folder generated in Android Studio 2.2 and later
115 |
116 | # NDK
117 | obj/
118 |
119 | # IntelliJ IDEA
120 | *.iws
121 | /out/
122 |
123 | # User-specific configurations
124 | .idea/caches/
125 | .idea/libraries/
126 | .idea/shelf/
127 | .idea/.name
128 | .idea/compiler.xml
129 | .idea/copyright/profiles_settings.xml
130 | .idea/encodings.xml
131 | .idea/misc.xml
132 | .idea/modules.xml
133 | .idea/scopes/scope_settings.xml
134 | .idea/vcs.xml
135 | .idea/jsLibraryMappings.xml
136 | .idea/datasources.xml
137 | .idea/dataSources.ids
138 | .idea/sqlDataSources.xml
139 | .idea/dynamic.xml
140 | .idea/uiDesigner.xml
141 |
142 | # OS-specific files
143 | .DS_Store
144 | .DS_Store?
145 | ._*
146 | .Spotlight-V100
147 | .Trashes
148 | ehthumbs.db
149 | Thumbs.db
150 |
151 | # Legacy Eclipse project files
152 | .classpath
153 | .project
154 | .cproject
155 | .settings/
156 |
157 | # Mobile Tools for Java (J2ME)
158 | .mtj.tmp/
159 |
160 | # Package Files #
161 | *.war
162 | *.ear
163 |
164 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
165 | hs_err_pid*
166 |
167 | ## Plugin-specific files:
168 |
169 | # mpeltonen/sbt-idea plugin
170 | .idea_modules/
171 |
172 | # JIRA plugin
173 | atlassian-ide-plugin.xml
174 |
175 | # Mongo Explorer plugin
176 | .idea/mongoSettings.xml
177 |
178 | # Crashlytics plugin (for Android Studio and IntelliJ)
179 | com_crashlytics_export_strings.xml
180 | crashlytics.properties
181 | crashlytics-build.properties
182 | fabric.properties
183 |
184 | ### AndroidStudio Patch ###
185 |
186 | !/gradle/wrapper/gradle-wrapper.jar
187 |
188 | # End of https://www.gitignore.io/api/android,androidstudio
189 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
20 |
21 |
30 |
31 |
42 |
43 |
54 |
55 |
66 |
67 |
78 |
79 |
88 |
89 |
98 |
99 |
108 |
109 |
121 |
122 |
134 |
135 |
146 |
147 |
148 |
--------------------------------------------------------------------------------
/app/src/main/java/net/mobilewebprint/nan/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package net.mobilewebprint.nan;
2 |
3 | import android.content.SharedPreferences;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.MenuItem;
7 | import android.widget.Toast;
8 |
9 | import androidx.appcompat.app.ActionBar;
10 | import androidx.appcompat.app.AppCompatActivity;
11 | import androidx.core.app.NavUtils;
12 | import androidx.preference.EditTextPreference;
13 | import androidx.preference.ListPreference;
14 | import androidx.preference.Preference;
15 | import androidx.preference.PreferenceFragmentCompat;
16 | import androidx.preference.Preference.OnPreferenceChangeListener;
17 | import androidx.preference.PreferenceScreen;
18 |
19 | public class SettingsActivity extends AppCompatActivity {
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(R.layout.settings_activity);
25 | if (savedInstanceState == null) {
26 | getSupportFragmentManager()
27 | .beginTransaction()
28 | .replace(R.id.settings, new SettingsFragment())
29 | .commit();
30 | }
31 | ActionBar actionBar = getSupportActionBar();
32 | if (actionBar != null) {
33 | actionBar.setDisplayHomeAsUpEnabled(true);
34 | }
35 | }
36 |
37 | @Override
38 | public boolean onOptionsItemSelected(MenuItem item) {
39 | int id = item.getItemId();
40 | // When the home button is pressed, take the user back to the VisualizerActivity
41 | if (id == android.R.id.home) {
42 | NavUtils.navigateUpFromSameTask(this);
43 | }
44 | return super.onOptionsItemSelected(item);
45 | }
46 |
47 | public static class SettingsFragment extends PreferenceFragmentCompat implements
48 | SharedPreferences.OnSharedPreferenceChangeListener, OnPreferenceChangeListener {
49 | EditTextPreference passphrase;
50 | String currentEncryptType;
51 | @Override
52 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
53 | setPreferencesFromResource(R.xml.root_preferences, rootKey);
54 | SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
55 | SharedPreferences.Editor editor = sharedPreferences.edit();
56 | PreferenceScreen prefScreen = getPreferenceScreen();
57 | Preference name = findPreference(getString(R.string.service_name));
58 | Preference info = findPreference(getString(R.string.service_specific_info));
59 | Preference pass = findPreference(getString(R.string.security_pass));
60 | name.setOnPreferenceChangeListener(this);
61 | info.setOnPreferenceChangeListener(this);
62 | pass.setOnPreferenceChangeListener(this);
63 | }
64 |
65 | @Override
66 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
67 | // Figure out which preference was changed
68 | Preference preference = findPreference(key);
69 |
70 | String secType = getString(R.string.encryptType);
71 | String type = sharedPreferences.getString(key, "");
72 | if (key.equals(secType)) {
73 | if (type.equals("pmk")) {
74 | passphrase.setVisible(true);
75 | passphrase.setText("123456789abcdef0123456789abcdef0");
76 | } else if (type.equals("psk")) {
77 | passphrase.setVisible(true);
78 | passphrase.setText("12345678");
79 | } else {
80 | passphrase.setVisible(false);
81 | }
82 | }
83 | if (null != preference) {
84 | // Updates the summary for the preference
85 | if (!(preference instanceof EditTextPreference)) {
86 | String value = sharedPreferences.getString(preference.getKey(), "");
87 | }
88 | }
89 |
90 |
91 |
92 | }
93 |
94 | @Override
95 | public boolean onPreferenceChange(Preference preference, Object newValue) {
96 | Toast error = Toast.makeText(getContext(), "Please enter non empty string", Toast.LENGTH_LONG);
97 | String namekey = getString(R.string.service_name);
98 | String infokey = getString(R.string.service_specific_info);
99 | String passkey = getString(R.string.security_pass);
100 | if (preference.getKey().equals(namekey)||preference.getKey().equals(infokey)) {
101 | Log.d("prefs","IN HERE ");
102 | String name = (String) newValue;
103 | if (name.isEmpty()) {
104 | error.show();
105 | return false;
106 | }
107 | else
108 | return true;
109 | }
110 | return true;
111 | }
112 |
113 | /* private void setPreferenceSummary(Preference preference, String value) {
114 | if (preference instanceof ListPreference) {
115 | // For list preferences, figure out the label of the selected value
116 | ListPreference listPreference = (ListPreference) preference;
117 | int prefIndex = listPreference.findIndexOfValue(value);
118 | if (prefIndex >= 0) {
119 | // Set the summary to that label
120 | listPreference.setSummary(listPreference.getEntries()[prefIndex]);
121 | }
122 | } else if (preference instanceof EditTextPreference) {
123 | // For EditTextPreferences, set the summary to the value's simple string representation.
124 | preference.setSummary(value);
125 | }
126 | }*/
127 |
128 |
129 | @Override
130 | public void onCreate(Bundle savedInstanceState) {
131 | super.onCreate(savedInstanceState);
132 | getPreferenceScreen().getSharedPreferences()
133 | .registerOnSharedPreferenceChangeListener(this);
134 | String secType = getString(R.string.encryptType);
135 | passphrase = (EditTextPreference) getPreferenceManager().findPreference(getResources().getString(R.string.security_pass));
136 | currentEncryptType = getPreferenceManager().getSharedPreferences().getString(secType,"");
137 | Log.d("prefs","TYPE "+currentEncryptType);
138 | if (currentEncryptType.equals("open")){
139 | passphrase.setVisible(false);
140 | }
141 | else
142 | passphrase.setVisible(true);
143 | }
144 |
145 | @Override
146 | public void onDestroy() {
147 | super.onDestroy();
148 | getPreferenceScreen().getSharedPreferences()
149 | .unregisterOnSharedPreferenceChangeListener(this);
150 | }
151 | }
152 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/app/src/main/java/net/mobilewebprint/nan/MainActivity.java:
--------------------------------------------------------------------------------
1 | package net.mobilewebprint.nan;
2 |
3 |
4 | import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_128;
5 | import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128;
6 |
7 | import android.Manifest;
8 | import android.annotation.TargetApi;
9 | import android.content.BroadcastReceiver;
10 | import android.content.ContentUris;
11 | import android.content.ContentValues;
12 | import android.content.Context;
13 | import android.content.Intent;
14 | import android.content.IntentFilter;
15 | import android.content.SharedPreferences;
16 | import android.content.pm.PackageManager;
17 | import android.database.Cursor;
18 | import android.database.DatabaseUtils;
19 | import android.net.ConnectivityManager;
20 | import android.net.ConnectivityManager.NetworkCallback;
21 | import android.net.LinkProperties;
22 | import android.net.Network;
23 | import android.net.NetworkCapabilities;
24 | import android.net.NetworkRequest;
25 | import android.net.NetworkSpecifier;
26 | import android.net.Uri;
27 | import android.net.wifi.aware.AttachCallback;
28 | import android.net.wifi.aware.DiscoverySessionCallback;
29 | import android.net.wifi.aware.IdentityChangedListener;
30 | import android.net.wifi.aware.PeerHandle;
31 | import android.net.wifi.aware.PublishConfig;
32 | import android.net.wifi.aware.PublishDiscoverySession;
33 | import android.net.wifi.aware.SubscribeConfig;
34 | import android.net.wifi.aware.SubscribeDiscoverySession;
35 | import android.net.wifi.aware.WifiAwareManager;
36 | import android.net.wifi.aware.WifiAwareNetworkInfo;
37 | import android.net.wifi.aware.WifiAwareNetworkSpecifier;
38 | import android.net.wifi.aware.WifiAwareSession;
39 | import android.net.wifi.aware.WifiAwareDataPathSecurityConfig;
40 | import android.os.Build;
41 | import android.os.Bundle;
42 |
43 | import androidx.annotation.NonNull;
44 |
45 | import com.google.android.material.floatingactionbutton.FloatingActionButton;
46 | import com.google.android.material.snackbar.Snackbar;
47 |
48 | import androidx.annotation.RequiresApi;
49 | import androidx.core.app.ActivityCompat;
50 | import androidx.appcompat.app.AppCompatActivity;
51 | import androidx.appcompat.widget.Toolbar;
52 | import androidx.preference.EditTextPreference;
53 | import androidx.preference.PreferenceManager;
54 |
55 | import android.os.Environment;
56 | import android.provider.MediaStore;
57 | import android.provider.OpenableColumns;
58 | import android.util.Log;
59 | import android.view.View;
60 | import android.view.Menu;
61 | import android.view.MenuItem;
62 | import android.widget.Button;
63 | import android.widget.CheckBox;
64 | import android.widget.EditText;
65 | import android.widget.TextView;
66 | import android.widget.Toast;
67 |
68 | import java.io.*;
69 | import java.lang.Thread;
70 | import java.lang.Runnable;
71 | import java.net.SocketException;
72 | import java.net.InetAddress;
73 | import java.net.Inet6Address;
74 | import java.net.NetworkInterface;
75 | import java.net.Socket;
76 | import java.net.ServerSocket;
77 | import java.net.UnknownHostException;
78 | import java.util.Enumeration;
79 | import java.util.List;
80 | import java.util.Map;
81 |
82 |
83 | /*
84 | * Note: as it stands, to run, do the following:
85 | *
86 | * 1. On Pixel #1, run the NAN app, and click the PUBLISH button.
87 | * 2. On Pixel #2, run the NAN app, and click the SUBSCRIBE button.
88 | * -- There is a slight delay. Wait until both have 2 MAC addresses.
89 | *
90 | * Unfortunately, requestNetwork does not get any callbacks.
91 | *
92 | */
93 |
94 | public class MainActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
95 |
96 | private final int MAC_ADDRESS_MESSAGE = 55;
97 | private static final int MY_PERMISSION_FINE_LOCATION_REQUEST_CODE = 88;
98 | private static final int MY_PERMISSION_BACKGROUND_LOCATION_REQUEST_CODE = 66;
99 | // private final String SERVICE_NAME = "org.wifi.nan.test";
100 |
101 | private BroadcastReceiver broadcastReceiver;
102 | private WifiAwareManager wifiAwareManager;
103 | private ConnectivityManager connectivityManager;
104 | private WifiAwareSession wifiAwareSession;
105 | private NetworkSpecifier networkSpecifier;
106 |
107 | private WifiAwareDataPathSecurityConfig secConfig;
108 | private PublishDiscoverySession publishDiscoverySession;
109 | private SubscribeDiscoverySession subscribeDiscoverySession;
110 | private PeerHandle peerHandle;
111 | private byte[] myMac;
112 | private byte[] otherMac;
113 |
114 | private int pubType;
115 | private int subType;
116 | private String EncryptType;
117 | private String SERVICE_NAME;
118 | private byte[] serviceInfo;
119 | private byte[] pmk;
120 | private byte[] pmkid = new byte[16];
121 | private String psk;
122 |
123 | private final int IP_ADDRESS_MESSAGE = 33;
124 | private final int MESSAGE = 7;
125 | private static final int MY_PERMISSION_EXTERNAL_REQUEST_CODE = 99;
126 | private static final int MY_PERMISSION_EXTERNAL_READ_REQUEST_CODE = 98;
127 | private static final int MY_PERMISSION_NEARBY_WIFI_DEV = 86;
128 | private Inet6Address ipv6;
129 | private ServerSocket serverSocket;
130 | private Inet6Address peerIpv6;
131 | private int peerPort;
132 | // private final byte[] serviceInfo = "android".getBytes();
133 | // private final byte[] pmk = "123456789abcdef0123456789abcdef0".getBytes();
134 | private byte[] portOnSystem;
135 | private int portToUse;
136 | private byte[] myIP;
137 | private byte[] otherIP;
138 | private byte[] msgtosend;
139 |
140 |
141 | @Override
142 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
143 | if (key.equals(getString(R.string.service_name))) {
144 | SERVICE_NAME = sharedPreferences.getString(getResources().getString(R.string.service_name), "org.wifi.nan.test");
145 | Log.d("prefs", "service Name updated to: " + SERVICE_NAME);
146 | } else if (key.equals(getString(R.string.service_specific_info))) {
147 | serviceInfo = sharedPreferences.getString(getResources().getString(R.string.service_specific_info), "android").getBytes();
148 | Log.d("prefs", "service info updated to: " + new String(serviceInfo));
149 | } else if (key.equals(getString(R.string.encryptType))) {
150 | EncryptType = sharedPreferences.getString(getResources().getString(R.string.encryptType), "open");
151 | } else if (key.equals(getString(R.string.pubType))) {
152 | String type = sharedPreferences.getString(getResources().getString(R.string.pubType), "unsolicited");
153 | if (type.equals("unsolicited")) {
154 | pubType = PublishConfig.PUBLISH_TYPE_UNSOLICITED;
155 | Log.d("prefs", "updated pubtype : " + type);
156 | } else {
157 | pubType = PublishConfig.PUBLISH_TYPE_SOLICITED;
158 | Log.d("prefs", "updated pubtype : " + type);
159 | }
160 |
161 | } else if (key.equals(getString(R.string.subType))) {
162 | String type = sharedPreferences.getString(getResources().getString(R.string.subType), "passive");
163 | if (type.equals("passive")) {
164 | subType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE;
165 | Log.d("prefs", "updated subtype: " + type);
166 | } else {
167 | subType = SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE;
168 | Log.d("prefs", "updated subtype: " + type);
169 | }
170 | }
171 | try {
172 | if (EncryptType.equals("pmk")) {
173 | pmk = sharedPreferences.getString(getResources().getString(R.string.security_pass), "123456789abcdef0123456789abcdef0").getBytes();
174 | Log.d("prefs", "pmk " + new String(pmk));
175 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
176 | secConfig = new WifiAwareDataPathSecurityConfig.Builder(WIFI_AWARE_CIPHER_SUITE_NCS_PK_128)
177 | .setPmk(pmk)
178 | .setPmkId(pmkid)
179 | .build();
180 | }
181 | } else if (EncryptType.equals("psk")) {
182 | psk = sharedPreferences.getString(getResources().getString(R.string.security_pass), "12345678");
183 | Log.d("prefs", "psk " + psk);
184 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
185 | secConfig = new WifiAwareDataPathSecurityConfig.Builder(WIFI_AWARE_CIPHER_SUITE_NCS_PK_128)
186 | .setPskPassphrase(psk)
187 | .build();
188 | }
189 | }
190 | } catch (NullPointerException e) {
191 | Log.e("prefs", e.toString());
192 | }
193 |
194 | }
195 |
196 | private void setupSharedPreferences() {
197 | // Get all of the values from shared preferences to set it up
198 | SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
199 | Map keys = sharedPreferences.getAll();
200 |
201 | for (Map.Entry entry : keys.entrySet()) {
202 | Log.d("map values", entry.getKey() + ": " +
203 | entry.getValue().toString());
204 | if (entry.getKey().equals(getResources().getString(R.string.service_name))) {
205 | SERVICE_NAME = entry.getValue().toString();
206 | Log.d("prefs", "service Name set " + entry.getValue().toString());
207 | }
208 | if (entry.getKey().equals(getResources().getString(R.string.service_specific_info))) {
209 | serviceInfo = entry.getValue().toString().getBytes();
210 | Log.d("prefs", "service info set " + entry.getValue().toString());
211 | }
212 | if (entry.getKey().equals(getResources().getString(R.string.encryptType))) {
213 | EncryptType = entry.getValue().toString();
214 | }
215 | if (entry.getKey().equals(getResources().getString(R.string.pubType))) {
216 | if (entry.getValue().toString().equals("unsolicited")) {
217 | pubType = PublishConfig.PUBLISH_TYPE_UNSOLICITED;
218 | Log.d("prefs", "pubtype unsolict: " + pubType);
219 | } else {
220 | pubType = PublishConfig.PUBLISH_TYPE_SOLICITED;
221 | Log.d("prefs", "pubtype solicit: " + pubType);
222 | }
223 | }
224 | if (entry.getKey().equals(getResources().getString(R.string.subType))) {
225 | if (entry.getValue().toString().equals("passive")) {
226 | subType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE;
227 | Log.d("prefs", "updated subtype: " + subType);
228 | } else {
229 | subType = SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE;
230 | Log.d("prefs", "updated subtype: " + subType);
231 | }
232 | }
233 | }
234 | try {
235 | if (EncryptType.equals("pmk")) {
236 | pmk = sharedPreferences.getString(getResources().getString(R.string.security_pass), "123456789abcdef0123456789abcdef0").getBytes();
237 | Log.d("prefs", "pmk " + new String(pmk));
238 | } else if (EncryptType.equals("psk")) {
239 | psk = sharedPreferences.getString(getResources().getString(R.string.security_pass), "12345678");
240 | Log.d("prefs", "psk " + psk);
241 | }
242 | } catch (java.lang.NullPointerException e) {
243 | Log.e("prefs", e.toString());
244 | }
245 |
246 |
247 | // Register the listener
248 | sharedPreferences.registerOnSharedPreferenceChangeListener(this);
249 | }
250 |
251 | /**
252 | * Handles initialization (creation) of the activity.
253 | *
254 | * @param savedInstanceState
255 | */
256 | @Override
257 | @TargetApi(26)
258 | protected void onCreate(Bundle savedInstanceState) {
259 | super.onCreate(savedInstanceState);
260 |
261 | wifiAwareManager = null;
262 | wifiAwareSession = null;
263 | connectivityManager = null;
264 | networkSpecifier = null;
265 | publishDiscoverySession = null;
266 | subscribeDiscoverySession = null;
267 | peerHandle = null;
268 |
269 | //Log.d("myTag","Supported Aware: " + getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE));
270 | setupSharedPreferences();
271 | setupPermissions();
272 | setContentView(R.layout.activity_main);
273 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
274 | setSupportActionBar(toolbar);
275 |
276 | //------------------------------------------------------------------------------------------------------
277 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.sendmsgfab); /* +++++ */
278 | fab.setOnClickListener(new View.OnClickListener() {
279 | @Override
280 | public void onClick(View view) {
281 | String msg = "messageToBeSent: ";
282 | EditText editText = (EditText) findViewById(R.id.msgtext);
283 | msg += editText.getText().toString();
284 | msgtosend = msg.getBytes();
285 | if (publishDiscoverySession != null && peerHandle != null) {
286 | publishDiscoverySession.sendMessage(peerHandle, MESSAGE, msgtosend);
287 | } else if (subscribeDiscoverySession != null && peerHandle != null) {
288 | subscribeDiscoverySession.sendMessage(peerHandle, MESSAGE, msgtosend);
289 | }
290 | }
291 | }); /* ----- */
292 | //------------------------------------------------------------------------------------------------------
293 |
294 | //------------------------------------------------------------------------------------------------------
295 | Button statusButton = (Button) findViewById(R.id.statusbtn); /* +++++ */
296 | statusButton.setOnClickListener(new View.OnClickListener() {
297 | @Override
298 | public void onClick(View view) {
299 | if (publishDiscoverySession != null && peerHandle != null) {
300 | //publishDiscoverySession.sendMessage(peerHandle, MAC_ADDRESS_MESSAGE, myMac);
301 | Snackbar.make(view, "publisher req met", Snackbar.LENGTH_LONG)
302 | .setAction("Action", null).show();
303 | Button responderButton = (Button) findViewById(R.id.responderButton);
304 | responderButton.setEnabled(true);
305 |
306 | } else if (subscribeDiscoverySession != null && peerHandle != null) {
307 | Snackbar.make(view, "subscriber req met", Snackbar.LENGTH_LONG)
308 | .setAction("Action", null).show();
309 | Button initiatorButton = (Button) findViewById(R.id.initiatorButton);
310 | initiatorButton.setEnabled(true);
311 | } else if (peerHandle == null) {
312 | Snackbar.make(view, "no peerHandle", Snackbar.LENGTH_LONG)
313 | .setAction("Action", null).show();
314 | } else {
315 | Snackbar.make(view, "no DiscoverySession", Snackbar.LENGTH_LONG)
316 | .setAction("Action", null).show();
317 | }
318 | }
319 | }); /* ----- */
320 | //------------------------------------------------------------------------------------------------------
321 |
322 | Button publishButton = (Button) findViewById(R.id.publishButton);
323 | publishButton.setOnClickListener(new View.OnClickListener() {
324 | @Override
325 | public void onClick(View v) {
326 | publishService();
327 | setStatus("NAN available: Device is Publisher \n--> click responder for connection");
328 | }
329 | });
330 |
331 | Button subscribeButton = (Button) findViewById(R.id.subscribeButton);
332 | subscribeButton.setOnClickListener(new View.OnClickListener() {
333 | @Override
334 | public void onClick(View v) {
335 | subscribeToService();
336 | setStatus("NAN available: Device is Subscriber \n--> click initiator for connection");
337 | }
338 | });
339 |
340 | Button initiatorButton = (Button) findViewById(R.id.initiatorButton);
341 | initiatorButton.setOnClickListener(new View.OnClickListener() {
342 | @RequiresApi(api = Build.VERSION_CODES.Q)
343 | @Override
344 | public void onClick(View v) {
345 | Log.d("myTag", "initiating subscribeSession " + EncryptType);
346 | //networkSpecifier = wifiAwareSession.createNetworkSpecifierOpen(WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, otherMac);
347 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
348 | if (EncryptType.equals("open")) {
349 | networkSpecifier = new WifiAwareNetworkSpecifier.Builder(subscribeDiscoverySession, peerHandle)
350 | .build();
351 | } else if (EncryptType.equals("pmk")) {
352 | networkSpecifier = new WifiAwareNetworkSpecifier.Builder(subscribeDiscoverySession, peerHandle)
353 | .setPmk(pmk)
354 | .build();
355 | } else if (EncryptType.equals("psk")) {
356 | networkSpecifier = new WifiAwareNetworkSpecifier.Builder(subscribeDiscoverySession, peerHandle)
357 | .setPskPassphrase(psk)
358 | .build();
359 | }
360 | }
361 |
362 | Log.d("myTag", "Initiator button clicked ");
363 | setStatus("NAN initiator: subscriber networkSpecifier created");
364 | requestNetwork();
365 | }
366 | });
367 |
368 | //-------------------------------------------------------------------------------------------- +++++
369 | Button responderButton = (Button) findViewById(R.id.responderButton);
370 | responderButton.setOnClickListener(new View.OnClickListener() {
371 | @RequiresApi(api = Build.VERSION_CODES.Q)
372 | @Override
373 | public void onClick(View v) {
374 | Log.d("step3 Responder", "starting dataSession " + EncryptType);
375 | //networkSpecifier = wifiAwareSession.createNetworkSpecifierOpen(WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, otherMac);
376 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
377 | if (EncryptType.equals("open")) {
378 | networkSpecifier = new WifiAwareNetworkSpecifier.Builder(publishDiscoverySession, peerHandle)
379 | .build();
380 | portOnSystem = portToBytes(serverSocket.getLocalPort());
381 | Log.d("step3 Responder", "server port sending OTA");
382 | if (publishDiscoverySession != null && peerHandle != null) {
383 | publishDiscoverySession.sendMessage(peerHandle, MAC_ADDRESS_MESSAGE, portOnSystem);
384 | Log.d("step3 Responder", "pub_sess");
385 | } else if (subscribeDiscoverySession != null && peerHandle != null) {
386 | subscribeDiscoverySession.sendMessage(peerHandle, MAC_ADDRESS_MESSAGE, portOnSystem);
387 | Log.d("step3 Responder", "dis_sess");
388 | }
389 | } else if (EncryptType.equals("pmk")) {
390 | try {
391 | networkSpecifier = new WifiAwareNetworkSpecifier.Builder(publishDiscoverySession, peerHandle)
392 | .setPmk(pmk)
393 | .setPort(portToUse)
394 | .build();
395 | } catch (Exception e) {
396 | Log.e("step3 Responder", e.toString());
397 | Log.d("step3 Responder", publishDiscoverySession.toString() + peerHandle.toString());
398 | }
399 |
400 | } else if (EncryptType.equals("psk")) {
401 | try {
402 | networkSpecifier = new WifiAwareNetworkSpecifier.Builder(publishDiscoverySession, peerHandle)
403 | .setPskPassphrase(psk)
404 | .setPort(portToUse)
405 | .build();
406 | } catch (Exception e) {
407 | Log.e("step3 Responder", e.toString());
408 | Log.d("step3 Responder", publishDiscoverySession.toString() + peerHandle.toString());
409 | }
410 |
411 | }
412 | }
413 | ;
414 | Log.d("myTag", "Responder button clicked \"");
415 | setStatus("NAN publisher: Responder networkSpecifier created");
416 | requestNetwork(); /* */
417 | }
418 | });
419 | //-------------------------------------------------------------------------------------------- -----
420 |
421 | //-------------------------------------------------------------------------------------------- +++++
422 | Button sendFileButton = (Button) findViewById(R.id.sendbtn);
423 | sendFileButton.setOnClickListener(new View.OnClickListener() {
424 | @Override
425 | public void onClick(View v) {
426 | try {
427 | if (EncryptType.equals("open")) {
428 | Toast.makeText(MainActivity.this, "Sending to port: " + portToUse, Toast.LENGTH_SHORT).show();
429 | Log.d("myTag", "sending to " + portToUse + "\t" + peerIpv6.getScopedInterface().getDisplayName());
430 | clientSendFile(Inet6Address.getByAddress("WifiAwareHost", otherIP, peerIpv6.getScopedInterface()), portToUse);
431 | } else {
432 | Toast.makeText(MainActivity.this, "Sending to port: " + peerPort, Toast.LENGTH_SHORT).show();
433 | Log.d("myTag", "sending to " + peerPort + "\t" + peerIpv6.getScopedInterface().getDisplayName());
434 | clientSendFile(Inet6Address.getByAddress("WifiAwareHost", otherIP, peerIpv6.getScopedInterface()), peerPort);
435 | }
436 |
437 | } catch (UnknownHostException e) {
438 | Log.d("sendFileError", "exception " + e.toString());
439 | }
440 |
441 | //TODO: spin up client and send to server
442 | }
443 | });
444 | //-------------------------------------------------------------------------------------------- -----
445 |
446 | connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
447 |
448 | setHaveSession(false);
449 |
450 | setStatus("starting...");
451 |
452 | String status = null;
453 | boolean hasNan = false;
454 |
455 | PackageManager packageManager = getPackageManager();
456 | if (packageManager == null) {
457 | status = "Cannot get PackageManager";
458 | } else {
459 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
460 | hasNan = packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
461 | }
462 | }
463 |
464 | if (!hasNan) {
465 | status = "Device does not have NAN";
466 | } else {
467 |
468 | wifiAwareManager = (WifiAwareManager) getSystemService(Context.WIFI_AWARE_SERVICE);
469 |
470 | if (wifiAwareManager == null) {
471 | status = "Cannot get WifiAwareManager";
472 | }
473 | }
474 |
475 | setStatus(status);
476 | }
477 |
478 | /**
479 | * App Permissions for Fine Location
480 | **/
481 | private void setupPermissions() {
482 | // If we don't have the record network permission...
483 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
484 | // And if we're on SDK M or later...
485 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
486 | // Ask again, nicely, for the permissions.
487 | String[] permissionsWeNeed = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
488 | requestPermissions(permissionsWeNeed, MY_PERMISSION_FINE_LOCATION_REQUEST_CODE);
489 | }
490 | }
491 |
492 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.NEARBY_WIFI_DEVICES) != PackageManager.PERMISSION_GRANTED) {
493 | // And if we're on SDK M or later...
494 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
495 | // Ask again, nicely, for the permissions.
496 | String[] permissionsWeNeed = new String[]{Manifest.permission.NEARBY_WIFI_DEVICES};
497 | requestPermissions(permissionsWeNeed, MY_PERMISSION_NEARBY_WIFI_DEV);
498 |
499 | return;
500 | }
501 | }
502 | /* if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
503 | // And if we're on SDK M or later...
504 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
505 | // Ask again, nicely, for the permissions.
506 | String[] permissionsWeNeed = new String[]{ Manifest.permission.ACCESS_BACKGROUND_LOCATION };
507 | requestPermissions(permissionsWeNeed, MY_PERMISSION_BACKGROUND_LOCATION_REQUEST_CODE);
508 | }
509 | }*/
510 |
511 | //-------------------------------------------------------------------------------------------- +++++
512 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
513 | // And if we're on SDK M or later...
514 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
515 | // Ask again, nicely, for the permissions.
516 | String[] permissionsWeNeed = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
517 | requestPermissions(permissionsWeNeed, MY_PERMISSION_EXTERNAL_REQUEST_CODE);
518 | }
519 | }
520 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
521 | // And if we're on SDK M or later...
522 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
523 | // Ask again, nicely, for the permissions.
524 | String[] permissionsWeNeed = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE};
525 | requestPermissions(permissionsWeNeed, MY_PERMISSION_EXTERNAL_READ_REQUEST_CODE);
526 | }
527 | }
528 | //-------------------------------------------------------------------------------------------- -----
529 | }
530 |
531 | @Override
532 | public void onRequestPermissionsResult(int requestCode,
533 | @NonNull String permissions[], @NonNull int[] grantResults) {
534 | switch (requestCode) {
535 | case MY_PERMISSION_FINE_LOCATION_REQUEST_CODE: {
536 | // If request is cancelled, the result arrays are empty.
537 | if (grantResults.length > 0
538 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
539 | return;
540 |
541 | } else {
542 | Toast.makeText(this, "Permission for location not granted. NAN can't run.", Toast.LENGTH_LONG).show();
543 | finish();
544 | // The permission was denied, so we can show a message why we can't run the app
545 | // and then close the app.
546 | }
547 | }
548 | case MY_PERMISSION_NEARBY_WIFI_DEV: {
549 | // If request is cancelled, the result arrays are empty.
550 | if (grantResults.length > 0
551 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
552 | return;
553 |
554 | } else {
555 | Toast.makeText(this, "Permission for nearby wifi devices. NAN can't run.", Toast.LENGTH_LONG).show();
556 | finish();
557 | // The permission was denied, so we can show a message why we can't run the app
558 | // and then close the app.
559 | }
560 | }
561 | /* case MY_PERMISSION_BACKGROUND_LOCATION_REQUEST_CODE: {
562 | // If request is cancelled, the result arrays are empty.
563 | if (grantResults.length > 0
564 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
565 | return;
566 |
567 | } else {
568 | Toast.makeText(this, "Permission for background location not granted.", Toast.LENGTH_LONG).show();
569 | // and then close the app.
570 | }
571 | }*/
572 | //-------------------------------------------------------------------------------------------- +++++
573 | case MY_PERMISSION_EXTERNAL_REQUEST_CODE: {
574 | // If request is cancelled, the result arrays are empty.
575 | if (grantResults.length > 0
576 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
577 | return;
578 |
579 | } else {
580 | Toast.makeText(this, "no sd card access", Toast.LENGTH_LONG).show();
581 | }
582 | }
583 | case MY_PERMISSION_EXTERNAL_READ_REQUEST_CODE: {
584 | // If request is cancelled, the result arrays are empty.
585 | if (grantResults.length > 0
586 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
587 | return;
588 |
589 | } else {
590 | Toast.makeText(this, "no sd card access", Toast.LENGTH_LONG).show();
591 | }
592 | }
593 | //-------------------------------------------------------------------------------------------- -----
594 | // Other permissions could go down here
595 |
596 | }
597 | }
598 |
599 | @TargetApi(26)
600 | private void requestNetwork() {
601 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
602 | return;
603 | }
604 |
605 | if (networkSpecifier == null) {
606 | Log.d("myTag", "No NetworkSpecifier Created ");
607 | return;
608 | }
609 | Log.d("myTag", "building network interface");
610 | Log.d("myTag", "using networkspecifier: " + networkSpecifier.toString());
611 | NetworkRequest networkRequest = new NetworkRequest.Builder()
612 | .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
613 | .setNetworkSpecifier(networkSpecifier)
614 | .build();
615 |
616 | Log.d("myTag", "finish building network interface");
617 | connectivityManager.requestNetwork(networkRequest, new NetworkCallback() {
618 | @Override
619 | public void onAvailable(Network network) {
620 | super.onAvailable(network);
621 | Log.d("myTag", "Network Available: " + network.toString());
622 | }
623 |
624 | @Override
625 | public void onLosing(Network network, int maxMsToLive) {
626 | super.onLosing(network, maxMsToLive);
627 | Log.d("myTag", "losing Network");
628 | }
629 |
630 | @Override
631 | public void onLost(Network network) {
632 | super.onLost(network);
633 | Toast.makeText(MainActivity.this, "lost network", Toast.LENGTH_LONG).show();
634 | Log.d("myTag", "Lost Network");
635 | }
636 |
637 | @Override
638 | public void onUnavailable() {
639 | super.onUnavailable();
640 | Toast.makeText(MainActivity.this, "onUnavailable", Toast.LENGTH_SHORT).show();
641 | Log.d("myTag", "entering onUnavailable ");
642 | }
643 |
644 | @RequiresApi(api = Build.VERSION_CODES.Q)
645 | @Override
646 | public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
647 | super.onCapabilitiesChanged(network, networkCapabilities);
648 | Toast.makeText(MainActivity.this, "onCapabilitiesChanged", Toast.LENGTH_SHORT).show();
649 | WifiAwareNetworkInfo peerAwareInfo = (WifiAwareNetworkInfo) networkCapabilities.getTransportInfo();
650 | peerIpv6 = peerAwareInfo.getPeerIpv6Addr();
651 | peerPort = peerAwareInfo.getPort();
652 | Log.d("myTag", "entering onCapabilitiesChanged ");
653 | setStatus("Ready for file transfer\nSend File when both IPv6 shown");
654 | }
655 |
656 | //-------------------------------------------------------------------------------------------- +++++
657 | @Override
658 | public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
659 | super.onLinkPropertiesChanged(network, linkProperties);
660 | //TODO: create socketServer on different thread to transfer files
661 | Toast.makeText(MainActivity.this, "onLinkPropertiesChanged", Toast.LENGTH_SHORT).show();
662 | Log.d("myTag", "entering linkPropertiesChanged ");
663 | try {
664 | //Log.d("myTag", "iface name: " + linkProperties.getInterfaceName());
665 | //Log.d("myTag", "iface link addr: " + linkProperties.getLinkAddresses());
666 |
667 | NetworkInterface awareNi = NetworkInterface.getByName(
668 | linkProperties.getInterfaceName());
669 | /*Inet6Address ipv6 = null;
670 | Enumeration ifcs = NetworkInterface.getNetworkInterfaces();
671 | while (ifcs.hasMoreElements()) {
672 | NetworkInterface iface = ifcs.nextElement();
673 | Log.d("myTag", "iface: " + iface.toString());
674 | }*/
675 |
676 | Enumeration Addresses = awareNi.getInetAddresses();
677 | while (Addresses.hasMoreElements()) {
678 | InetAddress addr = Addresses.nextElement();
679 | if (addr instanceof Inet6Address) {
680 | Log.d("myTag", "netinterface ipv6 address: " + addr.toString());
681 | if (((Inet6Address) addr).isLinkLocalAddress()) {
682 | ipv6 = Inet6Address.getByAddress("WifiAware", addr.getAddress(), awareNi);
683 | myIP = addr.getAddress();
684 | if (publishDiscoverySession != null && peerHandle != null) {
685 | publishDiscoverySession.sendMessage(peerHandle, IP_ADDRESS_MESSAGE, myIP);
686 | } else if (subscribeDiscoverySession != null && peerHandle != null) {
687 | subscribeDiscoverySession.sendMessage(peerHandle, IP_ADDRESS_MESSAGE, myIP);
688 | }
689 | break;
690 | }
691 | }
692 | }
693 | } catch (SocketException e) {
694 | Log.d("myTag", "socket exception " + e.toString());
695 | } catch (Exception e) {
696 | //EXCEPTION!!! java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Enumeration java.net.NetworkInterface.getInetAddresses()' on a null object reference
697 | Log.d("myTag", "EXCEPTION!!! " + e.toString());
698 | }
699 | //startServer(0,3,ipv6);
700 | // should be done in a separate thread
701 | /*
702 | startServer
703 | ServerSocket ss = new ServerSocket(0, 5, ipv6);
704 | int port = ss.getLocalPort(); */
705 | //TODO: need to send this port via messages to other device to finish client conn info
706 |
707 | // should be done in a separate thread
708 | // obtain server IPv6 and port number out-of-band
709 | //TODO: Retrieve address:port IPv6 before this client thread can be created
710 | /*
711 | Socket cs = network.getSocketFactory().createSocket(serverIpv6, serverPort); */
712 | }
713 | //-------------------------------------------------------------------------------------------- -----
714 |
715 | });
716 | }
717 |
718 | /**
719 | * Resuming activity
720 | *
721 | */
722 | @Override
723 | @TargetApi(26)
724 | protected void onResume() {
725 | super.onResume();
726 |
727 | String status = null;
728 | Log.d("myTag", "Current phone build" + Build.VERSION.SDK_INT + "\tMinimum:" + Build.VERSION_CODES.O);
729 | Log.d("myTag", "Supported Aware: " + getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE));
730 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
731 | Log.d("myTag", "Entering OnResume is executed");
732 | IntentFilter filter = new IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED);
733 | broadcastReceiver = new BroadcastReceiver() {
734 | @Override
735 | public void onReceive(Context context, Intent intent) {
736 | String status = "";
737 | wifiAwareManager.getCharacteristics();
738 | boolean nanAvailable = wifiAwareManager.isAvailable();
739 | Log.d("myTag", "NAN is available");
740 | if (nanAvailable) {
741 | attachToNanSession();
742 | status = "NAN has become Available";
743 | Log.d("myTag", "NAN attached");
744 | } else {
745 | status = "NAN has become Unavailable";
746 | Log.d("myTag", "NAN unavailable");
747 | }
748 |
749 | setStatus(status);
750 | }
751 | };
752 |
753 | getApplicationContext().registerReceiver(broadcastReceiver, filter);
754 |
755 | boolean nanAvailable = wifiAwareManager.isAvailable();
756 | if (nanAvailable) {
757 | attachToNanSession();
758 | status = "NAN is Available";
759 | } else {
760 | status = "NAN is Unavailable";
761 | }
762 | } else {
763 | status = "NAN is only supported in O+";
764 | }
765 |
766 | setStatus(status);
767 | }
768 |
769 | /**
770 | * Handles attaching to NAN session.
771 | *
772 | */
773 | @TargetApi(26)
774 | private void attachToNanSession() {
775 |
776 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
777 | return;
778 | }
779 |
780 | // Only once
781 | if (wifiAwareSession != null) {
782 | return;
783 | }
784 |
785 | if (wifiAwareManager == null || !wifiAwareManager.isAvailable()) {
786 | setStatus("NAN is Unavailable in attach");
787 | return;
788 | }
789 |
790 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.NEARBY_WIFI_DEVICES) != PackageManager.PERMISSION_GRANTED) {
791 | // TODO: Consider calling
792 | // ActivityCompat#requestPermissions
793 | // here to request the missing permissions, and then overriding
794 | // public void onRequestPermissionsResult(int requestCode, String[] permissions,
795 | // int[] grantResults)
796 | // to handle the case where the user grants the permission. See the documentation
797 | // for ActivityCompat#requestPermissions for more details.
798 | return;
799 | }
800 | wifiAwareManager.attach(new AttachCallback() {
801 | @Override
802 | public void onAttached(WifiAwareSession session) {
803 | super.onAttached(session);
804 |
805 | closeSession();
806 | wifiAwareSession = session;
807 | setHaveSession(true);
808 | }
809 |
810 | @Override
811 | public void onAttachFailed() {
812 | super.onAttachFailed();
813 | setHaveSession(false);
814 | setStatus("attach() failed.");
815 | }
816 |
817 | }, new IdentityChangedListener() {
818 | @Override
819 | public void onIdentityChanged(byte[] mac) {
820 | super.onIdentityChanged(mac);
821 | setMacAddress(mac);
822 | }
823 | }, null);
824 | }
825 |
826 | @TargetApi(26)
827 | private void publishService() {
828 | PublishConfig config;
829 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
830 | return;
831 | }
832 | Log.d("nanPUBLISH", "building publish session " + SERVICE_NAME);
833 |
834 | if (pubType == PublishConfig.PUBLISH_TYPE_UNSOLICITED)
835 | Log.d("nanPUBLISH", "publish unsolicited " + pubType);
836 | else if (pubType == PublishConfig.PUBLISH_TYPE_SOLICITED)
837 | Log.d("nanPUBLISH", "publish solicited " + pubType);
838 | if (!EncryptType.equals("open") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
839 | if (EncryptType.equals("pmk")) {
840 | Log.d("prefs", "pmk " + new String(pmk));
841 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
842 | secConfig = new WifiAwareDataPathSecurityConfig.Builder(WIFI_AWARE_CIPHER_SUITE_NCS_SK_128)
843 | .setPmk(pmk)
844 | // .setPmkId(pmkid)
845 | .build();
846 | }
847 | } else if (EncryptType.equals("psk")) {
848 | Log.d("prefs", "psk " + psk);
849 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
850 | secConfig = new WifiAwareDataPathSecurityConfig.Builder(WIFI_AWARE_CIPHER_SUITE_NCS_SK_128)
851 | .setPskPassphrase(psk)
852 | .build();
853 | }
854 | }
855 | config = new PublishConfig.Builder()
856 | .setServiceName(SERVICE_NAME)
857 | .setServiceSpecificInfo(serviceInfo)
858 | .setDataPathSecurityConfig(secConfig)
859 | .setPublishType(pubType)
860 | .build();
861 | } else {
862 | config = new PublishConfig.Builder()
863 | .setServiceName(SERVICE_NAME)
864 | .setServiceSpecificInfo(serviceInfo)
865 | .setPublishType(pubType)
866 | .build();
867 | }
868 |
869 |
870 | //-------------------------------------------------------------------------------------------- +++++
871 | Log.d("nanPUBLISH", "build finish");
872 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.NEARBY_WIFI_DEVICES) != PackageManager.PERMISSION_GRANTED) {
873 | // TODO: Consider calling
874 | // ActivityCompat#requestPermissions
875 | // here to request the missing permissions, and then overriding
876 | // public void onRequestPermissionsResult(int requestCode, String[] permissions,
877 | // int[] grantResults)
878 | // to handle the case where the user grants the permission. See the documentation
879 | // for ActivityCompat#requestPermissions for more details.
880 | return;
881 | }
882 | wifiAwareSession.publish(config, new DiscoverySessionCallback() {
883 | @Override
884 | public void onPublishStarted(@NonNull PublishDiscoverySession session) {
885 | super.onPublishStarted(session);
886 |
887 | publishDiscoverySession = session;
888 | startServer(0, 3);
889 | Button sendBtn = (Button) findViewById(R.id.sendbtn);
890 | sendBtn.setEnabled(false);
891 | Button responderButton = (Button) findViewById(R.id.responderButton);
892 | responderButton.setEnabled(true);
893 | if (publishDiscoverySession != null && peerHandle != null) {
894 | publishDiscoverySession.sendMessage(peerHandle, MAC_ADDRESS_MESSAGE, myMac);
895 | Log.d("nanPUBLISH", "onPublishStarted sending mac");
896 |
897 | Button initiatorButton = (Button) findViewById(R.id.initiatorButton);
898 | initiatorButton.setEnabled(false);
899 |
900 | }
901 | }
902 |
903 | @Override
904 | public void onServiceDiscovered(PeerHandle peerHandle_, byte[] serviceSpecificInfo, List matchFilter) {
905 | super.onServiceDiscovered(peerHandle, serviceSpecificInfo, matchFilter);
906 |
907 | peerHandle = peerHandle_;
908 | Log.d("nanPUBLISH", "onServiceDiscovered found peerHandle");
909 | }
910 |
911 | @Override
912 | public void onMessageReceived(PeerHandle peerHandle_, byte[] message) {
913 | super.onMessageReceived(peerHandle, message);
914 | Log.d("nanPUBLISH", "received message");
915 | if (message.length == 2) {
916 | portToUse = byteToPortInt(message);
917 | Log.d("received", "will use port number " + portToUse);
918 | } else if (message.length == 6) {
919 | setOtherMacAddress(message);
920 | //Toast.makeText(MainActivity.this, "mac received", Toast.LENGTH_SHORT).show();
921 | } else if (message.length == 16) {
922 | setOtherIPAddress(message);
923 | //Toast.makeText(MainActivity.this, "ip received", Toast.LENGTH_SHORT).show();
924 | } else if (message.length > 16) {
925 | setMessage(message);
926 | //Toast.makeText(MainActivity.this, "message received", Toast.LENGTH_SHORT).show();
927 | }
928 |
929 | peerHandle = peerHandle_;
930 |
931 | if (publishDiscoverySession != null && peerHandle != null) {
932 | publishDiscoverySession.sendMessage(peerHandle, MAC_ADDRESS_MESSAGE, myMac);
933 | Log.d("nanPUBLISH", "onMessageReceived sending mac");
934 | Button responderButton = (Button) findViewById(R.id.responderButton);
935 | Button initiatorButton = (Button) findViewById(R.id.initiatorButton);
936 | initiatorButton.setEnabled(false);
937 | responderButton.setEnabled(true);
938 | }
939 | }
940 | }, null);
941 | //-------------------------------------------------------------------------------------------- -----
942 | }
943 |
944 | //-------------------------------------------------------------------------------------------- +++++
945 | @TargetApi(26)
946 | private void subscribeToService() {
947 |
948 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
949 | return;
950 | }
951 | Log.d("nanSUBSCRIBE", "building subscribe session");
952 |
953 | if (subType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)
954 | Log.d("nanPUBLISH", "subscribe active ");
955 | else if (subType == SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)
956 | Log.d("nanPUBLISH", "subscribe passive ");
957 |
958 | SubscribeConfig config = new SubscribeConfig.Builder()
959 | .setServiceName(SERVICE_NAME)
960 | .setServiceSpecificInfo(serviceInfo)
961 | .setSubscribeType(subType)
962 | .build();
963 | Log.d("nanSUBSCRIBE", "build finish");
964 | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.NEARBY_WIFI_DEVICES) != PackageManager.PERMISSION_GRANTED) {
965 | // TODO: Consider calling
966 | // ActivityCompat#requestPermissions
967 | // here to request the missing permissions, and then overriding
968 | // public void onRequestPermissionsResult(int requestCode, String[] permissions,
969 | // int[] grantResults)
970 | // to handle the case where the user grants the permission. See the documentation
971 | // for ActivityCompat#requestPermissions for more details.
972 | return;
973 | }
974 | wifiAwareSession.subscribe(config, new DiscoverySessionCallback() {
975 |
976 | @Override
977 | public void onServiceDiscovered(PeerHandle peerHandle_, byte[] serviceSpecificInfo, List matchFilter) {
978 | super.onServiceDiscovered(peerHandle, serviceSpecificInfo, matchFilter);
979 |
980 | peerHandle = peerHandle_;
981 |
982 | if (subscribeDiscoverySession != null && peerHandle != null) {
983 | subscribeDiscoverySession.sendMessage(peerHandle, MAC_ADDRESS_MESSAGE, myMac);
984 | Log.d("nanSUBSCRIBE", "onServiceDiscovered send mac");
985 | Button responderButton = (Button) findViewById(R.id.responderButton);
986 | Button initiatorButton = (Button) findViewById(R.id.initiatorButton);
987 | initiatorButton.setEnabled(true);
988 | responderButton.setEnabled(false);
989 | }
990 | }
991 |
992 | @Override
993 | public void onSubscribeStarted(@NonNull SubscribeDiscoverySession session) {
994 | super.onSubscribeStarted(session);
995 |
996 | subscribeDiscoverySession = session;
997 |
998 | if (subscribeDiscoverySession != null && peerHandle != null) {
999 | subscribeDiscoverySession.sendMessage(peerHandle, MAC_ADDRESS_MESSAGE, myMac);
1000 | Log.d("nanSUBSCRIBE", "onServiceStarted send mac");
1001 | Button responderButton = (Button) findViewById(R.id.responderButton);
1002 | Button initiatorButton = (Button) findViewById(R.id.initiatorButton);
1003 | initiatorButton.setEnabled(true);
1004 | responderButton.setEnabled(false);
1005 | }
1006 | }
1007 |
1008 | @Override
1009 | public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
1010 | super.onMessageReceived(peerHandle, message);
1011 | Log.d("nanSUBSCRIBE", "received message");
1012 | //Toast.makeText(MainActivity.this, "received", Toast.LENGTH_LONG).show();
1013 | if (message.length == 2) {
1014 | portToUse = byteToPortInt(message);
1015 | Log.d("received", "will use port number " + portToUse);
1016 | } else if (message.length == 6) {
1017 | setOtherMacAddress(message);
1018 | //Toast.makeText(MainActivity.this, "mac received", Toast.LENGTH_SHORT).show();
1019 | } else if (message.length == 16) {
1020 | setOtherIPAddress(message);
1021 | //Toast.makeText(MainActivity.this, "ip received", Toast.LENGTH_SHORT).show();
1022 | } else if (message.length > 16) {
1023 | setMessage(message);
1024 | //Toast.makeText(MainActivity.this, "message received", Toast.LENGTH_SHORT).show();
1025 | }
1026 | }
1027 | }, null);
1028 | }
1029 | //-------------------------------------------------------------------------------------------- -----
1030 |
1031 | /**
1032 | * Handles cleanup of the activity.
1033 | *
1034 | */
1035 | @Override
1036 | protected void onPause() {
1037 | super.onPause();
1038 | getApplicationContext().unregisterReceiver(broadcastReceiver);
1039 | closeSession();
1040 | }
1041 |
1042 | private void closeSession() {
1043 |
1044 | if (publishDiscoverySession != null) {
1045 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
1046 | publishDiscoverySession.close();
1047 | }
1048 | publishDiscoverySession = null;
1049 | }
1050 |
1051 | if (subscribeDiscoverySession != null) {
1052 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
1053 | subscribeDiscoverySession.close();
1054 | }
1055 | subscribeDiscoverySession = null;
1056 | }
1057 |
1058 | if (wifiAwareSession != null) {
1059 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
1060 | wifiAwareSession.close();
1061 | }
1062 | wifiAwareSession = null;
1063 | }
1064 | }
1065 |
1066 | /**
1067 | * Handles creating the options menu.
1068 | *
1069 | * @param menu
1070 | * @return
1071 | */
1072 | @Override
1073 | public boolean onCreateOptionsMenu(Menu menu) {
1074 | // Inflate the menu; this adds items to the action bar if it is present.
1075 | getMenuInflater().inflate(R.menu.menu_main, menu);
1076 | return true;
1077 | }
1078 |
1079 | /**
1080 | * Handles when an option is selected from the menu.
1081 | *
1082 | * @param item
1083 | * @return
1084 | */
1085 | @Override
1086 | public boolean onOptionsItemSelected(MenuItem item) {
1087 | // Handle action bar item clicks here. The action bar will
1088 | // automatically handle clicks on the Home/Up button, so long
1089 | // as you specify a parent activity in AndroidManifest.xml.
1090 | int id = item.getItemId();
1091 | //-------------------------------------------------------------------------------------------- +++++
1092 |
1093 | //noinspection SimplifiableIfStatement
1094 | if (id == R.id.action_settings) {
1095 | Intent startSettingsActivity = new Intent(this, SettingsActivity.class);
1096 | startActivity(startSettingsActivity);
1097 | return true;
1098 | }
1099 | if (id == R.id.close) {
1100 | closeSession();
1101 | finish();
1102 | System.exit(0);
1103 | }
1104 |
1105 | return super.onOptionsItemSelected(item);
1106 | //-------------------------------------------------------------------------------------------- -----
1107 | }
1108 |
1109 | /**
1110 | * Helper to set the status field.
1111 | *
1112 | * @param status
1113 | */
1114 | private void setStatus(String status) {
1115 | TextView textView = (TextView)findViewById(R.id.status);
1116 | textView.setText(status);
1117 | }
1118 |
1119 | private void setHaveSession(boolean haveSession) {
1120 | CheckBox cbHaveSession = (CheckBox)findViewById(R.id.haveSession);
1121 | cbHaveSession.setChecked(haveSession);
1122 | }
1123 |
1124 | private void setMacAddress(byte[] mac) {
1125 | myMac = mac;
1126 | String macAddress = String.format("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
1127 | EditText editText = (EditText)findViewById(R.id.macAddress);
1128 | editText.setText(macAddress);
1129 | }
1130 |
1131 | private void setOtherMacAddress(byte[] mac) {
1132 | otherMac = mac;
1133 | String macAddress = String.format("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
1134 | EditText editText = (EditText)findViewById(R.id.otherMac);
1135 | editText.setText(macAddress);
1136 | }
1137 |
1138 | //-------------------------------------------------------------------------------------------- +++++
1139 | private void setOtherIPAddress(byte[] ip) {
1140 | otherIP = ip;
1141 | try {
1142 | String ipAddr = Inet6Address.getByAddress(otherIP).toString();
1143 | EditText editText = (EditText) findViewById(R.id.IPv6text);
1144 | editText.setText(ipAddr);
1145 | } catch (UnknownHostException e) {
1146 | Log.d("myTag", "socket exception " + e.toString());
1147 | }
1148 | }
1149 | private void setMessage(byte[] msg) {
1150 | String outmsg = new String(msg).replace("messageToBeSent: ","");
1151 | EditText editText = (EditText) findViewById(R.id.msgtext);
1152 | editText.setText(outmsg);
1153 | }
1154 |
1155 | public int byteToPortInt(byte[] bytes){
1156 | return ((bytes[1] & 0xFF) << 8 | (bytes[0] & 0xFF));
1157 | }
1158 |
1159 | public byte[] portToBytes(int port){
1160 | byte[] data = new byte [2];
1161 | data[0] = (byte) (port & 0xFF);
1162 | data[1] = (byte) ((port >> 8) & 0xFF);
1163 | return data;
1164 | }
1165 |
1166 | @TargetApi(26)
1167 | public void startServer(final int port, final int backlog) {
1168 | Runnable serverTask = new Runnable() {
1169 | @Override
1170 | public void run() {
1171 | try{
1172 | Log.d("serverThread", "thread running");
1173 | Thread.sleep(1000);
1174 | serverSocket = new ServerSocket(port, backlog);
1175 | //ServerSocket serverSocket = new ServerSocket();
1176 | while (true) {
1177 | portToUse = serverSocket.getLocalPort();
1178 | if (EncryptType.equals("open")) {
1179 | portOnSystem = portToBytes(serverSocket.getLocalPort());
1180 | }
1181 |
1182 | Log.d("serverThread", "server waiting to accept on " + serverSocket.toString());
1183 | Socket clientSocket = serverSocket.accept();
1184 | DataOutputStream out = new DataOutputStream(new BufferedOutputStream(clientSocket.getOutputStream()));
1185 | DataInputStream in = new DataInputStream(new BufferedInputStream(clientSocket.getInputStream()));
1186 | byte[] buffer = new byte[4096];
1187 | int read;
1188 | int totalRead = 0;
1189 | Uri imageCollection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
1190 |
1191 | ContentValues values = new ContentValues();
1192 |
1193 | values.put(MediaStore.MediaColumns.DISPLAY_NAME, "nanFile"); //file name
1194 | values.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4"); //file extension, will automatically add to file
1195 | values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM ); //end "/" is not mandatory
1196 |
1197 | //Uri uri = getContentResolver().insert(MediaStore.Files.getContentUri("external"), values); //important!
1198 | Uri uri = getContentResolver().insert(imageCollection, values); //important!
1199 | assert uri != null;
1200 | OutputStream fos = getContentResolver().openOutputStream(uri);
1201 | //FileOutputStream fos = new FileOutputStream("/sdcard/Download/newfile");
1202 | Log.d("serverThread", "Socket being written to begin... ");
1203 | while ((read = in.read(buffer)) > 0) {
1204 | fos.write(buffer,0,read);
1205 | totalRead += read;
1206 | if (totalRead%(4096*2500)==0) {//every 10MB update status
1207 | Log.d("clientThread", "total bytes retrieved:" + totalRead);
1208 | }
1209 | }
1210 | Log.d("serverThread", "finished file transfer: " + totalRead);
1211 |
1212 | }
1213 | } catch (IOException e) {
1214 | Log.d("serverThread", "socket exception " + e.toString());
1215 | Log.d("serverThread", e.getStackTrace().toString());
1216 | } catch (InterruptedException e) {
1217 | e.printStackTrace();
1218 | }
1219 | }
1220 | };
1221 | Thread serverThread = new Thread(serverTask);
1222 | serverThread.start();
1223 |
1224 | }
1225 | public void clientSendFile(final Inet6Address serverIP,final int serverPort) {
1226 | Runnable clientTask = new Runnable() {
1227 | @Override
1228 | public void run() {
1229 | byte[] buffer = new byte[4096];
1230 | int bytesRead;
1231 | Socket clientSocket = null;
1232 | int fsize = 1;
1233 | long fileSizeInBytes = 1;
1234 | InputStream is = null;
1235 | OutputStream outs = null;
1236 | Log.d("clientThread", "thread running socket info "+ serverIP.getHostAddress() + "\t" + serverPort);
1237 | try {
1238 | clientSocket = new Socket( serverIP , serverPort );
1239 | is = clientSocket.getInputStream();
1240 | outs = clientSocket.getOutputStream();
1241 | Log.d("clientThread", "socket created ");
1242 | } catch (IOException ex) {
1243 | Log.d("clientThread", "socket could not be created " + ex.toString());
1244 | }
1245 | try {
1246 | Uri contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
1247 | Cursor cursor = getContentResolver().query(contentUri, null, null,
1248 | null, "date_modified DESC");
1249 | //Log.d("clientThread", DatabaseUtils.dumpCursorToString(cursor));
1250 | Uri uri = null;
1251 | if (cursor.getCount() == 0) {
1252 | Log.d( "clientThread","No Video files");;
1253 | } else {
1254 | while (cursor.moveToNext()) {
1255 | String fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DISPLAY_NAME));
1256 | Log.d("clientThread", fileName);
1257 | long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media._ID));
1258 | uri = ContentUris.withAppendedId(contentUri, id);
1259 | fsize = cursor.getColumnIndex(OpenableColumns.SIZE);
1260 | File mediaFile = new File(uri.getPath());
1261 | fileSizeInBytes = ((cursor.getLong(fsize)));
1262 | Log.d("clientThread", String.valueOf(fileSizeInBytes));
1263 | break;
1264 | }
1265 | }
1266 | if (uri == null) {
1267 | Log.d( "clientThread","\"IEEEspecJun2018.pdf\" not found");
1268 | }
1269 |
1270 | InputStream in = getContentResolver().openInputStream(uri);
1271 | //InputStream in = new FileInputStream("/sdcard/Download/IEEEspecJun2018.pdf");
1272 | int count;
1273 | int totalSent = 0;
1274 | DataOutputStream dos = new DataOutputStream(outs);
1275 | Log.d("clientThread", "beginning to send file (log updates every 2MB)");
1276 | while ((count = in.read(buffer))>0){
1277 | totalSent += count;
1278 | dos.write(buffer, 0, count);
1279 | if (totalSent%(10240*200)==0) {//every 2MB update status
1280 | Log.d("clientThread", "total bytes sent:" + totalSent +"\t"+ fileSizeInBytes);
1281 | try{
1282 | float percent = (float) totalSent/fileSizeInBytes;
1283 | setStatus("percent sent: "+ String.format("%.2f",percent));
1284 | } catch (Exception e) {
1285 | Log.e("clientThread",e.toString());
1286 | }
1287 | }
1288 | }
1289 | in.close();
1290 | dos.close();
1291 | Log.d("clientThread", "finished sending file!!! "+totalSent);
1292 | setStatus("Finished sending file");
1293 | } catch(FileNotFoundException e){
1294 | Log.d("clientThread", "file not found exception " + e.toString());
1295 | } catch(IOException e){
1296 | Log.d("clientThread", e.toString());
1297 | }
1298 |
1299 | }
1300 | };
1301 | Thread clientThread = new Thread(clientTask);
1302 | clientThread.start();
1303 |
1304 | }
1305 |
1306 | //-------------------------------------------------------------------------------------------- -----
1307 |
1308 | }
1309 |
--------------------------------------------------------------------------------