Skip to content

Commit

Permalink
v3.8:
Browse files Browse the repository at this point in the history
Replaced Google billing with PayPal
  • Loading branch information
Jolanrensen committed Jan 6, 2020
1 parent c9c3030 commit 7892e2a
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 134 deletions.
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# PermanentProxy-for-WearOS
App that will enable (on boot) a defined proxy on Wear OS watches. Could be used to enable Google Pay in "unsupported countries"
Simple app to run a proxy (on boot) on a Wear OS device and enable geo-restricted apps like Google Pay in unsupported regions!

(The apk provided is an empty PHONE companion app. Simply install Permanent Proxy on your Wear OS watch from the Play Store after installing this apk on your phone)

Sometimes big companies decide that Geoblocking is a good idea. I don't agree.
So that's why I created this Wear OS app to allow users to use their watch as if they were in another country. This means you can use certain payment apps or otherwise geospecific apps wherever you are in the world!
Expand All @@ -8,8 +10,29 @@ The app uses Android's built-in http_proxy command that turns on a proxy for the

To get started, first enable the Developer Options of your watch, which can be achieved by going to Settings -> System -> About and tap the Build number until you are a "developer".
Next, go to Settings -> Developer options and enable "ADB debugging" and "Debug over Bluetooth".
Finally start up Permanent Proxy and press "Always allow this Computer" if prompted.
Finally start up Permanent Proxy, request permission and press "Allow" or "Always allow this Computer" if prompted.
After requesting permission, ADB can be turned off again to save battery, unless you want to turn off the proxy completely.

Now you can get started!
Simply enter a proxy address and port, enable it (and on boot if you like) and you're done!

Proxy services can be found online and can be from any country. However, do make sure 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.


Having trouble getting permission?

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.

First 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

adb shell pm grant nl.jolanrensen.permanentproxy android.permission.WRITE_SECURE_SETTINGS

to give Permanent Proxy the permissions needed to turn on/edit the proxy.

To turn off the proxy, connect to your PC in the same manner as before, but now you will need the following command:

adb 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



Thanks to reddit user /u/shadowban!
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.3.61'
repositories {
google()
jcenter()

}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.android.tools.build:gradle:3.5.3'
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
Expand Down
4 changes: 2 additions & 2 deletions mobile/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ android {
applicationId "nl.jolanrensen.permanentproxy"
minSdkVersion 23
targetSdkVersion 29
versionCode 14
versionName "3.7"
versionCode 15
versionName "3.8"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand Down
12 changes: 6 additions & 6 deletions wear/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ android {
applicationId "nl.jolanrensen.permanentproxy"
minSdkVersion 23
targetSdkVersion 29
versionCode 14
versionName "3.7"
versionCode 15
versionName "3.8"
}
buildTypes {
release {
Expand All @@ -39,11 +39,11 @@ dependencies {
implementation 'com.tananaev:adblib:1.2'
implementation 'com.google.android.gms:play-services-wearable:17.0.0'
implementation 'androidx.percentlayout:percentlayout:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.android.billingclient:billing:1.1'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation "androidx.core:core-ktx:1.2.0-beta01"
// implementation 'com.android.billingclient:billing:1.1'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation "androidx.core:core-ktx:1.2.0-rc01"
implementation 'com.android.support:wear:28.0.0'
compileOnly 'com.google.android.wearable:wearable:2.5.0'
}
Binary file modified wear/release/mobile-release.apk
Binary file not shown.
Binary file modified wear/release/wear-release.apk
Binary file not shown.
3 changes: 2 additions & 1 deletion wear/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<uses-permission
android:name="android.permission.WRITE_SECURE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="com.android.vending.BILLING" />
<!-- <uses-permission android:name="com.android.vending.BILLING" />-->

<application
android:allowBackup="true"
Expand Down Expand Up @@ -53,6 +53,7 @@
</intent-filter>
</activity>
<activity android:name=".RequestPermissionActivity" />
<activity android:name="androidx.wear.activity.ConfirmationActivity" />
</application>

</manifest>
21 changes: 21 additions & 0 deletions wear/src/main/java/nl/jolanrensen/permanentproxy/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ package nl.jolanrensen.permanentproxy

import android.content.Context
import android.content.Intent
import android.content.Intent.ACTION_VIEW
import android.content.Intent.CATEGORY_BROWSABLE
import android.content.SharedPreferences
import android.net.Uri
import android.provider.Settings
import android.util.Log
import android.widget.Toast
import androidx.core.content.edit
import androidx.wear.activity.ConfirmationActivity
import androidx.wear.activity.ConfirmationActivity.EXTRA_ANIMATION_TYPE
import androidx.wear.activity.ConfirmationActivity.OPEN_ON_PHONE_ANIMATION
import com.google.android.wearable.intent.RemoteIntent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
Expand Down Expand Up @@ -122,6 +129,20 @@ object Constants {
}
}
}

fun Context.launchUrlOnPhone(url: String) {
RemoteIntent.startRemoteActivity(
this,
Intent(ACTION_VIEW)
.addCategory(CATEGORY_BROWSABLE)
.setData(Uri.parse(url)),
null
)
startActivity(
Intent(this, ConfirmationActivity::class.java)
.putExtra(EXTRA_ANIMATION_TYPE, OPEN_ON_PHONE_ANIMATION)
)
}
}


Expand Down
152 changes: 31 additions & 121 deletions wear/src/main/java/nl/jolanrensen/permanentproxy/DonateActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,142 +2,52 @@ package nl.jolanrensen.permanentproxy

import android.os.Bundle
import android.support.wearable.activity.WearableActivity
import android.view.View
import androidx.core.view.isVisible
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingClient.BillingResponse.*
import com.android.billingclient.api.BillingClientStateListener
import com.android.billingclient.api.BillingFlowParams
import com.android.billingclient.api.SkuDetailsParams
import kotlinx.android.synthetic.main.activity_donate.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import nl.jolanrensen.permanentproxy.Constants.logD
import nl.jolanrensen.permanentproxy.Constants.logE
import nl.jolanrensen.permanentproxy.Constants.toast
import nl.jolanrensen.permanentproxy.Constants.toastLong
import nl.jolanrensen.permanentproxy.Constants.launchUrlOnPhone

class DonateActivity : WearableActivity() {

private fun getPaypalLink(amount: Double) = "https://paypal.me/jolanrensen/$amount"

val thankYou = 0.99
val bigThankYou = 1.99
val biggerThankYou = 4.99
val biggestThankYou = 9.99

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_donate)

// Enables Always-on
setAmbientEnabled()

var billingClient: BillingClient? = null
billingClient = BillingClient.newBuilder(this)
.setListener { responseCode, purchases ->
logD("on purchases updated response: $responseCode, purchases: $purchases")
when (responseCode) {
FEATURE_NOT_SUPPORTED -> Unit
SERVICE_DISCONNECTED -> Unit
OK -> {
if (purchases != null) {
finish()
toastLong(
getString(R.string.donation_successful)
)
for (purchase in purchases) { // should only be 1
billingClient!!.consumeAsync(purchase.purchaseToken) { responseCode, _ ->
if (responseCode == OK)
logD("purchase consumed")
}
}
}
}
USER_CANCELED -> Unit
SERVICE_UNAVAILABLE -> Unit
BILLING_UNAVAILABLE -> Unit
ITEM_UNAVAILABLE -> Unit
DEVELOPER_ERROR -> Unit
ERROR -> Unit
ITEM_ALREADY_OWNED -> Unit
ITEM_NOT_OWNED -> Unit
}
}
.build()

var tries = 0
val billingClientStateListener = object : BillingClientStateListener {
override fun onBillingServiceDisconnected() {
logE("Billing service disconnected")
if (tries == 10) {
runOnUiThread {
toast(getString(R.string.couldnt_connect_to_play))
}
}
val listener = this
GlobalScope.launch(Dispatchers.Default) {
delay(100)
billingClient.startConnection(listener)
tries++
}
}
thank_you_price.text = getString(R.string._dollar, thankYou.toString())
thank_you_card.setOnClickListener {
launchUrlOnPhone(
getPaypalLink(thankYou)
)
}

override fun onBillingSetupFinished(@BillingClient.BillingResponse responseCode: Int) {
logD("Billing setup finished")
// get purchases
val skuList = arrayListOf(
"thank_you",
"big_thank_you",
"bigger_thank_you",
"biggest_thank_you"
)
billingClient.querySkuDetailsAsync(
SkuDetailsParams.newBuilder()
.setSkusList(skuList)
.setType(BillingClient.SkuType.INAPP)
.build()
) { responseCode, skuDetailsList ->
logD("Billing sku details received, $responseCode, $skuDetailsList")
if (responseCode == OK && skuDetailsList != null) {
for (skuDetails in skuDetailsList) {
val sku = skuDetails.sku
val price = skuDetails.price
runOnUiThread {
when (sku) {
"thank_you" -> thank_you_price.text = price
"big_thank_you" -> big_thank_you_price.text = price
"bigger_thank_you" -> bigger_thank_you_price.text = price
"biggest_thank_you" -> biggest_thank_you_price.text = price
}
}
}
} else {
billing_not_working.isVisible = true
billing_not_working2.isVisible = true
}
}
big_thank_you_price.text = getString(R.string._dollar, bigThankYou.toString())
big_thank_you_card.setOnClickListener {
launchUrlOnPhone(
getPaypalLink(bigThankYou)
)
}

val doPurchase = View.OnClickListener {
logD("Billing onclick $it")
billingClient!!.launchBillingFlow(
this@DonateActivity,
BillingFlowParams.newBuilder()
.setSku(
when (it.id) {
thank_you_card.id -> "thank_you"
big_thank_you_card.id -> "big_thank_you"
bigger_thank_you_card.id -> "bigger_thank_you"
biggest_thank_you_card.id -> "biggest_thank_you"
else -> null
}
)
.setType(BillingClient.SkuType.INAPP)
.build()
)
}
bigger_thank_you_price.text = getString(R.string._dollar, biggerThankYou.toString())
bigger_thank_you_card.setOnClickListener {
launchUrlOnPhone(
getPaypalLink(biggerThankYou)
)
}

thank_you_card.setOnClickListener(doPurchase)
big_thank_you_card.setOnClickListener(doPurchase)
bigger_thank_you_card.setOnClickListener(doPurchase)
biggest_thank_you_card.setOnClickListener(doPurchase)
}
biggest_thank_you_price.text = getString(R.string._dollar, biggestThankYou.toString())
biggest_thank_you_card.setOnClickListener {
launchUrlOnPhone(
getPaypalLink(biggestThankYou)
)
}
billingClient.startConnection(billingClientStateListener)
}
}
1 change: 1 addition & 0 deletions wear/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<string name="donation_successful">Thank you very much for donating! It is much appreciated :)</string>
<string name="too_long">Nothing happens?</string>
<string name="title_activity_old_watch">OldWatchActivity</string>
<string name="_dollar">\$%1$s</string>
<string name="old_watch">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</string>
<string name="request_permission_not_working">Requesting permission or turning off proxy not working?</string>
</resources>

0 comments on commit 7892e2a

Please sign in to comment.