mirror of
https://github.com/M66B/NetGuard.git
synced 2025-02-22 14:21:01 +00:00
parent
7f66df9dcd
commit
9776a5b03f
13 changed files with 355 additions and 7 deletions
|
@ -8,8 +8,8 @@ android {
|
|||
applicationId "eu.faircode.netguard"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 23
|
||||
versionCode 8
|
||||
versionName "0.8"
|
||||
versionCode 9
|
||||
versionName "0.9"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="com.android.vending.BILLING" />
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.vending.billing;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* InAppBillingService is the service that provides in-app billing version 3 and beyond.
|
||||
* This service provides the following features:
|
||||
* 1. Provides a new API to get details of in-app items published for the app including
|
||||
* price, type, title and description.
|
||||
* 2. The purchase flow is synchronous and purchase information is available immediately
|
||||
* after it completes.
|
||||
* 3. Purchase information of in-app purchases is maintained within the Google Play system
|
||||
* till the purchase is consumed.
|
||||
* 4. An API to consume a purchase of an inapp item. All purchases of one-time
|
||||
* in-app items are consumable and thereafter can be purchased again.
|
||||
* 5. An API to get current purchases of the user immediately. This will not contain any
|
||||
* consumed purchases.
|
||||
*
|
||||
* All calls will give a response code with the following possible values
|
||||
* RESULT_OK = 0 - success
|
||||
* RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog
|
||||
* RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested
|
||||
* RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase
|
||||
* RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
|
||||
* RESULT_ERROR = 6 - Fatal error during the API action
|
||||
* RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
|
||||
* RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
|
||||
*/
|
||||
interface IInAppBillingService {
|
||||
/**
|
||||
* Checks support for the requested billing API version, package and in-app type.
|
||||
* Minimum API version supported by this interface is 3.
|
||||
* @param apiVersion the billing version which the app is using
|
||||
* @param packageName the package name of the calling app
|
||||
* @param type type of the in-app item being purchased "inapp" for one-time purchases
|
||||
* and "subs" for subscription.
|
||||
* @return RESULT_OK(0) on success, corresponding result code on failures
|
||||
*/
|
||||
int isBillingSupported(int apiVersion, String packageName, String type);
|
||||
|
||||
/**
|
||||
* Provides details of a list of SKUs
|
||||
* Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
|
||||
* with a list JSON strings containing the productId, price, title and description.
|
||||
* This API can be called with a maximum of 20 SKUs.
|
||||
* @param apiVersion billing API version that the Third-party is using
|
||||
* @param packageName the package name of the calling app
|
||||
* @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
|
||||
* @return Bundle containing the following key-value pairs
|
||||
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
|
||||
* failure as listed above.
|
||||
* "DETAILS_LIST" with a StringArrayList containing purchase information
|
||||
* in JSON format similar to:
|
||||
* '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00",
|
||||
* "title : "Example Title", "description" : "This is an example description" }'
|
||||
*/
|
||||
Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
|
||||
|
||||
/**
|
||||
* Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
|
||||
* the type, a unique purchase token and an optional developer payload.
|
||||
* @param apiVersion billing API version that the app is using
|
||||
* @param packageName package name of the calling app
|
||||
* @param sku the SKU of the in-app item as published in the developer console
|
||||
* @param type the type of the in-app item ("inapp" for one-time purchases
|
||||
* and "subs" for subscription).
|
||||
* @param developerPayload optional argument to be sent back with the purchase information
|
||||
* @return Bundle containing the following key-value pairs
|
||||
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
|
||||
* failure as listed above.
|
||||
* "BUY_INTENT" - PendingIntent to start the purchase flow
|
||||
*
|
||||
* The Pending intent should be launched with startIntentSenderForResult. When purchase flow
|
||||
* has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
|
||||
* If the purchase is successful, the result data will contain the following key-value pairs
|
||||
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
|
||||
* failure as listed above.
|
||||
* "INAPP_PURCHASE_DATA" - String in JSON format similar to
|
||||
* '{"orderId":"12999763169054705758.1371079406387615",
|
||||
* "packageName":"com.example.app",
|
||||
* "productId":"exampleSku",
|
||||
* "purchaseTime":1345678900000,
|
||||
* "purchaseToken" : "122333444455555",
|
||||
* "developerPayload":"example developer payload" }'
|
||||
* "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
|
||||
* was signed with the private key of the developer
|
||||
* TODO: change this to app-specific keys.
|
||||
*/
|
||||
Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
|
||||
String developerPayload);
|
||||
|
||||
/**
|
||||
* Returns the current SKUs owned by the user of the type and package name specified along with
|
||||
* purchase information and a signature of the data to be validated.
|
||||
* This will return all SKUs that have been purchased in V3 and managed items purchased using
|
||||
* V1 and V2 that have not been consumed.
|
||||
* @param apiVersion billing API version that the app is using
|
||||
* @param packageName package name of the calling app
|
||||
* @param type the type of the in-app items being requested
|
||||
* ("inapp" for one-time purchases and "subs" for subscription).
|
||||
* @param continuationToken to be set as null for the first call, if the number of owned
|
||||
* skus are too many, a continuationToken is returned in the response bundle.
|
||||
* This method can be called again with the continuation token to get the next set of
|
||||
* owned skus.
|
||||
* @return Bundle containing the following key-value pairs
|
||||
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
|
||||
* failure as listed above.
|
||||
* "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
|
||||
* "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
|
||||
* "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
|
||||
* of the purchase information
|
||||
* "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
|
||||
* next set of in-app purchases. Only set if the
|
||||
* user has more owned skus than the current list.
|
||||
*/
|
||||
Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
|
||||
|
||||
/**
|
||||
* Consume the last purchase of the given SKU. This will result in this item being removed
|
||||
* from all subsequent responses to getPurchases() and allow re-purchase of this item.
|
||||
* @param apiVersion billing API version that the app is using
|
||||
* @param packageName package name of the calling app
|
||||
* @param purchaseToken token in the purchase information JSON that identifies the purchase
|
||||
* to be consumed
|
||||
* @return 0 if consumption succeeded. Appropriate error values for failures.
|
||||
*/
|
||||
int consumePurchase(int apiVersion, String packageName, String purchaseToken);
|
||||
}
|
|
@ -1,17 +1,23 @@
|
|||
package eu.faircode.netguard;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Uri;
|
||||
import android.net.VpnService;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
|
@ -25,10 +31,16 @@ import android.view.Menu;
|
|||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.vending.billing.IInAppBillingService;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ActivityMain extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
@ -38,8 +50,13 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
private RuleAdapter adapter = null;
|
||||
private MenuItem menuSearch = null;
|
||||
private MenuItem menuNetwork = null;
|
||||
private IInAppBillingService billingService = null;
|
||||
|
||||
private static final int REQUEST_VPN = 1;
|
||||
private static final int REQUEST_DONATION = 2;
|
||||
|
||||
private static final String SKU_DONATE = "donation"; // android.test.purchased
|
||||
private static final String ACTION_DONATE = "eu.faircode.netguard.DONATE";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -109,15 +126,25 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
intentFilter.addDataScheme("package");
|
||||
registerReceiver(packageChangedReceiver, intentFilter);
|
||||
|
||||
// Connect to billing
|
||||
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
|
||||
serviceIntent.setPackage("com.android.vending");
|
||||
bindService(serviceIntent, billingConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Log.i(TAG, "Destroy");
|
||||
running = false;
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
|
||||
unregisterReceiver(connectivityChangedReceiver);
|
||||
unregisterReceiver(packageChangedReceiver);
|
||||
|
||||
if (billingConnection != null)
|
||||
unbindService(billingConnection);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
@ -140,6 +167,20 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
}
|
||||
};
|
||||
|
||||
private ServiceConnection billingConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
Log.i(TAG, "Billing disconnected");
|
||||
billingService = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
Log.i(TAG, "Billing connected");
|
||||
billingService = IInAppBillingService.Stub.asInterface(service);
|
||||
}
|
||||
};
|
||||
|
||||
private void fillApplicationList() {
|
||||
// Get recycler view
|
||||
final RecyclerView rvApplication = (RecyclerView) findViewById(R.id.rvApplication);
|
||||
|
@ -225,8 +266,8 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
menuNetwork = menu.findItem(R.id.menu_network);
|
||||
menuNetwork.setIcon(Util.isWifiActive(this) ? R.drawable.ic_network_wifi_white_24dp : R.drawable.ic_network_cell_white_24dp);
|
||||
|
||||
MenuItem menuWwifi = menu.findItem(R.id.menu_whitelist_wifi);
|
||||
menuWwifi.setChecked(prefs.getBoolean("whitelist_wifi", true));
|
||||
MenuItem menuWifi = menu.findItem(R.id.menu_whitelist_wifi);
|
||||
menuWifi.setChecked(prefs.getBoolean("whitelist_wifi", true));
|
||||
|
||||
MenuItem menuOther = menu.findItem(R.id.menu_whitelist_other);
|
||||
menuOther.setChecked(prefs.getBoolean("whitelist_other", true));
|
||||
|
@ -324,10 +365,17 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
}
|
||||
|
||||
private void menu_about() {
|
||||
// Create view
|
||||
LayoutInflater inflater = LayoutInflater.from(this);
|
||||
View view = inflater.inflate(R.layout.about, null);
|
||||
TextView tvVersion = (TextView) view.findViewById(R.id.tvVersion);
|
||||
final Button btnDonate = (Button) view.findViewById(R.id.btnDonate);
|
||||
final TextView tvThanks = (TextView) view.findViewById(R.id.tvThanks);
|
||||
|
||||
// Show version
|
||||
tvVersion.setText(Util.getSelfVersionName(this));
|
||||
|
||||
// Handle logcat
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
private short tap = 0;
|
||||
|
||||
|
@ -339,14 +387,124 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Handle donate
|
||||
btnDonate.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
try {
|
||||
// adb shell pm clear com.android.vending
|
||||
Bundle bundle = billingService.getBuyIntent(3, getPackageName(), SKU_DONATE, "inapp", "");
|
||||
Log.i(TAG, "Billing.getBuyIntent");
|
||||
Util.logBundle(TAG, bundle);
|
||||
int response = bundle.getInt("RESPONSE_CODE");
|
||||
if (response == 0) {
|
||||
PendingIntent pi = bundle.getParcelable("BUY_INTENT");
|
||||
startIntentSenderForResult(
|
||||
pi.getIntentSender(),
|
||||
REQUEST_DONATION,
|
||||
new Intent(),
|
||||
Integer.valueOf(0),
|
||||
Integer.valueOf(0),
|
||||
Integer.valueOf(0));
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
||||
Toast.makeText(ActivityMain.this, ex.toString(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Handle donated
|
||||
final BroadcastReceiver onDonated = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
btnDonate.setVisibility(View.GONE);
|
||||
tvThanks.setVisibility(View.VISIBLE);
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter iff = new IntentFilter(ACTION_DONATE);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(onDonated, iff);
|
||||
|
||||
// Show dialog
|
||||
AlertDialog dialog = new AlertDialog.Builder(this)
|
||||
.setView(view)
|
||||
.setCancelable(true).create();
|
||||
.setCancelable(true)
|
||||
.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialogInterface) {
|
||||
LocalBroadcastManager.getInstance(ActivityMain.this).unregisterReceiver(onDonated);
|
||||
}
|
||||
})
|
||||
.create();
|
||||
dialog.show();
|
||||
|
||||
// Handle SKUs
|
||||
if (billingService != null)
|
||||
new AsyncTask<Object, Object, Object>() {
|
||||
@Override
|
||||
protected Object doInBackground(Object... objects) {
|
||||
try {
|
||||
// Get available SKUs
|
||||
ArrayList<String> skuList = new ArrayList<String>();
|
||||
skuList.add(SKU_DONATE);
|
||||
Bundle query = new Bundle();
|
||||
query.putStringArrayList("ITEM_ID_LIST", skuList);
|
||||
Bundle details = billingService.getSkuDetails(3, getPackageName(), "inapp", query);
|
||||
Log.i(TAG, "Billing.getSkuDetails");
|
||||
Util.logBundle(TAG, details);
|
||||
if (details.getInt("RESPONSE_CODE") != 0)
|
||||
return null;
|
||||
|
||||
// Check available SKUs
|
||||
boolean found = false;
|
||||
for (String item : details.getStringArrayList("DETAILS_LIST")) {
|
||||
JSONObject object = new JSONObject(item);
|
||||
if (SKU_DONATE.equals(object.getString("productId"))) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Log.i(TAG, SKU_DONATE + "=" + found);
|
||||
if (!found)
|
||||
return null;
|
||||
|
||||
// Get purchases
|
||||
Bundle purchases = billingService.getPurchases(3, getPackageName(), "inapp", null);
|
||||
Log.i(TAG, "Billing.getPurchases");
|
||||
Util.logBundle(TAG, purchases);
|
||||
return (purchases.getInt("RESPONSE_CODE") == 0 ? purchases : null);
|
||||
|
||||
} catch (Throwable ex) {
|
||||
return ex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Object result) {
|
||||
if (result instanceof Throwable) {
|
||||
// Handle exception
|
||||
Throwable ex = (Throwable) result;
|
||||
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
||||
Toast.makeText(ActivityMain.this, ex.toString(), Toast.LENGTH_LONG).show();
|
||||
|
||||
} else if (result != null) {
|
||||
// Show donate/donated
|
||||
Bundle bundle = (Bundle) result;
|
||||
ArrayList<String> skus = bundle.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
|
||||
btnDonate.setVisibility(skus.contains(SKU_DONATE) ? View.GONE : View.VISIBLE);
|
||||
tvThanks.setVisibility(skus.contains(SKU_DONATE) ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Log.i(TAG, "onActivityResult request=" + requestCode + " result=" + requestCode);
|
||||
Util.logExtras(TAG, data);
|
||||
|
||||
if (requestCode == REQUEST_VPN) {
|
||||
// Update enabled state
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
@ -355,7 +513,17 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
// Start service
|
||||
if (resultCode == RESULT_OK)
|
||||
SinkholeService.start(this);
|
||||
} else
|
||||
|
||||
} else if (requestCode == REQUEST_DONATION) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
// Handle donation
|
||||
Intent intent = new Intent(ACTION_DONATE);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
} else {
|
||||
Log.w(TAG, "Unknown activity result request=" + requestCode);
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="20dp"
|
||||
android:paddingBottom="40dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingTop="20dp">
|
||||
|
@ -44,4 +44,23 @@
|
|||
android:layout_marginTop="8dp"
|
||||
android:text="@string/app_copyright"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Small" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnDonate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/title_donate"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvThanks"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/title_thanks"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Medium"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
|
@ -17,4 +17,6 @@
|
|||
|
||||
<string name="title_using">السماح عند استخدام الجهاز</string>
|
||||
<string name="title_launch">Start application</string>
|
||||
<string name="title_donate">Donate</string>
|
||||
<string name="title_thanks">Thank you for your donation!</string>
|
||||
</resources>
|
||||
|
|
|
@ -17,4 +17,6 @@
|
|||
|
||||
<string name="title_using">Allow when device in use</string>
|
||||
<string name="title_launch">Start application</string>
|
||||
<string name="title_donate">Donate</string>
|
||||
<string name="title_thanks">Thank you for your donation!</string>
|
||||
</resources>
|
||||
|
|
|
@ -17,4 +17,6 @@
|
|||
|
||||
<string name="title_using">Consenti quando il dispositivo è in uso</string>
|
||||
<string name="title_launch">Start application</string>
|
||||
<string name="title_donate">Donate</string>
|
||||
<string name="title_thanks">Thank you for your donation!</string>
|
||||
</resources>
|
||||
|
|
|
@ -17,4 +17,6 @@
|
|||
|
||||
<string name="title_using">Sta toe als apparaat in gebruik</string>
|
||||
<string name="title_launch">Start applicatie</string>
|
||||
<string name="title_donate">Doneer</string>
|
||||
<string name="title_thanks">Bedankt voor uw donatie!</string>
|
||||
</resources>
|
||||
|
|
|
@ -17,4 +17,6 @@
|
|||
|
||||
<string name="title_using">Permite cand dispozitivul este folosit</string>
|
||||
<string name="title_launch">Porneste aplicatia</string>
|
||||
<string name="title_donate">Donate</string>
|
||||
<string name="title_thanks">Thank you for your donation!</string>
|
||||
</resources>
|
||||
|
|
|
@ -17,4 +17,6 @@
|
|||
|
||||
<string name="title_using">Povoliť pri používaní zariadenia</string>
|
||||
<string name="title_launch">Start application</string>
|
||||
<string name="title_donate">Donate</string>
|
||||
<string name="title_thanks">Thank you for your donation!</string>
|
||||
</resources>
|
||||
|
|
|
@ -17,4 +17,6 @@
|
|||
|
||||
<string name="title_using">设备使用时允许运行</string>
|
||||
<string name="title_launch">启动应用</string>
|
||||
<string name="title_donate">Donate</string>
|
||||
<string name="title_thanks">Thank you for your donation!</string>
|
||||
</resources>
|
|
@ -18,4 +18,6 @@
|
|||
|
||||
<string name="title_using">Allow when device in use</string>
|
||||
<string name="title_launch">Start application</string>
|
||||
<string name="title_donate">Donate</string>
|
||||
<string name="title_thanks">Thank you for your donation!</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue