diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser
new file mode 100644
index 0000000..d3943a2
Binary files /dev/null and b/.idea/caches/build_file_checksums.ser differ
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..30aa626
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3963879..99202cc 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -5,11 +5,12 @@
diff --git a/.idea/modules.xml b/.idea/modules.xml
index a5c9e58..d8a29ba 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,8 +2,8 @@
-
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index dc2fa72..e0d2abe 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Share internet via Wifi direct on Android
+# Share internet via Wifi direct on Android [Root]
## Direct Net Share
@@ -9,7 +9,7 @@ Requirements
------------
- Launch the app in the host device.
- Connect to the host device using the `ssid` and `password` displayed in the app.
-- On the other device, go to `Settings` -> `Wifi` -> Long click the current network -> `Modify network` -> `Advanced Options` -> and use the proxy settings displayed in the app.
+- No need to setup a proxy on the device(s) you wish to connect. The ip is forwarded thanks to the root rights.
Repository overview
-------------------
diff --git a/app/build.gradle b/app/build.gradle
index 50bf555..fb82f2b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
android {
compileSdkVersion 26
@@ -15,9 +16,19 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ kotlin {
+ experimental {
+ coroutines 'enable'
+ }
+ }
}
dependencies {
implementation 'com.android.support:appcompat-v7:26.1.0'
compile project(':direct-share')
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5"
+}
+repositories {
+ mavenCentral()
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 56519bc..8547375 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,7 @@
+
infoTv.text = String.format("SSID : %s\nPassword : %s", ssid, password) }
+ private lateinit var share: DirectNetShare
+ private val onCheckedChangeListener = CompoundButton.OnCheckedChangeListener { _, isChecked ->
+ if (isChecked) {
+ checkWifiAndStart()
+ } else {
+ stopShare()
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ infoTv = findViewById(R.id.info)
+ (findViewById(R.id.wifi_switch)).setOnCheckedChangeListener(onCheckedChangeListener)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ stopShare()
+ }
+
+ private fun checkWifiAndStart() {
+ if (!Utils.isWifiEnabled(applicationContext)) {
+ registerReceiver(object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ if (intent.action != null && intent.action == ConnectivityManager.CONNECTIVITY_ACTION) {
+ val noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)
+ if (!noConnectivity) {
+ startShare()
+ unregisterReceiver(this)
+ }
+ }
+ }
+ }, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
+ Utils.enableWifi(applicationContext)
+ } else {
+ startShare()
+ }
+ }
+
+ private fun startShare() {
+ share = DirectNetShare(this@MainActivity, groupCreatedListener)
+ share.start()
+ launch {
+ val success = rootManager.dhcpSetup()
+ Log.d("MainActivity", "DHCP setup successful? $success")
+ }
+ }
+
+ private fun stopShare() {
+ share.stop()
+ infoTv.text = ""
+ }
+}
diff --git a/app/src/main/java/shinil/direct_share/RootManager.kt b/app/src/main/java/shinil/direct_share/RootManager.kt
new file mode 100644
index 0000000..bc5013a
--- /dev/null
+++ b/app/src/main/java/shinil/direct_share/RootManager.kt
@@ -0,0 +1,32 @@
+package shinil.direct_share
+
+import android.util.Log
+import java.util.*
+
+class RootManager {
+ suspend fun dhcpSetup(): Boolean {
+ var success = true
+ success = success && runRootCommand("echo 1 > /proc/sys/net/ipv4/ip_forward")
+ success = success && runRootCommand("iptables -F")
+ success = success && runRootCommand("iptables -t nat -A POSTROUTING -j MASQUERADE")
+ success = success && runRootCommand("iptables -A FORWARD -j ACCEPT")
+ success = success && runRootCommand("iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to-destination 8.8.8.8:53")
+ success = success && runRootCommand("iptables -A FORWARD -p udp -d 8.8.8.8 --dport 53 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT")
+ return success
+ }
+
+ /**
+ * Warning: keep the 'suspend' here.
+ * waitFor documentation: Causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
+ */
+ private suspend fun runRootCommand(command: String): Boolean {
+ val commands = arrayOf("su", "-c", command)
+ val start: Long = System.currentTimeMillis()
+ val process: Process = Runtime.getRuntime().exec(commands)
+ val result = process.waitFor()
+ val end: Long = System.currentTimeMillis()
+ Log.d("RootManager", "Command ${Arrays.toString(commands)} executed in ${end - start} ms " +
+ " with result $result")
+ return result == 0
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/shinil/direct_share/U.java b/app/src/main/java/shinil/direct_share/Utils.java
similarity index 95%
rename from app/src/main/java/shinil/direct_share/U.java
rename to app/src/main/java/shinil/direct_share/Utils.java
index ce78894..eb7e805 100644
--- a/app/src/main/java/shinil/direct_share/U.java
+++ b/app/src/main/java/shinil/direct_share/Utils.java
@@ -7,7 +7,7 @@
* @author shinilms
*/
-public final class U {
+public final class Utils {
public static boolean enableWifi(Context context) {
WifiManager wifiManager = (WifiManager) context.getApplicationContext().
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 549bb2e..7062fd1 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,24 +1,21 @@
-
-
+
+
+ android:text="Enable Wifi" />
+
-
+ android:layout_marginTop="40dp" />
+
diff --git a/build.gradle b/build.gradle
index 020eae2..4671f02 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,14 +1,16 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
-
+ ext.kotlin_version = '1.2.41'
+
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.0.0'
-
+ classpath 'com.android.tools.build:gradle:3.1.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c8f987f..2e7eb92 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Dec 11 12:55:17 IST 2017
+#Thu May 24 11:27:11 GMT 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip