diff --git a/mobile/build.gradle b/mobile/build.gradle index 3d3cc724..ab59aba5 100644 --- a/mobile/build.gradle +++ b/mobile/build.gradle @@ -11,8 +11,8 @@ android { applicationId "nl.jolanrensen.permanentproxy" minSdkVersion 23 targetSdkVersion 29 - versionCode 12 - versionName "3.5" + versionCode 14 + versionName "3.7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/mobile/src/main/res/layout/activity_main.xml b/mobile/src/main/res/layout/activity_main.xml index e6366128..b92fcbfa 100644 --- a/mobile/src/main/res/layout/activity_main.xml +++ b/mobile/src/main/res/layout/activity_main.xml @@ -1,36 +1,45 @@ - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml index d7f4aa58..90276317 100644 --- a/mobile/src/main/res/values/strings.xml +++ b/mobile/src/main/res/values/strings.xml @@ -1,5 +1,6 @@ Permanent Proxy - This app is just a phone companion of Permanent Proxy. Please install Permanent Proxy from the Play Store on you Wear OS watch. + This app is just a phone companion of Permanent Proxy. Please install Permanent Proxy from the Play Store on you Wear OS watch. The app can be found in the \"Apps on your Phone\" section. System -> About and tap the Build number until you are a \"developer\".\nNext, go to Settings -> Developer options and enable \"ADB debugging\" and \"Debug over Bluetooth\".\nFinally start up Permanent Proxy, request permission and press \"Allow\" or \"Always allow this Computer\" if prompted.\nAfter the app has gotten permission, ADB can be turned off again unless you want to disable the proxy.\n\nNow you can get started! Simply enter a proxy address and port, enable it and you\'re done! If you reboot, the proxy will remain.\n\nProxy services can be found online and can be from any country. However, do make sure your proxy works and you completely trust the proxy you chose before you enter it! All the data of your watch might be sent through that proxy, even sensitive data, so act at your own risk.]]> + Some older watches are not powerful enough to get Secure Settings permission by itself using my method. If this is the case for your watch, you will need a PC to grant Permanent Proxy permission. The instructions are also available in the app description.\n\nFirst make sure to connect your watch to your PC via ADB. You can Google how to do this, there are lots of tutorials. When your watch is connected, use the command \n\nadb shell pm grant nl.jolanrensen.permanentproxy android.permission.WRITE_SECURE_SETTINGS\n\nto give Permanent Proxy the permissions needed to turn on/edit the proxy.\n\nTo turn off the proxy, connect to your PC in the same manner as before, but now you will need the following command: \n\nadb shell settings delete global http_proxy; adb shell settings delete global global_http_proxy_host; adb shell settings delete global global_http_proxy_port; adb shell settings delete global global_http_proxy_exclusion_list; adb shell settings delete global global_proxy_pac_url; adb shell reboot diff --git a/wear/build.gradle b/wear/build.gradle index f71a557d..44f54387 100644 --- a/wear/build.gradle +++ b/wear/build.gradle @@ -11,8 +11,8 @@ android { applicationId "nl.jolanrensen.permanentproxy" minSdkVersion 23 targetSdkVersion 29 - versionCode 12 - versionName "3.5" + versionCode 14 + versionName "3.7" } buildTypes { release { diff --git a/wear/release/mobile-release.apk b/wear/release/mobile-release.apk index 286d60ae..65465e07 100644 Binary files a/wear/release/mobile-release.apk and b/wear/release/mobile-release.apk differ diff --git a/wear/release/wear-release.aab b/wear/release/wear-release.aab index c22ec7d4..af943934 100644 Binary files a/wear/release/wear-release.aab and b/wear/release/wear-release.aab differ diff --git a/wear/release/wear-release.apk b/wear/release/wear-release.apk index d8e7db47..0db9d02f 100644 Binary files a/wear/release/wear-release.apk and b/wear/release/wear-release.apk differ diff --git a/wear/src/main/AndroidManifest.xml b/wear/src/main/AndroidManifest.xml index 8ec9602b..5f10f9fd 100644 --- a/wear/src/main/AndroidManifest.xml +++ b/wear/src/main/AndroidManifest.xml @@ -13,7 +13,7 @@ - + + - + android:label="@string/title_activity_donate"/> - + android:label="@string/title_activity_enable_adbbluetooth"/> diff --git a/wear/src/main/java/nl/jolanrensen/permanentproxy/MainActivity.kt b/wear/src/main/java/nl/jolanrensen/permanentproxy/MainActivity.kt index 0f251515..33efed7d 100644 --- a/wear/src/main/java/nl/jolanrensen/permanentproxy/MainActivity.kt +++ b/wear/src/main/java/nl/jolanrensen/permanentproxy/MainActivity.kt @@ -21,6 +21,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import nl.jolanrensen.permanentproxy.Constants.currentProxy import nl.jolanrensen.permanentproxy.Constants.getCurrentIP +import nl.jolanrensen.permanentproxy.Constants.logD import nl.jolanrensen.permanentproxy.Constants.logE import nl.jolanrensen.permanentproxy.Constants.startProxy import nl.jolanrensen.permanentproxy.Constants.stopProxy @@ -87,8 +88,8 @@ class MainActivity : WearableActivity() { startActivityForResult( Intent(this, RequestPermissionActivity::class.java), PERMISSION - ) + onPause() } donate.setOnClickListener { @@ -96,6 +97,12 @@ class MainActivity : WearableActivity() { Intent(this, DonateActivity::class.java) ) } + + old_watch.setOnClickListener { + startActivity( + Intent(this, OldWatchActivity::class.java) + ) + } } private fun setupStatus(wait: Boolean = false): Boolean { @@ -252,6 +259,17 @@ class MainActivity : WearableActivity() { } } + override fun onPause() { + super.onPause() + logD("onPause") + } + + override fun onResume() { + super.onResume() + logD("onResume") + } + + private fun showSoftKeyboard(view: View) { if (view.requestFocus()) { getSystemService()?.apply { @@ -272,6 +290,7 @@ class MainActivity : WearableActivity() { } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + onResume() when { requestCode == PERMISSION && resultCode == RESULT_OK -> { continueSetup() diff --git a/wear/src/main/java/nl/jolanrensen/permanentproxy/OldWatchActivity.kt b/wear/src/main/java/nl/jolanrensen/permanentproxy/OldWatchActivity.kt new file mode 100644 index 00000000..e3540d4e --- /dev/null +++ b/wear/src/main/java/nl/jolanrensen/permanentproxy/OldWatchActivity.kt @@ -0,0 +1,15 @@ +package nl.jolanrensen.permanentproxy + +import android.os.Bundle +import android.support.wearable.activity.WearableActivity + +class OldWatchActivity : WearableActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_old_watch) + + // Enables Always-on + setAmbientEnabled() + } +} diff --git a/wear/src/main/java/nl/jolanrensen/permanentproxy/RequestPermissionActivity.kt b/wear/src/main/java/nl/jolanrensen/permanentproxy/RequestPermissionActivity.kt index 98434fb6..159b6e44 100644 --- a/wear/src/main/java/nl/jolanrensen/permanentproxy/RequestPermissionActivity.kt +++ b/wear/src/main/java/nl/jolanrensen/permanentproxy/RequestPermissionActivity.kt @@ -1,9 +1,11 @@ package nl.jolanrensen.permanentproxy import android.app.Activity +import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle import android.support.wearable.activity.WearableActivity +import androidx.core.view.isVisible import kotlinx.android.synthetic.main.activity_request_permission.* import nl.jolanrensen.permanentproxy.Constants.logE import nl.jolanrensen.permanentproxy.Constants.toastLong @@ -65,11 +67,19 @@ class RequestPermissionActivity : WearableActivity() { // useless loading bar to show google the app is doing something thread(start = true) { var s = 0 - while (s <= 25 && !stop) { - loading_bar.progress = ((s / 25f) * 100f).toInt() + while (s <= 35 && !stop) { + loading_bar.progress = ((s / 35f) * 100f).toInt() s++ Thread.sleep(1000) } + runOnUiThread { + too_long.isVisible = true + too_long.setOnClickListener { + startActivity(Intent(this, OldWatchActivity::class.java)) + finish() + } + } + } } diff --git a/wear/src/main/java/nl/jolanrensen/permanentproxy/SendSingleCommand.kt b/wear/src/main/java/nl/jolanrensen/permanentproxy/SendSingleCommand.kt index 58b0e6af..fae5475b 100644 --- a/wear/src/main/java/nl/jolanrensen/permanentproxy/SendSingleCommand.kt +++ b/wear/src/main/java/nl/jolanrensen/permanentproxy/SendSingleCommand.kt @@ -7,18 +7,17 @@ import com.tananaev.adblib.AdbBase64 import com.tananaev.adblib.AdbConnection import com.tananaev.adblib.AdbCrypto import com.tananaev.adblib.AdbStream -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch import java.io.File import java.io.IOException import java.io.UnsupportedEncodingException +import java.lang.Thread.sleep import java.net.ConnectException import java.net.NoRouteToHostException import java.net.Socket import java.net.UnknownHostException import java.security.NoSuchAlgorithmException import java.security.spec.InvalidKeySpecException +import kotlin.concurrent.thread /** * Created by Jolan Rensen on 21-2-2017. @@ -126,7 +125,10 @@ constructor( if (ctrlC) stream.write(byteArrayOf(0x03)) stream.write(command + '\n') } catch (e: IOException) { - throw IOException("Couldn't write command, stream fails while sending data, try without CTRL+C", e) + throw IOException( + "Couldn't write command, stream fails while sending data, try without CTRL+C", + e + ) } catch (e: InterruptedException) { throw Exception("Couldn't write command, unable to wait to send data", e) } @@ -137,7 +139,7 @@ constructor( var timer = 0 logD("Getting responses...") - GlobalScope.launch { + thread(start = true) { while (!done) { try { timer = 0 @@ -152,53 +154,51 @@ constructor( } } - GlobalScope.launch { - // the timer resets on each response and when it reached the limit, it stops reading and continues with the rest - while (!done) { - delay(1) - timer++ - if (timer >= timeout) done = true - } + // the timer resets on each response and when it reached the limit, it stops reading and continues with the rest + while (!done) { + sleep(1) + timer++ + if (timer >= timeout) done = true + } + + logD("response:\n$responses") - logD("response:\n$responses") + // Trying to split the response on newlines, not waterproof + splitResponses = ArrayList() + for (item in responses.split("\\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) { + splitResponses!!.add(item.trim { it <= ' ' }) + } - // Trying to split the response on newlines, not waterproof - splitResponses = ArrayList() - for (item in responses.split("\\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) { - splitResponses!!.add(item.trim { it <= ' ' }) + logD("Sending close command and waiting for stream to close") + stream.close() + thread(start = true) { + sleep(10000) + if (!stream.isClosed) + throw Exception("Stream didn't close after 10 seconds waiting") + } + thread(start = true) { + while (!stream.isClosed) { + sleep(1) } + logD("Stream closed, closing Adb...") - logD("Sending close command and waiting for stream to close") - stream.close() - GlobalScope.launch { - delay(10000) - if (!stream.isClosed) - throw Exception("Stream didn't close after 10 seconds waiting") + try { + adb.close() + } catch (e: IOException) { + throw IOException("Couldn't close ADB connection socket", e) + } + thread(start = true) { + sleep(10000) + if (!sock.isClosed) + throw Exception("ADB connection socket didn't close after 10 seconds waiting") } - GlobalScope.launch { - while (!stream.isClosed) { - delay(1) - } - logD("Stream closed, closing Adb...") - try { - adb.close() - } catch (e: IOException) { - throw IOException("Couldn't close ADB connection socket", e) - } - GlobalScope.launch { - delay(10000) - if (!sock.isClosed) - throw Exception("ADB connection socket didn't close after 10 seconds waiting") - } - GlobalScope.launch { - while (!sock.isClosed) { - delay(1) - } - logD("ADB connection socket closed") - callBack(splitResponses) - } + while (!sock.isClosed) { + sleep(1) } + logD("ADB connection socket closed") + callBack(splitResponses) + } } diff --git a/wear/src/main/res/layout/activity_main.xml b/wear/src/main/res/layout/activity_main.xml index a970f252..1c1b24e8 100644 --- a/wear/src/main/res/layout/activity_main.xml +++ b/wear/src/main/res/layout/activity_main.xml @@ -134,13 +134,23 @@ android:id="@+id/donate" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="45dp" android:background="?android:attr/selectableItemBackground" android:gravity="center_vertical" android:minHeight="45dp" android:text="@string/donate" android:textAppearance="@android:style/TextAppearance.Material.Body1" /> + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/wear/src/main/res/layout/activity_request_permission.xml b/wear/src/main/res/layout/activity_request_permission.xml index 598e2dba..e3e60736 100644 --- a/wear/src/main/res/layout/activity_request_permission.xml +++ b/wear/src/main/res/layout/activity_request_permission.xml @@ -40,6 +40,20 @@ android:max="100" android:progress="0" /> + + How to enable ADB over Bluetooth? EnableADBBluetoothActivity System -> About and tap the Build number until you are a \"developer\".\nNext, go to Settings -> Developer options and enable \"ADB debugging\" and \"Debug over Bluetooth\".\nFinally start up Permanent Proxy, request permission and press \"Allow\" or \"Always allow this Computer\" if prompted.\nAfter the app has gotten permission, ADB can be turned off again unless you want to disable the proxy.\n\nNow you can get started! Simply enter a proxy address and port, enable it and you\'re done! If you reboot, the proxy will remain.\n\nProxy services can be found online and can be from any country. However, do make sure your proxy works and you completely trust the proxy you chose before you enter it! All the data of your watch might be sent through that proxy, even sensitive data, so act at your own risk.]]> - Requesting permission, this can take up to 25s… \"Allow\" or \"Always allow computer\" if prompted.\n\nNote: the app works best with WiFi turned OFF. + Requesting permission. This can take up to 25 seconds… \"Allow\" or \"Always allow computer\" if prompted.\n\Remember: the app works best with WiFi turned OFF. Write secure settings permission needed. This can be enabled via ADB over Bluetooth. ADB over Bluetooth is enabled, request permission! Permission granted,\nADB can be turned off. @@ -48,4 +48,8 @@ Donating won\'t give you extra features, however, it will considerably support me, the developer, to continue making awesome apps like this one! Thank you very much for donating! It is much appreciated :) + Nothing happens? + OldWatchActivity + Some older watches are not powerful enough to get Secure Settings permission by itself using my method. If this is the case for your watch, you will need a PC to grant Permanent Proxy permission. The instructions are also available in the mobile app or in the app description.\n\nFirst make sure to connect your watch to your PC via ADB. You can Google how to do this, there are lots of tutorials. When your watch is connected, use the command\n\nadb shell pm grant nl.jolanrensen.permanentproxy android.permission.WRITE_SECURE_SETTINGS\n\nto give Permanent Proxy the permissions needed to turn on/edit the proxy.\n\nTo turn off the proxy, connect to your PC in the same manner as before, but now you will need the following command:\n\nadb shell settings delete global http_proxy; adb shell settings delete global global_http_proxy_host; adb shell settings delete global global_http_proxy_port; adb shell settings delete global global_http_proxy_exclusion_list; adb shell settings delete global global_proxy_pac_url; adb shell reboot + Requesting permission or turning off proxy not working?