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