1
mobile/.gitignore
vendored
1
mobile/.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
/build
|
/build
|
||||||
/debug
|
/debug
|
||||||
/release
|
/release
|
||||||
|
/google/
|
||||||
|
|
||||||
# tests aren't ready yet
|
# tests aren't ready yet
|
||||||
/src/androidTest
|
/src/androidTest
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ android {
|
|||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
resConfigs "zh-rCN"
|
resConfigs "zh-rCN"
|
||||||
versionCode 25
|
versionCode 26
|
||||||
versionName "1.3.4"
|
versionName "1.3.5"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -26,11 +26,23 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dataBinding.enabled = true
|
dataBinding.enabled = true
|
||||||
|
flavorDimensions("freedom")
|
||||||
|
productFlavors {
|
||||||
|
freedom {
|
||||||
|
dimension "freedom"
|
||||||
|
buildConfigField "boolean", "DONATIONS", "true"
|
||||||
|
}
|
||||||
|
google {
|
||||||
|
dimension "freedom"
|
||||||
|
buildConfigField "boolean", "DONATIONS", "false"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
kapt "androidx.databinding:databinding-compiler:$androidPluginVersion"
|
kapt "androidx.databinding:databinding-compiler:$androidPluginVersion"
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
implementation 'com.android.billingclient:billing:1.1'
|
||||||
implementation "com.android.support:customtabs:$supportLibraryVersion"
|
implementation "com.android.support:customtabs:$supportLibraryVersion"
|
||||||
implementation "com.android.support:design:$supportLibraryVersion"
|
implementation "com.android.support:design:$supportLibraryVersion"
|
||||||
implementation "com.android.support:preference-v14:$supportLibraryVersion"
|
implementation "com.android.support:preference-v14:$supportLibraryVersion"
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_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.BLUETOOTH"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||||
|
|||||||
103
mobile/src/main/java/be/mygod/vpnhotspot/EBegFragment.kt
Normal file
103
mobile/src/main/java/be/mygod/vpnhotspot/EBegFragment.kt
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
package be.mygod.vpnhotspot
|
package be.mygod.vpnhotspot
|
||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
|
import android.content.Intent
|
||||||
import android.content.ServiceConnection
|
import android.content.ServiceConnection
|
||||||
import android.databinding.DataBindingUtil
|
import android.databinding.DataBindingUtil
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
|
import android.support.customtabs.CustomTabsIntent
|
||||||
import android.support.design.internal.BottomNavigationMenuView
|
import android.support.design.internal.BottomNavigationMenuView
|
||||||
import android.support.design.widget.BottomNavigationView
|
import android.support.design.widget.BottomNavigationView
|
||||||
import android.support.v4.app.Fragment
|
import android.support.v4.app.Fragment
|
||||||
@@ -23,6 +26,12 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
|||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
private lateinit var badge: QBadgeView
|
private lateinit var badge: QBadgeView
|
||||||
private var clients: ClientMonitorService.Binder? = null
|
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?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -76,4 +85,9 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
|
|||||||
|
|
||||||
private fun displayFragment(fragment: Fragment) =
|
private fun displayFragment(fragment: Fragment) =
|
||||||
supportFragmentManager.beginTransaction().replace(R.id.fragmentHolder, fragment).commitAllowingStateLoss()
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import android.content.Intent
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.customtabs.CustomTabsIntent
|
|
||||||
import android.support.v4.content.ContextCompat
|
|
||||||
import android.support.v4.content.FileProvider
|
import android.support.v4.content.FileProvider
|
||||||
import android.support.v7.preference.Preference
|
import android.support.v7.preference.Preference
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@@ -26,12 +24,6 @@ import java.net.NetworkInterface
|
|||||||
import java.net.SocketException
|
import java.net.SocketException
|
||||||
|
|
||||||
class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
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?) {
|
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
preferenceManager.preferenceDataStore = SharedPreferenceDataStore(app.pref)
|
preferenceManager.preferenceDataStore = SharedPreferenceDataStore(app.pref)
|
||||||
addPreferencesFromResource(R.xml.pref_settings)
|
addPreferencesFromResource(R.xml.pref_settings)
|
||||||
@@ -98,7 +90,11 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
findPreference("misc.source").setOnPreferenceClickListener {
|
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
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
mobile/src/main/res/drawable/ic_action_card_giftcard.xml
Normal file
10
mobile/src/main/res/drawable/ic_action_card_giftcard.xml
Normal 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>
|
||||||
69
mobile/src/main/res/layout/fragment_ebeg.xml
Normal file
69
mobile/src/main/res/layout/fragment_ebeg.xml
Normal 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>
|
||||||
6
mobile/src/main/res/layout/fragment_ebeg_more.xml
Normal file
6
mobile/src/main/res/layout/fragment_ebeg_more.xml
Normal 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"/>
|
||||||
@@ -74,6 +74,9 @@
|
|||||||
<string name="settings_misc_logcat_summary">这种非常有用哇</string>
|
<string name="settings_misc_logcat_summary">这种非常有用哇</string>
|
||||||
<string name="settings_misc_source">查看 GitHub 上的源码</string>
|
<string name="settings_misc_source">查看 GitHub 上的源码</string>
|
||||||
<string name="settings_misc_source_summary">Star, 提交 issues, 合作</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_tethering_title">VPN 共享已启用</string>
|
||||||
<string name="notification_channel_tethering">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="credentials_password_too_short" msgid="7502749986405522663">"密码至少应包含 8 个字符。"</string>
|
||||||
<string name="wifi_save" msgid="3331121567988522826">"保存"</string>
|
<string name="wifi_save" msgid="3331121567988522826">"保存"</string>
|
||||||
<string name="wifi_cancel" msgid="6763568902542968964">"取消"</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>
|
</resources>
|
||||||
|
|||||||
@@ -79,6 +79,9 @@
|
|||||||
<string name="settings_misc_logcat_summary">Such useful very wow</string>
|
<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">View on GitHub</string>
|
||||||
<string name="settings_misc_source_summary">Star, submit issues and contribute</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_tethering_title">VPN tethering active</string>
|
||||||
<string name="notification_channel_tethering">VPN Tethering Service</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="credentials_password_too_short">The password must have at least 8 characters.</string>
|
||||||
<string name="wifi_save">Save</string>
|
<string name="wifi_save">Save</string>
|
||||||
<string name="wifi_cancel">Cancel</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>
|
</resources>
|
||||||
|
|||||||
@@ -48,5 +48,10 @@
|
|||||||
android:icon="@drawable/ic_toggle_star"
|
android:icon="@drawable/ic_toggle_star"
|
||||||
android:title="@string/settings_misc_source"
|
android:title="@string/settings_misc_source"
|
||||||
android:summary="@string/settings_misc_source_summary"/>
|
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>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|||||||
Reference in New Issue
Block a user