Add the best feature ever (E-begging)

This reverts commit ebb6061a6e.
This commit is contained in:
Mygod
2018-07-13 15:05:33 +08:00
parent 2e912bf767
commit 33cd906f65
12 changed files with 259 additions and 11 deletions

1
mobile/.gitignore vendored
View File

@@ -1,6 +1,7 @@
/build
/debug
/release
/google/
# tests aren't ready yet
/src/androidTest

View File

@@ -11,8 +11,8 @@ android {
minSdkVersion 21
targetSdkVersion 28
resConfigs "zh-rCN"
versionCode 25
versionName "1.3.4"
versionCode 26
versionName "1.3.5"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
@@ -26,11 +26,23 @@ android {
}
}
dataBinding.enabled = true
flavorDimensions("freedom")
productFlavors {
freedom {
dimension "freedom"
buildConfigField "boolean", "DONATIONS", "true"
}
google {
dimension "freedom"
buildConfigField "boolean", "DONATIONS", "false"
}
}
}
dependencies {
kapt "androidx.databinding:databinding-compiler:$androidPluginVersion"
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.billingclient:billing:1.1'
implementation "com.android.support:customtabs:$supportLibraryVersion"
implementation "com.android.support:design:$supportLibraryVersion"
implementation "com.android.support:preference-v14:$supportLibraryVersion"

View File

@@ -21,6 +21,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.BILLING"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

View File

@@ -0,0 +1,103 @@
package be.mygod.vpnhotspot
import android.app.AlertDialog
import android.net.Uri
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewStub
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.Spinner
import com.android.billingclient.api.*
import com.crashlytics.android.Crashlytics
/**
* Based on: https://github.com/PrivacyApps/donations/blob/747d36a18433c7e9329691054122a8ad337a62d2/Donations/src/main/java/org/sufficientlysecure/donations/DonationsFragment.java
*/
class EBegFragment : DialogFragment(), PurchasesUpdatedListener, BillingClientStateListener,
SkuDetailsResponseListener, ConsumeResponseListener {
companion object {
private const val TAG = "EBegFragment"
}
private lateinit var billingClient: BillingClient
private lateinit var googleSpinner: Spinner
private var skus: MutableList<SkuDetails>? = null
set(value) {
field = value
googleSpinner.apply {
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item,
value?.map { it.price } ?: emptyList())
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
setAdapter(adapter)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
inflater.inflate(R.layout.fragment_ebeg, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
googleSpinner = view.findViewById(R.id.donations__google_android_market_spinner)
billingClient = BillingClient.newBuilder(view.context).setListener(this).build()
onBillingServiceDisconnected()
view.findViewById<Button>(R.id.donations__google_android_market_donate_button).setOnClickListener {
val skus = skus
if (skus == null) {
openDialog(android.R.drawable.ic_dialog_alert,
R.string.donations__google_android_market_not_supported_title,
getString(R.string.donations__google_android_market_not_supported))
} else billingClient.launchBillingFlow(requireActivity(), BillingFlowParams.newBuilder()
.setSku(skus[googleSpinner.selectedItemPosition].sku).setType(BillingClient.SkuType.INAPP).build())
}
@Suppress("ConstantConditionIf")
if (BuildConfig.DONATIONS) (view.findViewById<ViewStub>(R.id.donations__more_stub).inflate() as Button)
.setOnClickListener {
(activity as MainActivity).launchUrl(Uri.parse("https://mygod.be/donate/"))
}
}
private fun openDialog(icon: Int, title: Int, message: String) = AlertDialog.Builder(requireContext()).apply {
setIcon(icon)
setTitle(title)
setMessage(message)
isCancelable = true
setNeutralButton(R.string.donations__button_close) { dialog, _ -> dialog.dismiss() }
}.show()
override fun onBillingServiceDisconnected() {
skus = null
billingClient.startConnection(this)
}
override fun onBillingSetupFinished(responseCode: Int) {
if (responseCode == BillingClient.BillingResponse.OK) {
billingClient.querySkuDetailsAsync(
SkuDetailsParams.newBuilder().apply {
setSkusList(listOf("donate001", "donate002", "donate005", "donate010", "donate020", "donate050",
"donate100", "donate200", "donatemax"))
setType(BillingClient.SkuType.INAPP)
}.build(), this)
} else Crashlytics.log(Log.ERROR, TAG, "onBillingSetupFinished: $responseCode")
}
override fun onSkuDetailsResponse(responseCode: Int, skuDetailsList: MutableList<SkuDetails>?) {
if (responseCode == BillingClient.BillingResponse.OK) skus = skuDetailsList
else Crashlytics.log(Log.ERROR, TAG, "onSkuDetailsResponse: $responseCode")
}
override fun onPurchasesUpdated(responseCode: Int, purchases: MutableList<Purchase>?) {
if (responseCode == BillingClient.BillingResponse.OK && purchases != null) {
// directly consume in-app purchase, so that people can donate multiple times
purchases.forEach { billingClient.consumeAsync(it.purchaseToken, this) }
} else Crashlytics.log(Log.ERROR, TAG, "onPurchasesUpdated: $responseCode")
}
override fun onConsumeResponse(responseCode: Int, purchaseToken: String?) {
if (responseCode == BillingClient.BillingResponse.OK) {
openDialog(android.R.drawable.ic_dialog_info, R.string.donations__thanks_dialog_title,
getString(R.string.donations__thanks_dialog))
} else Crashlytics.log(Log.ERROR, TAG, "onConsumeResponse: $responseCode")
}
}

View File

@@ -1,10 +1,13 @@
package be.mygod.vpnhotspot
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.databinding.DataBindingUtil
import android.net.Uri
import android.os.Bundle
import android.os.IBinder
import android.support.customtabs.CustomTabsIntent
import android.support.design.internal.BottomNavigationMenuView
import android.support.design.widget.BottomNavigationView
import android.support.v4.app.Fragment
@@ -23,6 +26,12 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
private lateinit var binding: ActivityMainBinding
private lateinit var badge: QBadgeView
private var clients: ClientMonitorService.Binder? = null
private val customTabsIntent by lazy {
CustomTabsIntent.Builder()
.setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary))
.build()
}
fun launchUrl(url: Uri) = customTabsIntent.launchUrl(this, url)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -76,4 +85,9 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
private fun displayFragment(fragment: Fragment) =
supportFragmentManager.beginTransaction().replace(R.id.fragmentHolder, fragment).commitAllowingStateLoss()
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
supportFragmentManager.findFragmentByTag("donationsFragment")?.onActivityResult(requestCode, resultCode, data)
}
}

View File

@@ -5,8 +5,6 @@ import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.support.customtabs.CustomTabsIntent
import android.support.v4.content.ContextCompat
import android.support.v4.content.FileProvider
import android.support.v7.preference.Preference
import android.widget.Toast
@@ -26,12 +24,6 @@ import java.net.NetworkInterface
import java.net.SocketException
class SettingsPreferenceFragment : PreferenceFragmentCompat() {
private val customTabsIntent by lazy {
CustomTabsIntent.Builder()
.setToolbarColor(ContextCompat.getColor(requireContext(), R.color.colorPrimary))
.build()
}
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.preferenceDataStore = SharedPreferenceDataStore(app.pref)
addPreferencesFromResource(R.xml.pref_settings)
@@ -98,7 +90,11 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
true
}
findPreference("misc.source").setOnPreferenceClickListener {
customTabsIntent.launchUrl(requireActivity(), Uri.parse("https://github.com/Mygod/VPNHotspot"))
(activity as MainActivity).launchUrl(Uri.parse("https://github.com/Mygod/VPNHotspot"))
true
}
findPreference("misc.donate").setOnPreferenceClickListener {
EBegFragment().show(fragmentManager, "ebeg_fragment")
true
}
}

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M20,6h-2.18c0.11,-0.31 0.18,-0.65 0.18,-1 0,-1.66 -1.34,-3 -3,-3 -1.05,0 -1.96,0.54 -2.5,1.35l-0.5,0.67 -0.5,-0.68C10.96,2.54 10.05,2 9,2 7.34,2 6,3.34 6,5c0,0.35 0.07,0.69 0.18,1L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM15,4c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM9,4c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM20,19L4,19v-2h16v2zM20,14L4,14L4,8h5.08L7,10.83 8.62,12 11,8.76l1,-1.36 1,1.36L15.38,12 17,10.83 14.92,8L20,8v6z"/>
</vector>

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Based on:
~ https://github.com/PrivacyApps/donations/blob/747d36a18433c7e9329691054122a8ad337a62d2/Donations/src/main/res/layout/donations__fragment.xml
~ https://github.com/PrivacyApps/donations/blob/747d36a18433c7e9329691054122a8ad337a62d2/Donations/src/main/res/layout/donations__fragment_google.xml
~ -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isScrollContainer="true"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/donations__description"
android:textAppearance="@android:style/TextAppearance.Small" />
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:text="@string/donations__google_android_market"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:text="@string/donations__google_android_market_description"
android:textAppearance="@android:style/TextAppearance.Small" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingTop="5dp" >
<Spinner
android:id="@+id/donations__google_android_market_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:prompt="@string/donations__google_android_market_text" />
<Button
android:id="@+id/donations__google_android_market_donate_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/donations__google_android_market_donate_button" />
</LinearLayout>
</LinearLayout>
<ViewStub
android:id="@+id/donations__more_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="@layout/fragment_ebeg_more" />
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/donations__more_donate_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_misc_donate_more"/>

View File

@@ -74,6 +74,9 @@
<string name="settings_misc_logcat_summary">这种非常有用哇</string>
<string name="settings_misc_source">查看 GitHub 上的源码</string>
<string name="settings_misc_source_summary">Star, 提交 issues, 合作</string>
<string name="settings_misc_donate">捐款</string>
<string name="settings_misc_donate_summary">请给我钱</string>
<string name="settings_misc_donate_more">PayPal, Flattr 等其他方式…</string>
<string name="notification_tethering_title">VPN 共享已启用</string>
<string name="notification_channel_tethering">VPN 共享服务</string>
@@ -94,4 +97,17 @@
<string name="credentials_password_too_short" msgid="7502749986405522663">"密码至少应包含 8 个字符。"</string>
<string name="wifi_save" msgid="3331121567988522826">"保存"</string>
<string name="wifi_cancel" msgid="6763568902542968964">"取消"</string>
<!-- Based on: https://github.com/PrivacyApps/donations/blob/747d36a18433c7e9329691054122a8ad337a62d2/Donations/src/main/res/values-zh/donations__strings.xml -->
<string name="donations__button_close">关闭</string>
<string name="donations__google_android_market">Google Play 商店</string>
<string name="donations__google_android_market_not_supported_title">不支持 In-App 捐赠。</string>
<string name="donations__google_android_market_not_supported">不支持 In-App 捐赠。你的 Google Play 商店是否安装正确了呢?</string>
<string name="donations__google_android_market_donate_button">捐赠!</string>
<string name="donations__google_android_market_text">捐赠多少?</string>
<string name="donations__thanks_dialog_title">谢谢!</string>
<string name="donations__thanks_dialog">谢谢捐赠!\n非常感谢您</string>
<string name="donations__description">觉得此应用很有用?\n捐赠给该开发者以支持此应用的开发</string>
<string name="donations__google_android_market_description">Google 收取 30% 的费用</string>
</resources>

View File

@@ -79,6 +79,9 @@
<string name="settings_misc_logcat_summary">Such useful very wow</string>
<string name="settings_misc_source">View on GitHub</string>
<string name="settings_misc_source_summary">Star, submit issues and contribute</string>
<string name="settings_misc_donate">Donate</string>
<string name="settings_misc_donate_summary">I love money</string>
<string name="settings_misc_donate_more">PayPal, Flattr, more…</string>
<string name="notification_tethering_title">VPN tethering active</string>
<string name="notification_channel_tethering">VPN Tethering Service</string>
@@ -101,4 +104,16 @@
<string name="credentials_password_too_short">The password must have at least 8 characters.</string>
<string name="wifi_save">Save</string>
<string name="wifi_cancel">Cancel</string>
<!-- Based on: https://github.com/PrivacyApps/donations/blob/747d36a18433c7e9329691054122a8ad337a62d2/Donations/src/main/res/values/donations__strings.xml -->
<string name="donations__button_close">Close</string>
<string name="donations__description">Do you find this application useful?\nSupport its development by sending a donation to the developer!</string>
<string name="donations__google_android_market">Google Play Store</string>
<string name="donations__google_android_market_not_supported_title">In-App Donations are not supported.</string>
<string name="donations__google_android_market_not_supported">In-App Donations are not supported. Is Google Play Store installed correctly?</string>
<string name="donations__google_android_market_description">Google charges a fee of 30%</string>
<string name="donations__google_android_market_donate_button">Donate!</string>
<string name="donations__google_android_market_text">How much?</string>
<string name="donations__thanks_dialog_title">Thanks!</string>
<string name="donations__thanks_dialog">Thanks for donating!\nI really appreciate this!</string>
</resources>

View File

@@ -48,5 +48,10 @@
android:icon="@drawable/ic_toggle_star"
android:title="@string/settings_misc_source"
android:summary="@string/settings_misc_source_summary"/>
<Preference
android:key="misc.donate"
android:icon="@drawable/ic_action_card_giftcard"
android:title="@string/settings_misc_donate"
android:summary="@string/settings_misc_donate_summary"/>
</PreferenceCategory>
</PreferenceScreen>