From f47542c1df669250bcf4932325820cf24354c8df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= <dominik@dominikschuermann.de> Date: Mon, 7 Nov 2016 10:55:28 +0100 Subject: [PATCH] Update build environment --- FasterGPS/build.gradle | 6 +- .../org/fastergps/ui/HelpAboutFragment.java | 2 +- .../java/org/fastergps/ui/HelpActivity.java | 6 +- .../org/fastergps/ui/HelpHtmlFragment.java | 2 +- build.gradle | 9 +- gradle/wrapper/gradle-wrapper.jar | Bin 49896 -> 52928 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 57 +- gradlew.bat | 14 +- libraries/Donations/.gitignore | 33 - libraries/Donations/build.gradle | 20 - .../Donations/src/main/AndroidManifest.xml | 13 - .../vending/billing/IInAppBillingService.aidl | 144 --- .../donations/DonationsFragment.java | 525 ---------- .../donations/google/util/Base64.java | 570 ---------- .../google/util/Base64DecoderException.java | 32 - .../donations/google/util/IabException.java | 43 - .../donations/google/util/IabHelper.java | 991 ------------------ .../donations/google/util/IabResult.java | 45 - .../donations/google/util/Inventory.java | 91 -- .../donations/google/util/Purchase.java | 63 -- .../donations/google/util/Security.java | 130 --- .../donations/google/util/SkuDetails.java | 58 - .../main/res/layout/donations__fragment.xml | 43 - .../res/layout/donations__fragment_flattr.xml | 65 -- .../res/layout/donations__fragment_google.xml | 43 - .../res/layout/donations__fragment_paypal.xml | 28 - .../main/res/values-bg/donations__strings.xml | 15 - .../main/res/values-ca/donations__strings.xml | 18 - .../main/res/values-cs/donations__strings.xml | 10 - .../res/values-da-rDK/donations__strings.xml | 18 - .../res/values-de-rDE/donations__strings.xml | 18 - .../main/res/values-el/donations__strings.xml | 15 - .../res/values-es-rES/donations__strings.xml | 18 - .../res/values-es-rMX/donations__strings.xml | 18 - .../res/values-et-rEE/donations__strings.xml | 15 - .../main/res/values-fi/donations__strings.xml | 15 - .../main/res/values-fr/donations__strings.xml | 18 - .../main/res/values-he/donations__strings.xml | 15 - .../main/res/values-hr/donations__strings.xml | 15 - .../main/res/values-hu/donations__strings.xml | 15 - .../main/res/values-id/donations__strings.xml | 18 - .../main/res/values-it/donations__strings.xml | 18 - .../res/values-iw-rIL/donations__strings.xml | 15 - .../main/res/values-ja/donations__strings.xml | 18 - .../main/res/values-km/donations__strings.xml | 2 - .../main/res/values-ko/donations__strings.xml | 2 - .../main/res/values-mn/donations__strings.xml | 4 - .../main/res/values-nl/donations__strings.xml | 18 - .../res/values-no-rNO/donations__strings.xml | 4 - .../main/res/values-pl/donations__strings.xml | 18 - .../res/values-pt-rBR/donations__strings.xml | 18 - .../res/values-ro-rRO/donations__strings.xml | 4 - .../main/res/values-ru/donations__strings.xml | 18 - .../res/values-sl-rSI/donations__strings.xml | 15 - .../main/res/values-sr/donations__strings.xml | 16 - .../main/res/values-sv/donations__strings.xml | 15 - .../main/res/values-tr/donations__strings.xml | 18 - .../main/res/values-uk/donations__strings.xml | 18 - .../res/values-vi-rVN/donations__strings.xml | 18 - .../main/res/values-vi/donations__strings.xml | 4 - .../res/values-zh-rCN/donations__strings.xml | 18 - .../res/values-zh-rHK/donations__strings.xml | 18 - .../res/values-zh-rTW/donations__strings.xml | 15 - .../main/res/values/donations__strings.xml | 21 - libraries/HtmlTextView/.gitignore | 33 - libraries/HtmlTextView/LICENSE | 202 ---- libraries/HtmlTextView/README.md | 45 - libraries/HtmlTextView/build.gradle | 16 - .../HtmlTextView/src/main/AndroidManifest.xml | 13 - .../htmltextview/HtmlTagHandler.java | 92 -- .../htmltextview/HtmlTextView.java | 83 -- .../JellyBeanSpanFixTextView.java | 212 ---- .../htmltextview/UrlImageGetter.java | 128 --- libraries/RootCommands/build.gradle | 4 +- 75 files changed, 51 insertions(+), 4370 deletions(-) delete mode 100644 libraries/Donations/.gitignore delete mode 100644 libraries/Donations/build.gradle delete mode 100644 libraries/Donations/src/main/AndroidManifest.xml delete mode 100644 libraries/Donations/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/DonationsFragment.java delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Base64.java delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Base64DecoderException.java delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabException.java delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabHelper.java delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabResult.java delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Inventory.java delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Purchase.java delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Security.java delete mode 100644 libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/SkuDetails.java delete mode 100644 libraries/Donations/src/main/res/layout/donations__fragment.xml delete mode 100644 libraries/Donations/src/main/res/layout/donations__fragment_flattr.xml delete mode 100644 libraries/Donations/src/main/res/layout/donations__fragment_google.xml delete mode 100644 libraries/Donations/src/main/res/layout/donations__fragment_paypal.xml delete mode 100644 libraries/Donations/src/main/res/values-bg/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-ca/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-cs/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-da-rDK/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-de-rDE/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-el/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-es-rES/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-es-rMX/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-et-rEE/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-fi/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-fr/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-he/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-hr/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-hu/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-id/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-it/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-iw-rIL/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-ja/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-km/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-ko/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-mn/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-nl/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-no-rNO/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-pl/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-pt-rBR/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-ro-rRO/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-ru/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-sl-rSI/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-sr/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-sv/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-tr/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-uk/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-vi-rVN/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-vi/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-zh-rCN/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-zh-rHK/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values-zh-rTW/donations__strings.xml delete mode 100644 libraries/Donations/src/main/res/values/donations__strings.xml delete mode 100644 libraries/HtmlTextView/.gitignore delete mode 100644 libraries/HtmlTextView/LICENSE delete mode 100644 libraries/HtmlTextView/README.md delete mode 100644 libraries/HtmlTextView/build.gradle delete mode 100644 libraries/HtmlTextView/src/main/AndroidManifest.xml delete mode 100644 libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/HtmlTagHandler.java delete mode 100644 libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/HtmlTextView.java delete mode 100644 libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/JellyBeanSpanFixTextView.java delete mode 100644 libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/UrlImageGetter.java diff --git a/FasterGPS/build.gradle b/FasterGPS/build.gradle index 8a13331..65dc96a 100644 --- a/FasterGPS/build.gradle +++ b/FasterGPS/build.gradle @@ -2,14 +2,14 @@ apply plugin: 'com.android.application' dependencies { compile 'com.android.support:support-v4:21.0.3' - compile project(':libraries:Donations') - compile project(':libraries:HtmlTextView') + compile 'org.sufficientlysecure:donations:2.4' + compile 'org.sufficientlysecure:html-textview:2.0' compile project(':libraries:RootCommands') } android { compileSdkVersion 21 - buildToolsVersion "21.1.2" + buildToolsVersion "25.0.0" defaultConfig { minSdkVersion 16 diff --git a/FasterGPS/src/main/java/org/fastergps/ui/HelpAboutFragment.java b/FasterGPS/src/main/java/org/fastergps/ui/HelpAboutFragment.java index 94483f4..ade3afb 100644 --- a/FasterGPS/src/main/java/org/fastergps/ui/HelpAboutFragment.java +++ b/FasterGPS/src/main/java/org/fastergps/ui/HelpAboutFragment.java @@ -58,7 +58,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa HtmlTextView aboutTextView = (HtmlTextView) view.findViewById(R.id.help_about_text); // load html into textview - aboutTextView.setHtmlFromRawResource(getActivity(), R.raw.help_about); + aboutTextView.setHtml(R.raw.help_about); // no flickering when clicking textview for Android < 4 aboutTextView.setTextColor(getResources().getColor( diff --git a/FasterGPS/src/main/java/org/fastergps/ui/HelpActivity.java b/FasterGPS/src/main/java/org/fastergps/ui/HelpActivity.java index ff73ce9..66d99e4 100644 --- a/FasterGPS/src/main/java/org/fastergps/ui/HelpActivity.java +++ b/FasterGPS/src/main/java/org/fastergps/ui/HelpActivity.java @@ -44,7 +44,7 @@ public class HelpActivity extends FragmentActivity { /** * PayPal */ - private static final String PAYPAL_USER = "dominik@dominikschuermann.de"; + private static final String PAYPAL_USER = "dominik@sufficientlysecure.org"; private static final String PAYPAL_CURRENCY_CODE = "EUR"; @@ -69,10 +69,10 @@ public void onCreate(Bundle savedInstanceState) { if (BuildConfig.DONATIONS_GOOGLE) { donationsFragment = DonationsFragment.newInstance(BuildConfig.DEBUG, true, GOOGLE_PUBKEY, GOOGLE_CATALOG, getResources().getStringArray(R.array.help_donation_google_catalog_values), false, null, null, - null, false, null, null); + null, false, null, null, false, null); } else { donationsFragment = DonationsFragment.newInstance(BuildConfig.DEBUG, false, null, null, null, true, PAYPAL_USER, - PAYPAL_CURRENCY_CODE, getString(R.string.help_donation_paypal_item), true, FLATTR_PROJECT_URL, FLATTR_URL); + PAYPAL_CURRENCY_CODE, getString(R.string.help_donation_paypal_item), true, FLATTR_PROJECT_URL, FLATTR_URL, false, null); } ft.replace(R.id.help_donations_container, donationsFragment, "donationsFragment"); diff --git a/FasterGPS/src/main/java/org/fastergps/ui/HelpHtmlFragment.java b/FasterGPS/src/main/java/org/fastergps/ui/HelpHtmlFragment.java index c67f129..37722d0 100644 --- a/FasterGPS/src/main/java/org/fastergps/ui/HelpHtmlFragment.java +++ b/FasterGPS/src/main/java/org/fastergps/ui/HelpHtmlFragment.java @@ -62,7 +62,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa layout.addView(text); // load html into textview - text.setHtmlFromRawResource(mActivity, R.raw.help); + text.setHtml(R.raw.help); // no flickering when clicking textview for Android < 4 text.setTextColor(getResources().getColor(android.R.color.secondary_text_dark_nodisable)); diff --git a/build.gradle b/build.gradle index fd84509..00e6910 100644 --- a/build.gradle +++ b/build.gradle @@ -1,19 +1,18 @@ buildscript { repositories { - mavenCentral() + jcenter() } - dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' + classpath 'com.android.tools.build:gradle:2.2.2' } } allprojects { repositories { - mavenCentral() + jcenter() } } task wrapper(type: Wrapper) { - gradleVersion = '2.2.1' + gradleVersion = '3.1' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8c0fb64a8698b08ecc4158d828ca593c4928e9dd..6ffa237849ef3607e39c3b334a92a65367962071 100644 GIT binary patch delta 46322 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 F{C{hz7Wn`G delta 43308 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0c71e76..ae2abab 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 10 15:27:10 PDT 2013 +#Fri Oct 28 14:50:17 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-bin.zip diff --git a/gradlew b/gradlew index 91a7e26..9aa616c 100755 --- a/gradlew +++ b/gradlew @@ -6,12 +6,30 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -161,4 +161,9 @@ function splitJvmOpts() { eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then + cd "$(dirname "$0")" +fi + exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat index aec9973..e95643d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/libraries/Donations/.gitignore b/libraries/Donations/.gitignore deleted file mode 100644 index afa9dfc..0000000 --- a/libraries/Donations/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -#Android specific -bin -gen -obj -libs/armeabi -lint.xml -local.properties -release.properties -ant.properties -*.class -*.apk - -#Gradle -.gradle -build -gradle.properties -gradlew -gradlew.bat -gradle - -#Maven -target -pom.xml.* - -#Eclipse -.project -.classpath -.settings -.metadata - -#IntelliJ IDEA -.idea -*.iml diff --git a/libraries/Donations/build.gradle b/libraries/Donations/build.gradle deleted file mode 100644 index 334b87c..0000000 --- a/libraries/Donations/build.gradle +++ /dev/null @@ -1,20 +0,0 @@ -apply plugin: 'android-library' - -android { - compileSdkVersion 21 - buildToolsVersion "21.1.2" - - defaultConfig { - minSdkVersion 16 - targetSdkVersion 21 - } - - // Do not abort build if lint finds errors - lintOptions { - abortOnError false - } -} - -dependencies { - compile 'com.android.support:support-v4:21.0.3' -} \ No newline at end of file diff --git a/libraries/Donations/src/main/AndroidManifest.xml b/libraries/Donations/src/main/AndroidManifest.xml deleted file mode 100644 index eeae23a..0000000 --- a/libraries/Donations/src/main/AndroidManifest.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="org.sufficientlysecure.donations" - android:versionCode="3" - android:versionName="2.1" > - - <uses-sdk - android:minSdkVersion="7" - android:targetSdkVersion="17" /> - - <application /> - -</manifest> \ No newline at end of file diff --git a/libraries/Donations/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl b/libraries/Donations/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl deleted file mode 100644 index 2a492f7..0000000 --- a/libraries/Donations/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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); -} diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/DonationsFragment.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/DonationsFragment.java deleted file mode 100644 index 9f700ad..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/DonationsFragment.java +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright (C) 2011-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * 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 org.sufficientlysecure.donations; - -import android.content.ActivityNotFoundException; -import android.view.*; -import android.widget.*; -import org.sufficientlysecure.donations.google.util.IabHelper; -import org.sufficientlysecure.donations.google.util.IabResult; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.app.AlertDialog; -import android.content.Intent; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.util.Log; -import android.view.View.OnClickListener; -import android.webkit.WebView; -import android.webkit.WebViewClient; -import android.webkit.WebView.HitTestResult; - -import android.content.DialogInterface; -import android.os.Handler; -import org.sufficientlysecure.donations.google.util.Purchase; - -public class DonationsFragment extends Fragment { - - public static final String ARG_DEBUG = "debug"; - - public static final String ARG_GOOGLE_ENABLED = "googleEnabled"; - public static final String ARG_GOOGLE_PUBKEY = "googlePubkey"; - public static final String ARG_GOOGLE_CATALOG = "googleCatalog"; - public static final String ARG_GOOGLE_CATALOG_VALUES = "googleCatalogValues"; - - public static final String ARG_PAYPAL_ENABLED = "paypalEnabled"; - public static final String ARG_PAYPAL_USER = "paypalUser"; - public static final String ARG_PAYPAL_CURRENCY_CODE = "paypalCurrencyCode"; - public static final String ARG_PAYPAL_ITEM_NAME = "mPaypalItemName"; - - public static final String ARG_FLATTR_ENABLED = "flattrEnabled"; - public static final String ARG_FLATTR_PROJECT_URL = "flattrProjectUrl"; - public static final String ARG_FLATTR_URL = "flattrUrl"; - - private static final String TAG = "Donations Library"; - - // http://developer.android.com/google/play/billing/billing_testing.html - private static final String[] CATALOG_DEBUG = new String[]{"android.test.purchased", - "android.test.canceled", "android.test.refunded", "android.test.item_unavailable"}; - - private Spinner mGoogleSpinner; - private TextView mFlattrUrlTextView; - - // Google Play helper object - private IabHelper mHelper; - - protected boolean mDebug = false; - - protected boolean mGoogleEnabled = false; - protected String mGooglePubkey = ""; - protected String[] mGgoogleCatalog = new String[]{}; - protected String[] mGoogleCatalogValues = new String[]{}; - - protected boolean mPaypalEnabled = false; - protected String mPaypalUser = ""; - protected String mPaypalCurrencyCode = ""; - protected String mPaypalItemName = ""; - - protected boolean mFlattrEnabled = false; - protected String mFlattrProjectUrl = ""; - protected String mFlattrUrl = ""; - - /** - * Instantiate DonationsFragment. - * - * @param debug You can use BuildConfig.DEBUG to propagate the debug flag from your app to the Donations library - * @param googleEnabled Enabled Google Play donations - * @param googlePubkey Your Google Play public key - * @param googleCatalog Possible item names that can be purchased from Google Play - * @param googleCatalogValues Values for the names - * @param paypalEnabled Enable PayPal donations - * @param paypalUser Your PayPal email address - * @param paypalCurrencyCode Currency code like EUR. See here for other codes: - * https://developer.paypal.com/webapps/developer/docs/classic/api/currency_codes/#id09A6G0U0GYK - * @param paypalItemName Display item name on PayPal, like "Donation for NTPSync" - * @param flattrEnabled Enable Flattr donations - * @param flattrProjectUrl The project URL used on Flattr - * @param flattrUrl The Flattr URL to your thing. NOTE: Enter without http:// - * @return DonationsFragment - */ - public static DonationsFragment newInstance(boolean debug, boolean googleEnabled, String googlePubkey, String[] googleCatalog, - String[] googleCatalogValues, boolean paypalEnabled, String paypalUser, - String paypalCurrencyCode, String paypalItemName, boolean flattrEnabled, - String flattrProjectUrl, String flattrUrl) { - DonationsFragment donationsFragment = new DonationsFragment(); - Bundle args = new Bundle(); - - args.putBoolean(ARG_DEBUG, debug); - - args.putBoolean(ARG_GOOGLE_ENABLED, googleEnabled); - args.putString(ARG_GOOGLE_PUBKEY, googlePubkey); - args.putStringArray(ARG_GOOGLE_CATALOG, googleCatalog); - args.putStringArray(ARG_GOOGLE_CATALOG_VALUES, googleCatalogValues); - - args.putBoolean(ARG_PAYPAL_ENABLED, paypalEnabled); - args.putString(ARG_PAYPAL_USER, paypalUser); - args.putString(ARG_PAYPAL_CURRENCY_CODE, paypalCurrencyCode); - args.putString(ARG_PAYPAL_ITEM_NAME, paypalItemName); - - args.putBoolean(ARG_FLATTR_ENABLED, flattrEnabled); - args.putString(ARG_FLATTR_PROJECT_URL, flattrProjectUrl); - args.putString(ARG_FLATTR_URL, flattrUrl); - - donationsFragment.setArguments(args); - return donationsFragment; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mDebug = getArguments().getBoolean(ARG_DEBUG); - - mGoogleEnabled = getArguments().getBoolean(ARG_GOOGLE_ENABLED); - mGooglePubkey = getArguments().getString(ARG_GOOGLE_PUBKEY); - mGgoogleCatalog = getArguments().getStringArray(ARG_GOOGLE_CATALOG); - mGoogleCatalogValues = getArguments().getStringArray(ARG_GOOGLE_CATALOG_VALUES); - - mPaypalEnabled = getArguments().getBoolean(ARG_PAYPAL_ENABLED); - mPaypalUser = getArguments().getString(ARG_PAYPAL_USER); - mPaypalCurrencyCode = getArguments().getString(ARG_PAYPAL_CURRENCY_CODE); - mPaypalItemName = getArguments().getString(ARG_PAYPAL_ITEM_NAME); - - mFlattrEnabled = getArguments().getBoolean(ARG_FLATTR_ENABLED); - mFlattrProjectUrl = getArguments().getString(ARG_FLATTR_PROJECT_URL); - mFlattrUrl = getArguments().getString(ARG_FLATTR_URL); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.donations__fragment, container, false); - - return view; - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - /* Flattr */ - if (mFlattrEnabled) { - // inflate flattr view into stub - ViewStub flattrViewStub = (ViewStub) getActivity().findViewById( - R.id.donations__flattr_stub); - flattrViewStub.inflate(); - - buildFlattrView(); - } - - /* Google */ - if (mGoogleEnabled) { - // inflate google view into stub - ViewStub googleViewStub = (ViewStub) getActivity().findViewById( - R.id.donations__google_stub); - googleViewStub.inflate(); - - // choose donation amount - mGoogleSpinner = (Spinner) getActivity().findViewById( - R.id.donations__google_android_market_spinner); - ArrayAdapter<CharSequence> adapter; - if (mDebug) { - adapter = new ArrayAdapter<CharSequence>(getActivity(), - android.R.layout.simple_spinner_item, CATALOG_DEBUG); - } else { - adapter = new ArrayAdapter<CharSequence>(getActivity(), - android.R.layout.simple_spinner_item, mGoogleCatalogValues); - } - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mGoogleSpinner.setAdapter(adapter); - - Button btGoogle = (Button) getActivity().findViewById( - R.id.donations__google_android_market_donate_button); - btGoogle.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - donateGoogleOnClick(v); - } - }); - - // Create the helper, passing it our context and the public key to verify signatures with - if (mDebug) - Log.d(TAG, "Creating IAB helper."); - mHelper = new IabHelper(getActivity(), mGooglePubkey); - - // enable debug logging (for a production application, you should set this to false). - mHelper.enableDebugLogging(mDebug); - - // Start setup. This is asynchronous and the specified listener - // will be called once setup completes. - if (mDebug) - Log.d(TAG, "Starting setup."); - mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { - public void onIabSetupFinished(IabResult result) { - if (mDebug) - Log.d(TAG, "Setup finished."); - - if (!result.isSuccess()) { - // Oh noes, there was a problem. - 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)); - return; - } - - // Have we been disposed of in the meantime? If so, quit. - if (mHelper == null) return; - } - }); - } - - /* PayPal */ - if (mPaypalEnabled) { - // inflate paypal view into stub - ViewStub paypalViewStub = (ViewStub) getActivity().findViewById( - R.id.donations__paypal_stub); - paypalViewStub.inflate(); - - Button btPayPal = (Button) getActivity().findViewById( - R.id.donations__paypal_donate_button); - btPayPal.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - donatePayPalOnClick(v); - } - }); - } - } - - /** - * Open dialog - * - * @param icon - * @param title - * @param message - */ - void openDialog(int icon, int title, String message) { - AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity()); - dialog.setIcon(icon); - dialog.setTitle(title); - dialog.setMessage(message); - dialog.setCancelable(true); - dialog.setNeutralButton(R.string.donations__button_close, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); - dialog.show(); - } - - /** - * Donate button executes donations based on selection in spinner - * - * @param view - */ - public void donateGoogleOnClick(View view) { - final int index; - index = mGoogleSpinner.getSelectedItemPosition(); - if (mDebug) - Log.d(TAG, "selected item in spinner: " + index); - - if (mDebug) { - // when debugging, choose android.test.x item - mHelper.launchPurchaseFlow(getActivity(), - CATALOG_DEBUG[index], IabHelper.ITEM_TYPE_INAPP, - 0, mPurchaseFinishedListener, null); - } else { - mHelper.launchPurchaseFlow(getActivity(), - mGgoogleCatalog[index], IabHelper.ITEM_TYPE_INAPP, - 0, mPurchaseFinishedListener, null); - } - } - - // Callback for when a purchase is finished - IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { - public void onIabPurchaseFinished(IabResult result, Purchase purchase) { - if (mDebug) - Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase); - - // if we were disposed of in the meantime, quit. - if (mHelper == null) return; - - if (result.isSuccess()) { - if (mDebug) - Log.d(TAG, "Purchase successful."); - - // directly consume in-app purchase, so that people can donate multiple times - mHelper.consumeAsync(purchase, mConsumeFinishedListener); - - // show thanks openDialog - openDialog(android.R.drawable.ic_dialog_info, R.string.donations__thanks_dialog_title, - getString(R.string.donations__thanks_dialog)); - } - } - }; - - // Called when consumption is complete - IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() { - public void onConsumeFinished(Purchase purchase, IabResult result) { - if (mDebug) - Log.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result); - - // if we were disposed of in the meantime, quit. - if (mHelper == null) return; - - if (result.isSuccess()) { - if (mDebug) - Log.d(TAG, "Consumption successful. Provisioning."); - } - if (mDebug) - Log.d(TAG, "End consumption flow."); - } - }; - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (mDebug) - Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data); - if (mHelper == null) return; - - // Pass on the fragment result to the helper for handling - if (!mHelper.handleActivityResult(requestCode, resultCode, data)) { - // not handled, so handle it ourselves (here's where you'd - // perform any handling of activity results not related to in-app - // billing... - super.onActivityResult(requestCode, resultCode, data); - } else { - if (mDebug) - Log.d(TAG, "onActivityResult handled by IABUtil."); - } - } - - - /** - * Donate button with PayPal by opening browser with defined URL For possible parameters see: - * https://developer.paypal.com/webapps/developer/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/ - * - * @param view - */ - public void donatePayPalOnClick(View view) { - Uri.Builder uriBuilder = new Uri.Builder(); - uriBuilder.scheme("https").authority("www.paypal.com").path("cgi-bin/webscr"); - uriBuilder.appendQueryParameter("cmd", "_donations"); - - uriBuilder.appendQueryParameter("business", mPaypalUser); - uriBuilder.appendQueryParameter("lc", "US"); - uriBuilder.appendQueryParameter("item_name", mPaypalItemName); - uriBuilder.appendQueryParameter("no_note", "1"); - // uriBuilder.appendQueryParameter("no_note", "0"); - // uriBuilder.appendQueryParameter("cn", "Note to the developer"); - uriBuilder.appendQueryParameter("no_shipping", "1"); - uriBuilder.appendQueryParameter("currency_code", mPaypalCurrencyCode); - Uri payPalUri = uriBuilder.build(); - - if (mDebug) - Log.d(TAG, "Opening the browser with the url: " + payPalUri.toString()); - - // Start your favorite browser - try { - Intent viewIntent = new Intent(Intent.ACTION_VIEW, payPalUri); - startActivity(viewIntent); - } catch (ActivityNotFoundException e) { - openDialog(android.R.drawable.ic_dialog_alert, R.string.donations__alert_dialog_title, - getString(R.string.donations__alert_dialog_no_browser)); - } - } - - /** - * Build view for Flattr. see Flattr API for more information: - * http://developers.flattr.net/button/ - */ - @SuppressLint("SetJavaScriptEnabled") - @TargetApi(11) - private void buildFlattrView() { - final FrameLayout mLoadingFrame; - final WebView mFlattrWebview; - - mFlattrWebview = (WebView) getActivity().findViewById(R.id.donations__flattr_webview); - mLoadingFrame = (FrameLayout) getActivity().findViewById(R.id.donations__loading_frame); - - // disable hardware acceleration for this webview to get transparent background working - if (Build.VERSION.SDK_INT >= 11) { - mFlattrWebview.setLayerType(View.LAYER_TYPE_SOFTWARE, null); - } - - // define own webview client to override loading behaviour - mFlattrWebview.setWebViewClient(new WebViewClient() { - /** - * Open all links in browser, not in webview - */ - @Override - public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) { - try { - view.getContext().startActivity( - new Intent(Intent.ACTION_VIEW, Uri.parse(urlNewString))); - } catch (ActivityNotFoundException e) { - openDialog(android.R.drawable.ic_dialog_alert, R.string.donations__alert_dialog_title, - getString(R.string.donations__alert_dialog_no_browser)); - } - - return false; - } - - /** - * Links in the flattr iframe should load in the browser not in the iframe itself, - * http:/ - * /stackoverflow.com/questions/5641626/how-to-get-webview-iframe-link-to-launch-the - * -browser - */ - @Override - public void onLoadResource(WebView view, String url) { - if (url.contains("flattr")) { - HitTestResult result = view.getHitTestResult(); - if (result != null && result.getType() > 0) { - try { - view.getContext().startActivity( - new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - } catch (ActivityNotFoundException e) { - openDialog(android.R.drawable.ic_dialog_alert, R.string.donations__alert_dialog_title, - getString(R.string.donations__alert_dialog_no_browser)); - } - view.stopLoading(); - } - } - } - - /** - * After loading is done, remove frame with progress circle - */ - @Override - public void onPageFinished(WebView view, String url) { - // remove loading frame, show webview - if (mLoadingFrame.getVisibility() == View.VISIBLE) { - mLoadingFrame.setVisibility(View.GONE); - mFlattrWebview.setVisibility(View.VISIBLE); - } - } - }); - - // get flattr values from xml config - String projectUrl = mFlattrProjectUrl; - String flattrUrl = this.mFlattrUrl; - - // make text white and background transparent - String htmlStart = "<html> <head><style type='text/css'>*{color: #FFFFFF; background-color: transparent;}</style>"; - - // https is not working in android 2.1 and 2.2 - String flattrScheme; - if (Build.VERSION.SDK_INT >= 9) { - flattrScheme = "https://"; - } else { - flattrScheme = "http://"; - } - - // set url of flattr link - mFlattrUrlTextView = (TextView) getActivity().findViewById(R.id.donations__flattr_url); - mFlattrUrlTextView.setText(flattrScheme + flattrUrl); - - String flattrJavascript = "<script type='text/javascript'>" - + "/* <![CDATA[ */" - + "(function() {" - + "var s = document.createElement('script'), t = document.getElementsByTagName('script')[0];" - + "s.type = 'text/javascript';" + "s.async = true;" + "s.src = '" + flattrScheme - + "api.flattr.com/js/0.6/load.js?mode=auto';" + "t.parentNode.insertBefore(s, t);" - + "})();" + "/* ]]> */" + "</script>"; - String htmlMiddle = "</head> <body> <div align='center'>"; - String flattrHtml = "<a class='FlattrButton' style='display:none;' href='" - + projectUrl - + "' target='_blank'></a> <noscript><a href='" - + flattrScheme - + flattrUrl - + "' target='_blank'> <img src='" - + flattrScheme - + "api.flattr.com/button/flattr-badge-large.png' alt='Flattr this' title='Flattr this' border='0' /></a></noscript>"; - String htmlEnd = "</div> </body> </html>"; - - String flattrCode = htmlStart + flattrJavascript + htmlMiddle + flattrHtml + htmlEnd; - - mFlattrWebview.getSettings().setJavaScriptEnabled(true); - - mFlattrWebview.loadData(flattrCode, "text/html", "utf-8"); - - // disable scroll on touch - mFlattrWebview.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - // already handled (returns true) when moving - return (motionEvent.getAction() == MotionEvent.ACTION_MOVE); - } - }); - - // make background of webview transparent - // has to be called AFTER loadData - // http://stackoverflow.com/questions/5003156/android-webview-style-background-colortransparent-ignored-on-android-2-2 - mFlattrWebview.setBackgroundColor(0x00000000); - } -} diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Base64.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Base64.java deleted file mode 100644 index df6120e..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Base64.java +++ /dev/null @@ -1,570 +0,0 @@ -// Portions copyright 2002, Google, Inc. -// -// 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 org.sufficientlysecure.donations.google.util; - -// This code was converted from code at http://iharder.sourceforge.net/base64/ -// Lots of extraneous features were removed. -/* The original code said: - * <p> - * I am placing this code in the Public Domain. Do with it as you will. - * This software comes with no guarantees or warranties but with - * plenty of well-wishing instead! - * Please visit - * <a href="http://iharder.net/xmlizable">http://iharder.net/xmlizable</a> - * periodically to check for updates or to contribute improvements. - * </p> - * - * @author Robert Harder - * @author rharder@usa.net - * @version 1.3 - */ - -/** - * Base64 converter class. This code is not a complete MIME encoder; - * it simply converts binary data to base64 data and back. - * - * <p>Note {@link CharBase64} is a GWT-compatible implementation of this - * class. - */ -public class Base64 { - /** Specify encoding (value is {@code true}). */ - public final static boolean ENCODE = true; - - /** Specify decoding (value is {@code false}). */ - public final static boolean DECODE = false; - - /** The equals sign (=) as a byte. */ - private final static byte EQUALS_SIGN = (byte) '='; - - /** The new line character (\n) as a byte. */ - private final static byte NEW_LINE = (byte) '\n'; - - /** - * The 64 valid Base64 values. - */ - private final static byte[] ALPHABET = - {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', - (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', - (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', - (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', - (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', - (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', - (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', - (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', - (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', - (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', - (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', - (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', - (byte) '9', (byte) '+', (byte) '/'}; - - /** - * The 64 valid web safe Base64 values. - */ - private final static byte[] WEBSAFE_ALPHABET = - {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', - (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', - (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', - (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', - (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', - (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', - (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', - (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', - (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', - (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', - (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', - (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', - (byte) '9', (byte) '-', (byte) '_'}; - - /** - * Translates a Base64 value to either its 6-bit reconstruction value - * or a negative number indicating some other meaning. - **/ - private final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - 62, // Plus sign at decimal 43 - -9, -9, -9, // Decimal 44 - 46 - 63, // Slash at decimal 47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' - -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9, -9 // Decimal 123 - 127 - /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ - }; - - /** The web safe decodabet */ - private final static byte[] WEBSAFE_DECODABET = - {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44 - 62, // Dash '-' sign at decimal 45 - -9, -9, // Decimal 46-47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' - -9, -9, -9, -9, // Decimal 91-94 - 63, // Underscore '_' at decimal 95 - -9, // Decimal 96 - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9, -9 // Decimal 123 - 127 - /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ - }; - - // Indicates white space in encoding - private final static byte WHITE_SPACE_ENC = -5; - // Indicates equals sign in encoding - private final static byte EQUALS_SIGN_ENC = -1; - - /** Defeats instantiation. */ - private Base64() { - } - - /* ******** E N C O D I N G M E T H O D S ******** */ - - /** - * Encodes up to three bytes of the array <var>source</var> - * and writes the resulting four Base64 bytes to <var>destination</var>. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * <var>srcOffset</var> and <var>destOffset</var>. - * This method does not check to make sure your arrays - * are large enough to accommodate <var>srcOffset</var> + 3 for - * the <var>source</var> array or <var>destOffset</var> + 4 for - * the <var>destination</var> array. - * The actual number of significant bytes in your array is - * given by <var>numSigBytes</var>. - * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param numSigBytes the number of significant bytes in your array - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @param alphabet is the encoding alphabet - * @return the <var>destination</var> array - * @since 1.3 - */ - private static byte[] encode3to4(byte[] source, int srcOffset, - int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) { - // 1 2 3 - // 01234567890123456789012345678901 Bit position - // --------000000001111111122222222 Array position from threeBytes - // --------| || || || | Six bit groups to index alphabet - // >>18 >>12 >> 6 >> 0 Right shift necessary - // 0x3f 0x3f 0x3f Additional AND - - // Create buffer with zero-padding if there are only one or two - // significant bytes passed in the array. - // We have to shift left 24 in order to flush out the 1's that appear - // when Java treats a value as negative that is cast from a byte to an int. - int inBuff = - (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) - | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) - | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); - - switch (numSigBytes) { - case 3: - destination[destOffset] = alphabet[(inBuff >>> 18)]; - destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = alphabet[(inBuff) & 0x3f]; - return destination; - case 2: - destination[destOffset] = alphabet[(inBuff >>> 18)]; - destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - case 1: - destination[destOffset] = alphabet[(inBuff >>> 18)]; - destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = EQUALS_SIGN; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - default: - return destination; - } // end switch - } // end encode3to4 - - /** - * Encodes a byte array into Base64 notation. - * Equivalent to calling - * {@code encodeBytes(source, 0, source.length)} - * - * @param source The data to convert - * @since 1.4 - */ - public static String encode(byte[] source) { - return encode(source, 0, source.length, ALPHABET, true); - } - - /** - * Encodes a byte array into web safe Base64 notation. - * - * @param source The data to convert - * @param doPadding is {@code true} to pad result with '=' chars - * if it does not fall on 3 byte boundaries - */ - public static String encodeWebSafe(byte[] source, boolean doPadding) { - return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding); - } - - /** - * Encodes a byte array into Base64 notation. - * - * @param source the data to convert - * @param off offset in array where conversion should begin - * @param len length of data to convert - * @param alphabet the encoding alphabet - * @param doPadding is {@code true} to pad result with '=' chars - * if it does not fall on 3 byte boundaries - * @since 1.4 - */ - public static String encode(byte[] source, int off, int len, byte[] alphabet, - boolean doPadding) { - byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE); - int outLen = outBuff.length; - - // If doPadding is false, set length to truncate '=' - // padding characters - while (doPadding == false && outLen > 0) { - if (outBuff[outLen - 1] != '=') { - break; - } - outLen -= 1; - } - - return new String(outBuff, 0, outLen); - } - - /** - * Encodes a byte array into Base64 notation. - * - * @param source the data to convert - * @param off offset in array where conversion should begin - * @param len length of data to convert - * @param alphabet is the encoding alphabet - * @param maxLineLength maximum length of one line. - * @return the BASE64-encoded byte array - */ - public static byte[] encode(byte[] source, int off, int len, byte[] alphabet, - int maxLineLength) { - int lenDiv3 = (len + 2) / 3; // ceil(len / 3) - int len43 = lenDiv3 * 4; - byte[] outBuff = new byte[len43 // Main 4:3 - + (len43 / maxLineLength)]; // New lines - - int d = 0; - int e = 0; - int len2 = len - 2; - int lineLength = 0; - for (; d < len2; d += 3, e += 4) { - - // The following block of code is the same as - // encode3to4( source, d + off, 3, outBuff, e, alphabet ); - // but inlined for faster encoding (~20% improvement) - int inBuff = - ((source[d + off] << 24) >>> 8) - | ((source[d + 1 + off] << 24) >>> 16) - | ((source[d + 2 + off] << 24) >>> 24); - outBuff[e] = alphabet[(inBuff >>> 18)]; - outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f]; - outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f]; - outBuff[e + 3] = alphabet[(inBuff) & 0x3f]; - - lineLength += 4; - if (lineLength == maxLineLength) { - outBuff[e + 4] = NEW_LINE; - e++; - lineLength = 0; - } // end if: end of line - } // end for: each piece of array - - if (d < len) { - encode3to4(source, d + off, len - d, outBuff, e, alphabet); - - lineLength += 4; - if (lineLength == maxLineLength) { - // Add a last newline - outBuff[e + 4] = NEW_LINE; - e++; - } - e += 4; - } - - assert (e == outBuff.length); - return outBuff; - } - - - /* ******** D E C O D I N G M E T H O D S ******** */ - - - /** - * Decodes four bytes from array <var>source</var> - * and writes the resulting bytes (up to three of them) - * to <var>destination</var>. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * <var>srcOffset</var> and <var>destOffset</var>. - * This method does not check to make sure your arrays - * are large enough to accommodate <var>srcOffset</var> + 4 for - * the <var>source</var> array or <var>destOffset</var> + 3 for - * the <var>destination</var> array. - * This method returns the actual number of bytes that - * were converted from the Base64 encoding. - * - * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @param decodabet the decodabet for decoding Base64 content - * @return the number of decoded bytes converted - * @since 1.3 - */ - private static int decode4to3(byte[] source, int srcOffset, - byte[] destination, int destOffset, byte[] decodabet) { - // Example: Dk== - if (source[srcOffset + 2] == EQUALS_SIGN) { - int outBuff = - ((decodabet[source[srcOffset]] << 24) >>> 6) - | ((decodabet[source[srcOffset + 1]] << 24) >>> 12); - - destination[destOffset] = (byte) (outBuff >>> 16); - return 1; - } else if (source[srcOffset + 3] == EQUALS_SIGN) { - // Example: DkL= - int outBuff = - ((decodabet[source[srcOffset]] << 24) >>> 6) - | ((decodabet[source[srcOffset + 1]] << 24) >>> 12) - | ((decodabet[source[srcOffset + 2]] << 24) >>> 18); - - destination[destOffset] = (byte) (outBuff >>> 16); - destination[destOffset + 1] = (byte) (outBuff >>> 8); - return 2; - } else { - // Example: DkLE - int outBuff = - ((decodabet[source[srcOffset]] << 24) >>> 6) - | ((decodabet[source[srcOffset + 1]] << 24) >>> 12) - | ((decodabet[source[srcOffset + 2]] << 24) >>> 18) - | ((decodabet[source[srcOffset + 3]] << 24) >>> 24); - - destination[destOffset] = (byte) (outBuff >> 16); - destination[destOffset + 1] = (byte) (outBuff >> 8); - destination[destOffset + 2] = (byte) (outBuff); - return 3; - } - } // end decodeToBytes - - - /** - * Decodes data from Base64 notation. - * - * @param s the string to decode (decoded in default encoding) - * @return the decoded data - * @since 1.4 - */ - public static byte[] decode(String s) throws Base64DecoderException { - byte[] bytes = s.getBytes(); - return decode(bytes, 0, bytes.length); - } - - /** - * Decodes data from web safe Base64 notation. - * Web safe encoding uses '-' instead of '+', '_' instead of '/' - * - * @param s the string to decode (decoded in default encoding) - * @return the decoded data - */ - public static byte[] decodeWebSafe(String s) throws Base64DecoderException { - byte[] bytes = s.getBytes(); - return decodeWebSafe(bytes, 0, bytes.length); - } - - /** - * Decodes Base64 content in byte array format and returns - * the decoded byte array. - * - * @param source The Base64 encoded data - * @return decoded data - * @since 1.3 - * @throws Base64DecoderException - */ - public static byte[] decode(byte[] source) throws Base64DecoderException { - return decode(source, 0, source.length); - } - - /** - * Decodes web safe Base64 content in byte array format and returns - * the decoded data. - * Web safe encoding uses '-' instead of '+', '_' instead of '/' - * - * @param source the string to decode (decoded in default encoding) - * @return the decoded data - */ - public static byte[] decodeWebSafe(byte[] source) - throws Base64DecoderException { - return decodeWebSafe(source, 0, source.length); - } - - /** - * Decodes Base64 content in byte array format and returns - * the decoded byte array. - * - * @param source the Base64 encoded data - * @param off the offset of where to begin decoding - * @param len the length of characters to decode - * @return decoded data - * @since 1.3 - * @throws Base64DecoderException - */ - public static byte[] decode(byte[] source, int off, int len) - throws Base64DecoderException { - return decode(source, off, len, DECODABET); - } - - /** - * Decodes web safe Base64 content in byte array format and returns - * the decoded byte array. - * Web safe encoding uses '-' instead of '+', '_' instead of '/' - * - * @param source the Base64 encoded data - * @param off the offset of where to begin decoding - * @param len the length of characters to decode - * @return decoded data - */ - public static byte[] decodeWebSafe(byte[] source, int off, int len) - throws Base64DecoderException { - return decode(source, off, len, WEBSAFE_DECODABET); - } - - /** - * Decodes Base64 content using the supplied decodabet and returns - * the decoded byte array. - * - * @param source the Base64 encoded data - * @param off the offset of where to begin decoding - * @param len the length of characters to decode - * @param decodabet the decodabet for decoding Base64 content - * @return decoded data - */ - public static byte[] decode(byte[] source, int off, int len, byte[] decodabet) - throws Base64DecoderException { - int len34 = len * 3 / 4; - byte[] outBuff = new byte[2 + len34]; // Upper limit on size of output - int outBuffPosn = 0; - - byte[] b4 = new byte[4]; - int b4Posn = 0; - int i = 0; - byte sbiCrop = 0; - byte sbiDecode = 0; - for (i = 0; i < len; i++) { - sbiCrop = (byte) (source[i + off] & 0x7f); // Only the low seven bits - sbiDecode = decodabet[sbiCrop]; - - if (sbiDecode >= WHITE_SPACE_ENC) { // White space Equals sign or better - if (sbiDecode >= EQUALS_SIGN_ENC) { - // An equals sign (for padding) must not occur at position 0 or 1 - // and must be the last byte[s] in the encoded value - if (sbiCrop == EQUALS_SIGN) { - int bytesLeft = len - i; - byte lastByte = (byte) (source[len - 1 + off] & 0x7f); - if (b4Posn == 0 || b4Posn == 1) { - throw new Base64DecoderException( - "invalid padding byte '=' at byte offset " + i); - } else if ((b4Posn == 3 && bytesLeft > 2) - || (b4Posn == 4 && bytesLeft > 1)) { - throw new Base64DecoderException( - "padding byte '=' falsely signals end of encoded value " - + "at offset " + i); - } else if (lastByte != EQUALS_SIGN && lastByte != NEW_LINE) { - throw new Base64DecoderException( - "encoded value has invalid trailing byte"); - } - break; - } - - b4[b4Posn++] = sbiCrop; - if (b4Posn == 4) { - outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet); - b4Posn = 0; - } - } - } else { - throw new Base64DecoderException("Bad Base64 input character at " + i - + ": " + source[i + off] + "(decimal)"); - } - } - - // Because web safe encoding allows non padding base64 encodes, we - // need to pad the rest of the b4 buffer with equal signs when - // b4Posn != 0. There can be at most 2 equal signs at the end of - // four characters, so the b4 buffer must have two or three - // characters. This also catches the case where the input is - // padded with EQUALS_SIGN - if (b4Posn != 0) { - if (b4Posn == 1) { - throw new Base64DecoderException("single trailing character at offset " - + (len - 1)); - } - b4[b4Posn++] = EQUALS_SIGN; - outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet); - } - - byte[] out = new byte[outBuffPosn]; - System.arraycopy(outBuff, 0, out, 0, outBuffPosn); - return out; - } -} diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Base64DecoderException.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Base64DecoderException.java deleted file mode 100644 index 86a8f48..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Base64DecoderException.java +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2002, Google, Inc. -// -// 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 org.sufficientlysecure.donations.google.util; - -/** - * Exception thrown when encountering an invalid Base64 input character. - * - * @author nelson - */ -public class Base64DecoderException extends Exception { - public Base64DecoderException() { - super(); - } - - public Base64DecoderException(String s) { - super(s); - } - - private static final long serialVersionUID = 1L; -} diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabException.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabException.java deleted file mode 100644 index 6bbd378..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabException.java +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2012 Google Inc. - * - * 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 org.sufficientlysecure.donations.google.util; - -/** - * Exception thrown when something went wrong with in-app billing. - * An IabException has an associated IabResult (an error). - * To get the IAB result that caused this exception to be thrown, - * call {@link #getResult()}. - */ -public class IabException extends Exception { - IabResult mResult; - - public IabException(IabResult r) { - this(r, null); - } - public IabException(int response, String message) { - this(new IabResult(response, message)); - } - public IabException(IabResult r, Exception cause) { - super(r.getMessage(), cause); - mResult = r; - } - public IabException(int response, String message, Exception cause) { - this(new IabResult(response, message), cause); - } - - /** Returns the IAB result (error) that this exception signals. */ - public IabResult getResult() { return mResult; } -} \ No newline at end of file diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabHelper.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabHelper.java deleted file mode 100644 index 1506cd6..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabHelper.java +++ /dev/null @@ -1,991 +0,0 @@ -/* Copyright (c) 2012 Google Inc. - * - * 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 org.sufficientlysecure.donations.google.util; - -import android.app.Activity; -import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentSender.SendIntentException; -import android.content.ServiceConnection; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; - -import com.android.vending.billing.IInAppBillingService; - -import org.json.JSONException; - -import java.util.ArrayList; -import java.util.List; - - -/** - * Provides convenience methods for in-app billing. You can create one instance of this - * class for your application and use it to process in-app billing operations. - * It provides synchronous (blocking) and asynchronous (non-blocking) methods for - * many common in-app billing operations, as well as automatic signature - * verification. - * - * After instantiating, you must perform setup in order to start using the object. - * To perform setup, call the {@link #startSetup} method and provide a listener; - * that listener will be notified when setup is complete, after which (and not before) - * you may call other methods. - * - * After setup is complete, you will typically want to request an inventory of owned - * items and subscriptions. See {@link #queryInventory}, {@link #queryInventoryAsync} - * and related methods. - * - * When you are done with this object, don't forget to call {@link #dispose} - * to ensure proper cleanup. This object holds a binding to the in-app billing - * service, which will leak unless you dispose of it correctly. If you created - * the object on an Activity's onCreate method, then the recommended - * place to dispose of it is the Activity's onDestroy method. - * - * A note about threading: When using this object from a background thread, you may - * call the blocking versions of methods; when using from a UI thread, call - * only the asynchronous versions and handle the results via callbacks. - * Also, notice that you can only call one asynchronous operation at a time; - * attempting to start a second asynchronous operation while the first one - * has not yet completed will result in an exception being thrown. - * - * @author Bruno Oliveira (Google) - * - */ -public class IabHelper { - // Is debug logging enabled? - boolean mDebugLog = false; - String mDebugTag = "IabHelper"; - - // Is setup done? - boolean mSetupDone = false; - - // Has this object been disposed of? (If so, we should ignore callbacks, etc) - boolean mDisposed = false; - - // Are subscriptions supported? - boolean mSubscriptionsSupported = false; - - // Is an asynchronous operation in progress? - // (only one at a time can be in progress) - boolean mAsyncInProgress = false; - - // (for logging/debugging) - // if mAsyncInProgress == true, what asynchronous operation is in progress? - String mAsyncOperation = ""; - - // Context we were passed during initialization - Context mContext; - - // Connection to the service - IInAppBillingService mService; - ServiceConnection mServiceConn; - - // The request code used to launch purchase flow - int mRequestCode; - - // The item type of the current purchase flow - String mPurchasingItemType; - - // Public key for verifying signature, in base64 encoding - String mSignatureBase64 = null; - - // Billing response codes - public static final int BILLING_RESPONSE_RESULT_OK = 0; - public static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1; - public static final int BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE = 3; - public static final int BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE = 4; - public static final int BILLING_RESPONSE_RESULT_DEVELOPER_ERROR = 5; - public static final int BILLING_RESPONSE_RESULT_ERROR = 6; - public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7; - public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8; - - // IAB Helper error codes - public static final int IABHELPER_ERROR_BASE = -1000; - public static final int IABHELPER_REMOTE_EXCEPTION = -1001; - public static final int IABHELPER_BAD_RESPONSE = -1002; - public static final int IABHELPER_VERIFICATION_FAILED = -1003; - public static final int IABHELPER_SEND_INTENT_FAILED = -1004; - public static final int IABHELPER_USER_CANCELLED = -1005; - public static final int IABHELPER_UNKNOWN_PURCHASE_RESPONSE = -1006; - public static final int IABHELPER_MISSING_TOKEN = -1007; - public static final int IABHELPER_UNKNOWN_ERROR = -1008; - public static final int IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE = -1009; - public static final int IABHELPER_INVALID_CONSUMPTION = -1010; - - // Keys for the responses from InAppBillingService - public static final String RESPONSE_CODE = "RESPONSE_CODE"; - public static final String RESPONSE_GET_SKU_DETAILS_LIST = "DETAILS_LIST"; - public static final String RESPONSE_BUY_INTENT = "BUY_INTENT"; - public static final String RESPONSE_INAPP_PURCHASE_DATA = "INAPP_PURCHASE_DATA"; - public static final String RESPONSE_INAPP_SIGNATURE = "INAPP_DATA_SIGNATURE"; - public static final String RESPONSE_INAPP_ITEM_LIST = "INAPP_PURCHASE_ITEM_LIST"; - public static final String RESPONSE_INAPP_PURCHASE_DATA_LIST = "INAPP_PURCHASE_DATA_LIST"; - public static final String RESPONSE_INAPP_SIGNATURE_LIST = "INAPP_DATA_SIGNATURE_LIST"; - public static final String INAPP_CONTINUATION_TOKEN = "INAPP_CONTINUATION_TOKEN"; - - // Item types - public static final String ITEM_TYPE_INAPP = "inapp"; - public static final String ITEM_TYPE_SUBS = "subs"; - - // some fields on the getSkuDetails response bundle - public static final String GET_SKU_DETAILS_ITEM_LIST = "ITEM_ID_LIST"; - public static final String GET_SKU_DETAILS_ITEM_TYPE_LIST = "ITEM_TYPE_LIST"; - - /** - * Creates an instance. After creation, it will not yet be ready to use. You must perform - * setup by calling {@link #startSetup} and wait for setup to complete. This constructor does not - * block and is safe to call from a UI thread. - * - * @param ctx Your application or Activity context. Needed to bind to the in-app billing service. - * @param base64PublicKey Your application's public key, encoded in base64. - * This is used for verification of purchase signatures. You can find your app's base64-encoded - * public key in your application's page on Google Play Developer Console. Note that this - * is NOT your "developer public key". - */ - public IabHelper(Context ctx, String base64PublicKey) { - mContext = ctx.getApplicationContext(); - mSignatureBase64 = base64PublicKey; - logDebug("IAB helper created."); - } - - /** - * Enables or disable debug logging through LogCat. - */ - public void enableDebugLogging(boolean enable, String tag) { - checkNotDisposed(); - mDebugLog = enable; - mDebugTag = tag; - } - - public void enableDebugLogging(boolean enable) { - checkNotDisposed(); - mDebugLog = enable; - } - - /** - * Callback for setup process. This listener's {@link #onIabSetupFinished} method is called - * when the setup process is complete. - */ - public interface OnIabSetupFinishedListener { - /** - * Called to notify that setup is complete. - * - * @param result The result of the setup process. - */ - public void onIabSetupFinished(IabResult result); - } - - /** - * Starts the setup process. This will start up the setup process asynchronously. - * You will be notified through the listener when the setup process is complete. - * This method is safe to call from a UI thread. - * - * @param listener The listener to notify when the setup process is complete. - */ - public void startSetup(final OnIabSetupFinishedListener listener) { - // If already set up, can't do it again. - checkNotDisposed(); - if (mSetupDone) throw new IllegalStateException("IAB helper is already set up."); - - // Connection to IAB service - logDebug("Starting in-app billing setup."); - mServiceConn = new ServiceConnection() { - @Override - public void onServiceDisconnected(ComponentName name) { - logDebug("Billing service disconnected."); - mService = null; - } - - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - if (mDisposed) return; - logDebug("Billing service connected."); - mService = IInAppBillingService.Stub.asInterface(service); - String packageName = mContext.getPackageName(); - try { - logDebug("Checking for in-app billing 3 support."); - - // check for in-app billing v3 support - int response = mService.isBillingSupported(3, packageName, ITEM_TYPE_INAPP); - if (response != BILLING_RESPONSE_RESULT_OK) { - if (listener != null) listener.onIabSetupFinished(new IabResult(response, - "Error checking for billing v3 support.")); - - // if in-app purchases aren't supported, neither are subscriptions. - mSubscriptionsSupported = false; - return; - } - logDebug("In-app billing version 3 supported for " + packageName); - - // check for v3 subscriptions support - response = mService.isBillingSupported(3, packageName, ITEM_TYPE_SUBS); - if (response == BILLING_RESPONSE_RESULT_OK) { - logDebug("Subscriptions AVAILABLE."); - mSubscriptionsSupported = true; - } - else { - logDebug("Subscriptions NOT AVAILABLE. Response: " + response); - } - - mSetupDone = true; - } - catch (RemoteException e) { - if (listener != null) { - listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION, - "RemoteException while setting up in-app billing.")); - } - e.printStackTrace(); - return; - } - - if (listener != null) { - listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Setup successful.")); - } - } - }; - - Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND"); - if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) { - // service available to handle that Intent - mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE); - } - else { - // no service available to handle that Intent - if (listener != null) { - listener.onIabSetupFinished( - new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE, - "Billing service unavailable on device.")); - } - } - } - - /** - * Dispose of object, releasing resources. It's very important to call this - * method when you are done with this object. It will release any resources - * used by it such as service connections. Naturally, once the object is - * disposed of, it can't be used again. - */ - public void dispose() { - logDebug("Disposing."); - mSetupDone = false; - if (mServiceConn != null) { - logDebug("Unbinding from service."); - if (mContext != null) mContext.unbindService(mServiceConn); - } - mDisposed = true; - mContext = null; - mServiceConn = null; - mService = null; - mPurchaseListener = null; - } - - private void checkNotDisposed() { - if (mDisposed) throw new IllegalStateException("IabHelper was disposed of, so it cannot be used."); - } - - /** Returns whether subscriptions are supported. */ - public boolean subscriptionsSupported() { - checkNotDisposed(); - return mSubscriptionsSupported; - } - - - /** - * Callback that notifies when a purchase is finished. - */ - public interface OnIabPurchaseFinishedListener { - /** - * Called to notify that an in-app purchase finished. If the purchase was successful, - * then the sku parameter specifies which item was purchased. If the purchase failed, - * the sku and extraData parameters may or may not be null, depending on how far the purchase - * process went. - * - * @param result The result of the purchase. - * @param info The purchase information (null if purchase failed) - */ - public void onIabPurchaseFinished(IabResult result, Purchase info); - } - - // The listener registered on launchPurchaseFlow, which we have to call back when - // the purchase finishes - OnIabPurchaseFinishedListener mPurchaseListener; - - public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) { - launchPurchaseFlow(act, sku, requestCode, listener, ""); - } - - public void launchPurchaseFlow(Activity act, String sku, int requestCode, - OnIabPurchaseFinishedListener listener, String extraData) { - launchPurchaseFlow(act, sku, ITEM_TYPE_INAPP, requestCode, listener, extraData); - } - - public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, - OnIabPurchaseFinishedListener listener) { - launchSubscriptionPurchaseFlow(act, sku, requestCode, listener, ""); - } - - public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, - OnIabPurchaseFinishedListener listener, String extraData) { - launchPurchaseFlow(act, sku, ITEM_TYPE_SUBS, requestCode, listener, extraData); - } - - /** - * Initiate the UI flow for an in-app purchase. Call this method to initiate an in-app purchase, - * which will involve bringing up the Google Play screen. The calling activity will be paused while - * the user interacts with Google Play, and the result will be delivered via the activity's - * {@link android.app.Activity#onActivityResult} method, at which point you must call - * this object's {@link #handleActivityResult} method to continue the purchase flow. This method - * MUST be called from the UI thread of the Activity. - * - * @param act The calling activity. - * @param sku The sku of the item to purchase. - * @param itemType indicates if it's a product or a subscription (ITEM_TYPE_INAPP or ITEM_TYPE_SUBS) - * @param requestCode A request code (to differentiate from other responses -- - * as in {@link android.app.Activity#startActivityForResult}). - * @param listener The listener to notify when the purchase process finishes - * @param extraData Extra data (developer payload), which will be returned with the purchase data - * when the purchase completes. This extra data will be permanently bound to that purchase - * and will always be returned when the purchase is queried. - */ - public void launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode, - OnIabPurchaseFinishedListener listener, String extraData) { - checkNotDisposed(); - checkSetupDone("launchPurchaseFlow"); - flagStartAsync("launchPurchaseFlow"); - IabResult result; - - if (itemType.equals(ITEM_TYPE_SUBS) && !mSubscriptionsSupported) { - IabResult r = new IabResult(IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE, - "Subscriptions are not available."); - flagEndAsync(); - if (listener != null) listener.onIabPurchaseFinished(r, null); - return; - } - - try { - logDebug("Constructing buy intent for " + sku + ", item type: " + itemType); - Bundle buyIntentBundle = mService.getBuyIntent(3, mContext.getPackageName(), sku, itemType, extraData); - int response = getResponseCodeFromBundle(buyIntentBundle); - if (response != BILLING_RESPONSE_RESULT_OK) { - logError("Unable to buy item, Error response: " + getResponseDesc(response)); - flagEndAsync(); - result = new IabResult(response, "Unable to buy item"); - if (listener != null) listener.onIabPurchaseFinished(result, null); - return; - } - - PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT); - logDebug("Launching buy intent for " + sku + ". Request code: " + requestCode); - mRequestCode = requestCode; - mPurchaseListener = listener; - mPurchasingItemType = itemType; - act.startIntentSenderForResult(pendingIntent.getIntentSender(), - requestCode, new Intent(), - Integer.valueOf(0), Integer.valueOf(0), - Integer.valueOf(0)); - } - catch (SendIntentException e) { - logError("SendIntentException while launching purchase flow for sku " + sku); - e.printStackTrace(); - flagEndAsync(); - - result = new IabResult(IABHELPER_SEND_INTENT_FAILED, "Failed to send intent."); - if (listener != null) listener.onIabPurchaseFinished(result, null); - } - catch (RemoteException e) { - logError("RemoteException while launching purchase flow for sku " + sku); - e.printStackTrace(); - flagEndAsync(); - - result = new IabResult(IABHELPER_REMOTE_EXCEPTION, "Remote exception while starting purchase flow"); - if (listener != null) listener.onIabPurchaseFinished(result, null); - } - } - - /** - * Handles an activity result that's part of the purchase flow in in-app billing. If you - * are calling {@link #launchPurchaseFlow}, then you must call this method from your - * Activity's {@link android.app.Activity@onActivityResult} method. This method - * MUST be called from the UI thread of the Activity. - * - * @param requestCode The requestCode as you received it. - * @param resultCode The resultCode as you received it. - * @param data The data (Intent) as you received it. - * @return Returns true if the result was related to a purchase flow and was handled; - * false if the result was not related to a purchase, in which case you should - * handle it normally. - */ - public boolean handleActivityResult(int requestCode, int resultCode, Intent data) { - IabResult result; - if (requestCode != mRequestCode) return false; - - checkNotDisposed(); - checkSetupDone("handleActivityResult"); - - // end of async purchase operation that started on launchPurchaseFlow - flagEndAsync(); - - if (data == null) { - logError("Null data in IAB activity result."); - result = new IabResult(IABHELPER_BAD_RESPONSE, "Null data in IAB result"); - if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); - return true; - } - - int responseCode = getResponseCodeFromIntent(data); - String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA); - String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE); - - if (resultCode == Activity.RESULT_OK && responseCode == BILLING_RESPONSE_RESULT_OK) { - logDebug("Successful resultcode from purchase activity."); - logDebug("Purchase data: " + purchaseData); - logDebug("Data signature: " + dataSignature); - logDebug("Extras: " + data.getExtras()); - logDebug("Expected item type: " + mPurchasingItemType); - - if (purchaseData == null || dataSignature == null) { - logError("BUG: either purchaseData or dataSignature is null."); - logDebug("Extras: " + data.getExtras().toString()); - result = new IabResult(IABHELPER_UNKNOWN_ERROR, "IAB returned null purchaseData or dataSignature"); - if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); - return true; - } - - Purchase purchase = null; - try { - purchase = new Purchase(mPurchasingItemType, purchaseData, dataSignature); - String sku = purchase.getSku(); - - // Verify signature - if (!Security.verifyPurchase(mSignatureBase64, purchaseData, dataSignature)) { - logError("Purchase signature verification FAILED for sku " + sku); - result = new IabResult(IABHELPER_VERIFICATION_FAILED, "Signature verification failed for sku " + sku); - if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, purchase); - return true; - } - logDebug("Purchase signature successfully verified."); - } - catch (JSONException e) { - logError("Failed to parse purchase data."); - e.printStackTrace(); - result = new IabResult(IABHELPER_BAD_RESPONSE, "Failed to parse purchase data."); - if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); - return true; - } - - if (mPurchaseListener != null) { - mPurchaseListener.onIabPurchaseFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Success"), purchase); - } - } - else if (resultCode == Activity.RESULT_OK) { - // result code was OK, but in-app billing response was not OK. - logDebug("Result code was OK but in-app billing response was not OK: " + getResponseDesc(responseCode)); - if (mPurchaseListener != null) { - result = new IabResult(responseCode, "Problem purchashing item."); - mPurchaseListener.onIabPurchaseFinished(result, null); - } - } - else if (resultCode == Activity.RESULT_CANCELED) { - logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode)); - result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled."); - if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); - } - else { - logError("Purchase failed. Result code: " + Integer.toString(resultCode) - + ". Response: " + getResponseDesc(responseCode)); - result = new IabResult(IABHELPER_UNKNOWN_PURCHASE_RESPONSE, "Unknown purchase response."); - if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); - } - return true; - } - - public Inventory queryInventory(boolean querySkuDetails, List<String> moreSkus) throws IabException { - return queryInventory(querySkuDetails, moreSkus, null); - } - - /** - * Queries the inventory. This will query all owned items from the server, as well as - * information on additional skus, if specified. This method may block or take long to execute. - * Do not call from a UI thread. For that, use the non-blocking version {@link #refreshInventoryAsync}. - * - * @param querySkuDetails if true, SKU details (price, description, etc) will be queried as well - * as purchase information. - * @param moreItemSkus additional PRODUCT skus to query information on, regardless of ownership. - * Ignored if null or if querySkuDetails is false. - * @param moreSubsSkus additional SUBSCRIPTIONS skus to query information on, regardless of ownership. - * Ignored if null or if querySkuDetails is false. - * @throws IabException if a problem occurs while refreshing the inventory. - */ - public Inventory queryInventory(boolean querySkuDetails, List<String> moreItemSkus, - List<String> moreSubsSkus) throws IabException { - checkNotDisposed(); - checkSetupDone("queryInventory"); - try { - Inventory inv = new Inventory(); - int r = queryPurchases(inv, ITEM_TYPE_INAPP); - if (r != BILLING_RESPONSE_RESULT_OK) { - throw new IabException(r, "Error refreshing inventory (querying owned items)."); - } - - if (querySkuDetails) { - r = querySkuDetails(ITEM_TYPE_INAPP, inv, moreItemSkus); - if (r != BILLING_RESPONSE_RESULT_OK) { - throw new IabException(r, "Error refreshing inventory (querying prices of items)."); - } - } - - // if subscriptions are supported, then also query for subscriptions - if (mSubscriptionsSupported) { - r = queryPurchases(inv, ITEM_TYPE_SUBS); - if (r != BILLING_RESPONSE_RESULT_OK) { - throw new IabException(r, "Error refreshing inventory (querying owned subscriptions)."); - } - - if (querySkuDetails) { - r = querySkuDetails(ITEM_TYPE_SUBS, inv, moreItemSkus); - if (r != BILLING_RESPONSE_RESULT_OK) { - throw new IabException(r, "Error refreshing inventory (querying prices of subscriptions)."); - } - } - } - - return inv; - } - catch (RemoteException e) { - throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while refreshing inventory.", e); - } - catch (JSONException e) { - throw new IabException(IABHELPER_BAD_RESPONSE, "Error parsing JSON response while refreshing inventory.", e); - } - } - - /** - * Listener that notifies when an inventory query operation completes. - */ - public interface QueryInventoryFinishedListener { - /** - * Called to notify that an inventory query operation completed. - * - * @param result The result of the operation. - * @param inv The inventory. - */ - public void onQueryInventoryFinished(IabResult result, Inventory inv); - } - - - /** - * Asynchronous wrapper for inventory query. This will perform an inventory - * query as described in {@link #queryInventory}, but will do so asynchronously - * and call back the specified listener upon completion. This method is safe to - * call from a UI thread. - * - * @param querySkuDetails as in {@link #queryInventory} - * @param moreSkus as in {@link #queryInventory} - * @param listener The listener to notify when the refresh operation completes. - */ - public void queryInventoryAsync(final boolean querySkuDetails, - final List<String> moreSkus, - final QueryInventoryFinishedListener listener) { - final Handler handler = new Handler(); - checkNotDisposed(); - checkSetupDone("queryInventory"); - flagStartAsync("refresh inventory"); - (new Thread(new Runnable() { - public void run() { - IabResult result = new IabResult(BILLING_RESPONSE_RESULT_OK, "Inventory refresh successful."); - Inventory inv = null; - try { - inv = queryInventory(querySkuDetails, moreSkus); - } - catch (IabException ex) { - result = ex.getResult(); - } - - flagEndAsync(); - - final IabResult result_f = result; - final Inventory inv_f = inv; - if (!mDisposed && listener != null) { - handler.post(new Runnable() { - public void run() { - listener.onQueryInventoryFinished(result_f, inv_f); - } - }); - } - } - })).start(); - } - - public void queryInventoryAsync(QueryInventoryFinishedListener listener) { - queryInventoryAsync(true, null, listener); - } - - public void queryInventoryAsync(boolean querySkuDetails, QueryInventoryFinishedListener listener) { - queryInventoryAsync(querySkuDetails, null, listener); - } - - - /** - * Consumes a given in-app product. Consuming can only be done on an item - * that's owned, and as a result of consumption, the user will no longer own it. - * This method may block or take long to return. Do not call from the UI thread. - * For that, see {@link #consumeAsync}. - * - * @param itemInfo The PurchaseInfo that represents the item to consume. - * @throws IabException if there is a problem during consumption. - */ - void consume(Purchase itemInfo) throws IabException { - checkNotDisposed(); - checkSetupDone("consume"); - - if (!itemInfo.mItemType.equals(ITEM_TYPE_INAPP)) { - throw new IabException(IABHELPER_INVALID_CONSUMPTION, - "Items of type '" + itemInfo.mItemType + "' can't be consumed."); - } - - try { - String token = itemInfo.getToken(); - String sku = itemInfo.getSku(); - if (token == null || token.equals("")) { - logError("Can't consume "+ sku + ". No token."); - throw new IabException(IABHELPER_MISSING_TOKEN, "PurchaseInfo is missing token for sku: " - + sku + " " + itemInfo); - } - - logDebug("Consuming sku: " + sku + ", token: " + token); - int response = mService.consumePurchase(3, mContext.getPackageName(), token); - if (response == BILLING_RESPONSE_RESULT_OK) { - logDebug("Successfully consumed sku: " + sku); - } - else { - logDebug("Error consuming consuming sku " + sku + ". " + getResponseDesc(response)); - throw new IabException(response, "Error consuming sku " + sku); - } - } - catch (RemoteException e) { - throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while consuming. PurchaseInfo: " + itemInfo, e); - } - } - - /** - * Callback that notifies when a consumption operation finishes. - */ - public interface OnConsumeFinishedListener { - /** - * Called to notify that a consumption has finished. - * - * @param purchase The purchase that was (or was to be) consumed. - * @param result The result of the consumption operation. - */ - public void onConsumeFinished(Purchase purchase, IabResult result); - } - - /** - * Callback that notifies when a multi-item consumption operation finishes. - */ - public interface OnConsumeMultiFinishedListener { - /** - * Called to notify that a consumption of multiple items has finished. - * - * @param purchases The purchases that were (or were to be) consumed. - * @param results The results of each consumption operation, corresponding to each - * sku. - */ - public void onConsumeMultiFinished(List<Purchase> purchases, List<IabResult> results); - } - - /** - * Asynchronous wrapper to item consumption. Works like {@link #consume}, but - * performs the consumption in the background and notifies completion through - * the provided listener. This method is safe to call from a UI thread. - * - * @param purchase The purchase to be consumed. - * @param listener The listener to notify when the consumption operation finishes. - */ - public void consumeAsync(Purchase purchase, OnConsumeFinishedListener listener) { - checkNotDisposed(); - checkSetupDone("consume"); - List<Purchase> purchases = new ArrayList<Purchase>(); - purchases.add(purchase); - consumeAsyncInternal(purchases, listener, null); - } - - /** - * Same as {@link consumeAsync}, but for multiple items at once. - * @param purchases The list of PurchaseInfo objects representing the purchases to consume. - * @param listener The listener to notify when the consumption operation finishes. - */ - public void consumeAsync(List<Purchase> purchases, OnConsumeMultiFinishedListener listener) { - checkNotDisposed(); - checkSetupDone("consume"); - consumeAsyncInternal(purchases, null, listener); - } - - /** - * Returns a human-readable description for the given response code. - * - * @param code The response code - * @return A human-readable string explaining the result code. - * It also includes the result code numerically. - */ - public static String getResponseDesc(int code) { - String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/" + - "3:Billing Unavailable/4:Item unavailable/" + - "5:Developer Error/6:Error/7:Item Already Owned/" + - "8:Item not owned").split("/"); - String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/" + - "-1002:Bad response received/" + - "-1003:Purchase signature verification failed/" + - "-1004:Send intent failed/" + - "-1005:User cancelled/" + - "-1006:Unknown purchase response/" + - "-1007:Missing token/" + - "-1008:Unknown error/" + - "-1009:Subscriptions not available/" + - "-1010:Invalid consumption attempt").split("/"); - - if (code <= IABHELPER_ERROR_BASE) { - int index = IABHELPER_ERROR_BASE - code; - if (index >= 0 && index < iabhelper_msgs.length) return iabhelper_msgs[index]; - else return String.valueOf(code) + ":Unknown IAB Helper Error"; - } - else if (code < 0 || code >= iab_msgs.length) - return String.valueOf(code) + ":Unknown"; - else - return iab_msgs[code]; - } - - - // Checks that setup was done; if not, throws an exception. - void checkSetupDone(String operation) { - if (!mSetupDone) { - logError("Illegal state for operation (" + operation + "): IAB helper is not set up."); - throw new IllegalStateException("IAB helper is not set up. Can't perform operation: " + operation); - } - } - - // Workaround to bug where sometimes response codes come as Long instead of Integer - int getResponseCodeFromBundle(Bundle b) { - Object o = b.get(RESPONSE_CODE); - if (o == null) { - logDebug("Bundle with null response code, assuming OK (known issue)"); - return BILLING_RESPONSE_RESULT_OK; - } - else if (o instanceof Integer) return ((Integer)o).intValue(); - else if (o instanceof Long) return (int)((Long)o).longValue(); - else { - logError("Unexpected type for bundle response code."); - logError(o.getClass().getName()); - throw new RuntimeException("Unexpected type for bundle response code: " + o.getClass().getName()); - } - } - - // Workaround to bug where sometimes response codes come as Long instead of Integer - int getResponseCodeFromIntent(Intent i) { - Object o = i.getExtras().get(RESPONSE_CODE); - if (o == null) { - logError("Intent with no response code, assuming OK (known issue)"); - return BILLING_RESPONSE_RESULT_OK; - } - else if (o instanceof Integer) return ((Integer)o).intValue(); - else if (o instanceof Long) return (int)((Long)o).longValue(); - else { - logError("Unexpected type for intent response code."); - logError(o.getClass().getName()); - throw new RuntimeException("Unexpected type for intent response code: " + o.getClass().getName()); - } - } - - void flagStartAsync(String operation) { - if (mAsyncInProgress) throw new IllegalStateException("Can't start async operation (" + - operation + ") because another async operation(" + mAsyncOperation + ") is in progress."); - mAsyncOperation = operation; - mAsyncInProgress = true; - logDebug("Starting async operation: " + operation); - } - - void flagEndAsync() { - logDebug("Ending async operation: " + mAsyncOperation); - mAsyncOperation = ""; - mAsyncInProgress = false; - } - - - int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException { - // Query purchases - logDebug("Querying owned items, item type: " + itemType); - logDebug("Package name: " + mContext.getPackageName()); - boolean verificationFailed = false; - String continueToken = null; - - do { - logDebug("Calling getPurchases with continuation token: " + continueToken); - Bundle ownedItems = mService.getPurchases(3, mContext.getPackageName(), - itemType, continueToken); - - int response = getResponseCodeFromBundle(ownedItems); - logDebug("Owned items response: " + String.valueOf(response)); - if (response != BILLING_RESPONSE_RESULT_OK) { - logDebug("getPurchases() failed: " + getResponseDesc(response)); - return response; - } - if (!ownedItems.containsKey(RESPONSE_INAPP_ITEM_LIST) - || !ownedItems.containsKey(RESPONSE_INAPP_PURCHASE_DATA_LIST) - || !ownedItems.containsKey(RESPONSE_INAPP_SIGNATURE_LIST)) { - logError("Bundle returned from getPurchases() doesn't contain required fields."); - return IABHELPER_BAD_RESPONSE; - } - - ArrayList<String> ownedSkus = ownedItems.getStringArrayList( - RESPONSE_INAPP_ITEM_LIST); - ArrayList<String> purchaseDataList = ownedItems.getStringArrayList( - RESPONSE_INAPP_PURCHASE_DATA_LIST); - ArrayList<String> signatureList = ownedItems.getStringArrayList( - RESPONSE_INAPP_SIGNATURE_LIST); - - for (int i = 0; i < purchaseDataList.size(); ++i) { - String purchaseData = purchaseDataList.get(i); - String signature = signatureList.get(i); - String sku = ownedSkus.get(i); - if (Security.verifyPurchase(mSignatureBase64, purchaseData, signature)) { - logDebug("Sku is owned: " + sku); - Purchase purchase = new Purchase(itemType, purchaseData, signature); - - if (TextUtils.isEmpty(purchase.getToken())) { - logWarn("BUG: empty/null token!"); - logDebug("Purchase data: " + purchaseData); - } - - // Record ownership and token - inv.addPurchase(purchase); - } - else { - logWarn("Purchase signature verification **FAILED**. Not adding item."); - logDebug(" Purchase data: " + purchaseData); - logDebug(" Signature: " + signature); - verificationFailed = true; - } - } - - continueToken = ownedItems.getString(INAPP_CONTINUATION_TOKEN); - logDebug("Continuation token: " + continueToken); - } while (!TextUtils.isEmpty(continueToken)); - - return verificationFailed ? IABHELPER_VERIFICATION_FAILED : BILLING_RESPONSE_RESULT_OK; - } - - int querySkuDetails(String itemType, Inventory inv, List<String> moreSkus) - throws RemoteException, JSONException { - logDebug("Querying SKU details."); - ArrayList<String> skuList = new ArrayList<String>(); - skuList.addAll(inv.getAllOwnedSkus(itemType)); - if (moreSkus != null) { - for (String sku : moreSkus) { - if (!skuList.contains(sku)) { - skuList.add(sku); - } - } - } - - if (skuList.size() == 0) { - logDebug("queryPrices: nothing to do because there are no SKUs."); - return BILLING_RESPONSE_RESULT_OK; - } - - Bundle querySkus = new Bundle(); - querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, skuList); - Bundle skuDetails = mService.getSkuDetails(3, mContext.getPackageName(), - itemType, querySkus); - - if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) { - int response = getResponseCodeFromBundle(skuDetails); - if (response != BILLING_RESPONSE_RESULT_OK) { - logDebug("getSkuDetails() failed: " + getResponseDesc(response)); - return response; - } - else { - logError("getSkuDetails() returned a bundle with neither an error nor a detail list."); - return IABHELPER_BAD_RESPONSE; - } - } - - ArrayList<String> responseList = skuDetails.getStringArrayList( - RESPONSE_GET_SKU_DETAILS_LIST); - - for (String thisResponse : responseList) { - SkuDetails d = new SkuDetails(itemType, thisResponse); - logDebug("Got sku details: " + d); - inv.addSkuDetails(d); - } - return BILLING_RESPONSE_RESULT_OK; - } - - - void consumeAsyncInternal(final List<Purchase> purchases, - final OnConsumeFinishedListener singleListener, - final OnConsumeMultiFinishedListener multiListener) { - final Handler handler = new Handler(); - flagStartAsync("consume"); - (new Thread(new Runnable() { - public void run() { - final List<IabResult> results = new ArrayList<IabResult>(); - for (Purchase purchase : purchases) { - try { - consume(purchase); - results.add(new IabResult(BILLING_RESPONSE_RESULT_OK, "Successful consume of sku " + purchase.getSku())); - } - catch (IabException ex) { - results.add(ex.getResult()); - } - } - - flagEndAsync(); - if (!mDisposed && singleListener != null) { - handler.post(new Runnable() { - public void run() { - singleListener.onConsumeFinished(purchases.get(0), results.get(0)); - } - }); - } - if (!mDisposed && multiListener != null) { - handler.post(new Runnable() { - public void run() { - multiListener.onConsumeMultiFinished(purchases, results); - } - }); - } - } - })).start(); - } - - void logDebug(String msg) { - if (mDebugLog) Log.d(mDebugTag, msg); - } - - void logError(String msg) { - Log.e(mDebugTag, "In-app billing error: " + msg); - } - - void logWarn(String msg) { - Log.w(mDebugTag, "In-app billing warning: " + msg); - } -} diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabResult.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabResult.java deleted file mode 100644 index 37e860b..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/IabResult.java +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2012 Google Inc. - * - * 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 org.sufficientlysecure.donations.google.util; - -/** - * Represents the result of an in-app billing operation. - * A result is composed of a response code (an integer) and possibly a - * message (String). You can get those by calling - * {@link #getResponse} and {@link #getMessage()}, respectively. You - * can also inquire whether a result is a success or a failure by - * calling {@link #isSuccess()} and {@link #isFailure()}. - */ -public class IabResult { - int mResponse; - String mMessage; - - public IabResult(int response, String message) { - mResponse = response; - if (message == null || message.trim().length() == 0) { - mMessage = IabHelper.getResponseDesc(response); - } - else { - mMessage = message + " (response: " + IabHelper.getResponseDesc(response) + ")"; - } - } - public int getResponse() { return mResponse; } - public String getMessage() { return mMessage; } - public boolean isSuccess() { return mResponse == IabHelper.BILLING_RESPONSE_RESULT_OK; } - public boolean isFailure() { return !isSuccess(); } - public String toString() { return "IabResult: " + getMessage(); } -} - diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Inventory.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Inventory.java deleted file mode 100644 index bf9c821..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Inventory.java +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (c) 2012 Google Inc. - * - * 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 org.sufficientlysecure.donations.google.util; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Represents a block of information about in-app items. - * An Inventory is returned by such methods as {@link IabHelper#queryInventory}. - */ -public class Inventory { - Map<String,SkuDetails> mSkuMap = new HashMap<String,SkuDetails>(); - Map<String,Purchase> mPurchaseMap = new HashMap<String,Purchase>(); - - Inventory() { } - - /** Returns the listing details for an in-app product. */ - public SkuDetails getSkuDetails(String sku) { - return mSkuMap.get(sku); - } - - /** Returns purchase information for a given product, or null if there is no purchase. */ - public Purchase getPurchase(String sku) { - return mPurchaseMap.get(sku); - } - - /** Returns whether or not there exists a purchase of the given product. */ - public boolean hasPurchase(String sku) { - return mPurchaseMap.containsKey(sku); - } - - /** Return whether or not details about the given product are available. */ - public boolean hasDetails(String sku) { - return mSkuMap.containsKey(sku); - } - - /** - * Erase a purchase (locally) from the inventory, given its product ID. This just - * modifies the Inventory object locally and has no effect on the server! This is - * useful when you have an existing Inventory object which you know to be up to date, - * and you have just consumed an item successfully, which means that erasing its - * purchase data from the Inventory you already have is quicker than querying for - * a new Inventory. - */ - public void erasePurchase(String sku) { - if (mPurchaseMap.containsKey(sku)) mPurchaseMap.remove(sku); - } - - /** Returns a list of all owned product IDs. */ - List<String> getAllOwnedSkus() { - return new ArrayList<String>(mPurchaseMap.keySet()); - } - - /** Returns a list of all owned product IDs of a given type */ - List<String> getAllOwnedSkus(String itemType) { - List<String> result = new ArrayList<String>(); - for (Purchase p : mPurchaseMap.values()) { - if (p.getItemType().equals(itemType)) result.add(p.getSku()); - } - return result; - } - - /** Returns a list of all purchases. */ - List<Purchase> getAllPurchases() { - return new ArrayList<Purchase>(mPurchaseMap.values()); - } - - void addSkuDetails(SkuDetails d) { - mSkuMap.put(d.getSku(), d); - } - - void addPurchase(Purchase p) { - mPurchaseMap.put(p.getSku(), p); - } -} diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Purchase.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Purchase.java deleted file mode 100644 index f877a98..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Purchase.java +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (c) 2012 Google Inc. - * - * 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 org.sufficientlysecure.donations.google.util; - -import org.json.JSONException; -import org.json.JSONObject; - -/** - * Represents an in-app billing purchase. - */ -public class Purchase { - String mItemType; // ITEM_TYPE_INAPP or ITEM_TYPE_SUBS - String mOrderId; - String mPackageName; - String mSku; - long mPurchaseTime; - int mPurchaseState; - String mDeveloperPayload; - String mToken; - String mOriginalJson; - String mSignature; - - public Purchase(String itemType, String jsonPurchaseInfo, String signature) throws JSONException { - mItemType = itemType; - mOriginalJson = jsonPurchaseInfo; - JSONObject o = new JSONObject(mOriginalJson); - mOrderId = o.optString("orderId"); - mPackageName = o.optString("packageName"); - mSku = o.optString("productId"); - mPurchaseTime = o.optLong("purchaseTime"); - mPurchaseState = o.optInt("purchaseState"); - mDeveloperPayload = o.optString("developerPayload"); - mToken = o.optString("token", o.optString("purchaseToken")); - mSignature = signature; - } - - public String getItemType() { return mItemType; } - public String getOrderId() { return mOrderId; } - public String getPackageName() { return mPackageName; } - public String getSku() { return mSku; } - public long getPurchaseTime() { return mPurchaseTime; } - public int getPurchaseState() { return mPurchaseState; } - public String getDeveloperPayload() { return mDeveloperPayload; } - public String getToken() { return mToken; } - public String getOriginalJson() { return mOriginalJson; } - public String getSignature() { return mSignature; } - - @Override - public String toString() { return "PurchaseInfo(type:" + mItemType + "):" + mOriginalJson; } -} diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Security.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Security.java deleted file mode 100644 index 29974ca..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/Security.java +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (c) 2012 Google Inc. - * - * 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 org.sufficientlysecure.donations.google.util; - -import android.text.TextUtils; -import android.util.Log; - -import org.json.JSONException; -import org.json.JSONObject; - - -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.Signature; -import java.security.SignatureException; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.X509EncodedKeySpec; - -/** - * Security-related methods. For a secure implementation, all of this code - * should be implemented on a server that communicates with the - * application on the device. For the sake of simplicity and clarity of this - * example, this code is included here and is executed on the device. If you - * must verify the purchases on the phone, you should obfuscate this code to - * make it harder for an attacker to replace the code with stubs that treat all - * purchases as verified. - */ -public class Security { - private static final String TAG = "IABUtil/Security"; - - private static final String KEY_FACTORY_ALGORITHM = "RSA"; - private static final String SIGNATURE_ALGORITHM = "SHA1withRSA"; - - /** - * Verifies that the data was signed with the given signature, and returns - * the verified purchase. The data is in JSON format and signed - * with a private key. The data also contains the {@link PurchaseState} - * and product ID of the purchase. - * @param base64PublicKey the base64-encoded public key to use for verifying. - * @param signedData the signed JSON string (signed, not encrypted) - * @param signature the signature for the data, signed with the private key - */ - public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) { - if (signedData == null) { - Log.e(TAG, "data is null"); - return false; - } - - boolean verified = false; - if (!TextUtils.isEmpty(signature)) { - PublicKey key = Security.generatePublicKey(base64PublicKey); - verified = Security.verify(key, signedData, signature); - if (!verified) { - Log.w(TAG, "signature does not match data."); - return false; - } - } - return true; - } - - /** - * Generates a PublicKey instance from a string containing the - * Base64-encoded public key. - * - * @param encodedPublicKey Base64-encoded public key - * @throws IllegalArgumentException if encodedPublicKey is invalid - */ - public static PublicKey generatePublicKey(String encodedPublicKey) { - try { - byte[] decodedKey = Base64.decode(encodedPublicKey); - KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM); - return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey)); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } catch (InvalidKeySpecException e) { - Log.e(TAG, "Invalid key specification."); - throw new IllegalArgumentException(e); - } catch (Base64DecoderException e) { - Log.e(TAG, "Base64 decoding failed."); - throw new IllegalArgumentException(e); - } - } - - /** - * Verifies that the signature from the server matches the computed - * signature on the data. Returns true if the data is correctly signed. - * - * @param publicKey public key associated with the developer account - * @param signedData signed data from server - * @param signature server signature - * @return true if the data and signature match - */ - public static boolean verify(PublicKey publicKey, String signedData, String signature) { - Signature sig; - try { - sig = Signature.getInstance(SIGNATURE_ALGORITHM); - sig.initVerify(publicKey); - sig.update(signedData.getBytes()); - if (!sig.verify(Base64.decode(signature))) { - Log.e(TAG, "Signature verification failed."); - return false; - } - return true; - } catch (NoSuchAlgorithmException e) { - Log.e(TAG, "NoSuchAlgorithmException."); - } catch (InvalidKeyException e) { - Log.e(TAG, "Invalid key specification."); - } catch (SignatureException e) { - Log.e(TAG, "Signature exception."); - } catch (Base64DecoderException e) { - Log.e(TAG, "Base64 decoding failed."); - } - return false; - } -} diff --git a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/SkuDetails.java b/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/SkuDetails.java deleted file mode 100644 index 236221a..0000000 --- a/libraries/Donations/src/main/java/org/sufficientlysecure/donations/google/util/SkuDetails.java +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2012 Google Inc. - * - * 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 org.sufficientlysecure.donations.google.util; - -import org.json.JSONException; -import org.json.JSONObject; - -/** - * Represents an in-app product's listing details. - */ -public class SkuDetails { - String mItemType; - String mSku; - String mType; - String mPrice; - String mTitle; - String mDescription; - String mJson; - - public SkuDetails(String jsonSkuDetails) throws JSONException { - this(IabHelper.ITEM_TYPE_INAPP, jsonSkuDetails); - } - - public SkuDetails(String itemType, String jsonSkuDetails) throws JSONException { - mItemType = itemType; - mJson = jsonSkuDetails; - JSONObject o = new JSONObject(mJson); - mSku = o.optString("productId"); - mType = o.optString("type"); - mPrice = o.optString("price"); - mTitle = o.optString("title"); - mDescription = o.optString("description"); - } - - public String getSku() { return mSku; } - public String getType() { return mType; } - public String getPrice() { return mPrice; } - public String getTitle() { return mTitle; } - public String getDescription() { return mDescription; } - - @Override - public String toString() { - return "SkuDetails:" + mJson; - } -} diff --git a/libraries/Donations/src/main/res/layout/donations__fragment.xml b/libraries/Donations/src/main/res/layout/donations__fragment.xml deleted file mode 100644 index a540012..0000000 --- a/libraries/Donations/src/main/res/layout/donations__fragment.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<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="15dp" - android:scrollbars="vertical" > - - <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" /> - - <ViewStub - android:id="@+id/donations__flattr_stub" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:inflatedId="@+id/donations__flattr" - android:layout="@layout/donations__fragment_flattr" /> - - <ViewStub - android:id="@+id/donations__google_stub" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:inflatedId="@+id/donations__google" - android:layout="@layout/donations__fragment_google" /> - - <ViewStub - android:id="@+id/donations__paypal_stub" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:inflatedId="@+id/donations__paypal" - android:layout="@layout/donations__fragment_paypal" /> - </LinearLayout> - -</ScrollView> \ No newline at end of file diff --git a/libraries/Donations/src/main/res/layout/donations__fragment_flattr.xml b/libraries/Donations/src/main/res/layout/donations__fragment_flattr.xml deleted file mode 100644 index cf86537..0000000 --- a/libraries/Donations/src/main/res/layout/donations__fragment_flattr.xml +++ /dev/null @@ -1,65 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - 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__flattr" - 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__flattr_description" - android:textAppearance="@android:style/TextAppearance.Small" /> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal" > - - <WebView - android:id="@+id/donations__flattr_webview" - android:layout_width="65dip" - android:layout_height="70dip" - android:layout_gravity="center" - android:scrollbars="none" - android:visibility="gone" /> - - <FrameLayout - android:id="@+id/donations__loading_frame" - android:layout_width="65dip" - android:layout_height="70dip" - android:layout_gravity="center" > - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" > - - <ProgressBar - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" /> - </LinearLayout> - </FrameLayout> - - <TextView - android:id="@+id/donations__flattr_url" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:autoLink="web" - android:paddingBottom="5dp" - android:paddingLeft="10dp" - android:paddingTop="5dp" - android:textAppearance="@android:style/TextAppearance.Small" /> - </LinearLayout> - -</LinearLayout> \ No newline at end of file diff --git a/libraries/Donations/src/main/res/layout/donations__fragment_google.xml b/libraries/Donations/src/main/res/layout/donations__fragment_google.xml deleted file mode 100644 index e6ef998..0000000 --- a/libraries/Donations/src/main/res/layout/donations__fragment_google.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - 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> \ No newline at end of file diff --git a/libraries/Donations/src/main/res/layout/donations__fragment_paypal.xml b/libraries/Donations/src/main/res/layout/donations__fragment_paypal.xml deleted file mode 100644 index 9a60ada..0000000 --- a/libraries/Donations/src/main/res/layout/donations__fragment_paypal.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - 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__paypal" - 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__paypal_description" - android:textAppearance="@android:style/TextAppearance.Small" /> - - <Button - android:id="@+id/donations__paypal_donate_button" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/donations__google_android_market_donate_button" /> - -</LinearLayout> \ No newline at end of file diff --git a/libraries/Donations/src/main/res/values-bg/donations__strings.xml b/libraries/Donations/src/main/res/values-bg/donations__strings.xml deleted file mode 100644 index ca85dd2..0000000 --- a/libraries/Donations/src/main/res/values-bg/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Затвори</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">Flattr взема 10% като месечна такса!</string> - <string name="donations__google_android_market">Google Play магазин</string> - <string name="donations__google_android_market_not_supported">Дарения чрез приложението не се поддържат. Инсталиран ли е правилно магазина Google Play?</string> - <string name="donations__google_android_market_description">Google взема 30% от всяко дарение!</string> - <string name="donations__google_android_market_donate_button">Дарете!</string> - <string name="donations__google_android_market_text">Колко?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Можете да изберете колко искате да дарите след натискане на бутона!</string> - <string name="donations__thanks_dialog_title">Благодаря!</string> - <string name="donations__thanks_dialog">Благодаря ви за дарението!\nНаистина оценявам това!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-ca/donations__strings.xml b/libraries/Donations/src/main/res/values-ca/donations__strings.xml deleted file mode 100644 index a538710..0000000 --- a/libraries/Donations/src/main/res/values-ca/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Tanca</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Has trobat útil aquesta aplicació?\nAjuda al seu desenvolupament enviant una donació al creador!</string> - <string name="donations__flattr_description">Flattr té unes comissions mensuals del deu percent!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">No es poden fer donatius des de l\'aplicació. Heu instal·lat Google Play Store correctament?</string> - <string name="donations__google_android_market_description">Google té unes comissions del 30 percent!</string> - <string name="donations__google_android_market_donate_button">Fer un donatiu</string> - <string name="donations__google_android_market_text">Quant?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Podeu escollir la quantitat del vostre donatiu tocant aquest botó.</string> - <string name="donations__thanks_dialog_title">Gràcies!</string> - <string name="donations__thanks_dialog">Gràcies per fer el donatiu!⏎ N\'estic molt agraït!</string> - <string name="donations__alert_dialog_title">S\'ha produït un error</string> - <string name="donations__alert_dialog_no_browser">No s\'ha trobat cap navegador per obrir el lloc web!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-cs/donations__strings.xml b/libraries/Donations/src/main/res/values-cs/donations__strings.xml deleted file mode 100644 index 85519a5..0000000 --- a/libraries/Donations/src/main/res/values-cs/donations__strings.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Zavřít</string> - <string name="donations__google_android_market">Google Play</string> - <string name="donations__google_android_market_donate_button">Podpořte nás!</string> - <string name="donations__google_android_market_text">Kolik to stojí?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__thanks_dialog_title">Díky!</string> - <string name="donations__thanks_dialog">Díky za darování!\nOpravdu si toho vážím!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-da-rDK/donations__strings.xml b/libraries/Donations/src/main/res/values-da-rDK/donations__strings.xml deleted file mode 100644 index a5c54e0..0000000 --- a/libraries/Donations/src/main/res/values-da-rDK/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Luk</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Finder du denne app brugbar?\nSupporter dets udvikling ved at sende en donation til udvikleren!</string> - <string name="donations__flattr_description">Flattr tager 10% i månedlig gebyr!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">In-App donationer er ikke supporteret. Er Google Play Store installeret korrekt?</string> - <string name="donations__google_android_market_description">Google tager 30% fra hver donation!</string> - <string name="donations__google_android_market_donate_button">Donér!</string> - <string name="donations__google_android_market_text">Hvor meget?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Du kan vælge hvor meget du vil donere efter du har trykket på knappen</string> - <string name="donations__thanks_dialog_title">Tak!</string> - <string name="donations__thanks_dialog">Tak fordi du donerede!\nJeg sætter virkelig pris på dette!</string> - <string name="donations__alert_dialog_title">En fejl opstod</string> - <string name="donations__alert_dialog_no_browser">Ingen browser blev fundet til at åbne en webside!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-de-rDE/donations__strings.xml b/libraries/Donations/src/main/res/values-de-rDE/donations__strings.xml deleted file mode 100644 index ff57433..0000000 --- a/libraries/Donations/src/main/res/values-de-rDE/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Schließen</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Findest die diese Anwendung nützlich?\nUnterstütze die Entwicklung indem Du sie flatterst oder spendest.</string> - <string name="donations__flattr_description">Flattr behält 10 % als monatliche Gebühr ein!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">In-App-Spenden werden nicht unterstützt. Ist der Google Play Store korrekt installiert?</string> - <string name="donations__google_android_market_description">30 % jeder Spende geht an Google!</string> - <string name="donations__google_android_market_donate_button">Spende!</string> - <string name="donations__google_android_market_text">Wie viel?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Du kannst auswählen wie viel Du spenden möchtest, nachdem Du auf den Button geklickt hast!</string> - <string name="donations__thanks_dialog_title">Danke!</string> - <string name="donations__thanks_dialog">Danke für die Spende!\nIch weiß es wirklich zu schätzen!</string> - <string name="donations__alert_dialog_title">Fehler aufgetreten</string> - <string name="donations__alert_dialog_no_browser">Kein Browser gefunden um eine Webseite zu öffnen!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-el/donations__strings.xml b/libraries/Donations/src/main/res/values-el/donations__strings.xml deleted file mode 100644 index 94d295d..0000000 --- a/libraries/Donations/src/main/res/values-el/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Κλείσιμο</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">Το Flattr παίρνει 10 % σαν μηνιαίο τέλος!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">Δεν υποστηρίζονται In-App δωρεές. Έχει εγκατασταθεί σωστά το Google Play Store;</string> - <string name="donations__google_android_market_description">Το Google παίρνει το 30 % κάθε δωρεάς!</string> - <string name="donations__google_android_market_donate_button">Δωρίστε!</string> - <string name="donations__google_android_market_text">Πόσο;</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Μπορείς να επιλέξεις πόσα θέλεις να δωρίσεις αφού πατήσεις το κουμπί!</string> - <string name="donations__thanks_dialog_title">Ευχαριστώ!</string> - <string name="donations__thanks_dialog">Ευχαριστώ για την δωρεά!\n\nΠραγματικά το εκτιμώ!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-es-rES/donations__strings.xml b/libraries/Donations/src/main/res/values-es-rES/donations__strings.xml deleted file mode 100644 index 695853e..0000000 --- a/libraries/Donations/src/main/res/values-es-rES/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Cerrar</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">¿Le resulta útil esta aplicación? \nApoye su desarrollo mediante el envío de una donación al desarrollador!</string> - <string name="donations__flattr_description">¡Flattr toma un 10% como cuota mensual!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">No se admiten Donaciones In-App. ¿Está Google Play Store instalado correctamente?</string> - <string name="donations__google_android_market_description">¡Google se queda el 30% de todas las donaciones!</string> - <string name="donations__google_android_market_donate_button">¡Donar!</string> - <string name="donations__google_android_market_text">¿Cuánto?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">¡Puedes elegir cuánto quieres donar después de pulsar el botón!</string> - <string name="donations__thanks_dialog_title">¡Gracias!</string> - <string name="donations__thanks_dialog">¡Gracias por donar!\n¡Te lo agradezco mucho!</string> - <string name="donations__alert_dialog_title">Se produjó un error</string> - <string name="donations__alert_dialog_no_browser">No se encontró un navegador para abrir una página web!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-es-rMX/donations__strings.xml b/libraries/Donations/src/main/res/values-es-rMX/donations__strings.xml deleted file mode 100644 index e5ceaa9..0000000 --- a/libraries/Donations/src/main/res/values-es-rMX/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Cerrar</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Encuentras útil esta aplicación ?\nApoya su desarrollo enviando una donación al desarrollador!</string> - <string name="donations__flattr_description">¡Flattr toma 10% como cargo mensual!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">Las donaciones In-App no están soportadas. ¿Está la Tienda de Google Play instalada correctamente?</string> - <string name="donations__google_android_market_description">¡Google se queda con el 30% de cada donación!</string> - <string name="donations__google_android_market_donate_button">¡Donar!</string> - <string name="donations__google_android_market_text">¿Cuánto?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">¡Puedes escoger cuánto deseas donar después de dar clic en el botón!</string> - <string name="donations__thanks_dialog_title">Gracias!</string> - <string name="donations__thanks_dialog">Gracias por donar!\nRealmente aprecio esto!</string> - <string name="donations__alert_dialog_title">Ocurrió un error</string> - <string name="donations__alert_dialog_no_browser">No se encontró un navegador para abrir el sitio web!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-et-rEE/donations__strings.xml b/libraries/Donations/src/main/res/values-et-rEE/donations__strings.xml deleted file mode 100644 index cf98591..0000000 --- a/libraries/Donations/src/main/res/values-et-rEE/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Sulge</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">Flattr võtab 10% igakuist tasu!</string> - <string name="donations__google_android_market">Google Play pood</string> - <string name="donations__google_android_market_not_supported">Annetused rakenduse sees ei ole toetatud. Kas Google Play pood on korrektselt paigaldatud?</string> - <string name="donations__google_android_market_description">Google võtab 30% igalt annetuselt!</string> - <string name="donations__google_android_market_donate_button">Anneta!</string> - <string name="donations__google_android_market_text">Kui palju?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Sellel nupul klikates saad valida kui palju soovid annetada!</string> - <string name="donations__thanks_dialog_title">Tänan!</string> - <string name="donations__thanks_dialog">Tänan annetamast! \nHindan seda väga!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-fi/donations__strings.xml b/libraries/Donations/src/main/res/values-fi/donations__strings.xml deleted file mode 100644 index 55432cd..0000000 --- a/libraries/Donations/src/main/res/values-fi/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Sulje</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">Flattr ottaa 10% kuukausipalkkiosta!</string> - <string name="donations__google_android_market">Googlen Android Market</string> - <string name="donations__google_android_market_not_supported">Sovelluksen sisäiset lahjoitukset eivät ole tuettu. Löytyykö laitteesta Android Market?</string> - <string name="donations__google_android_market_description">Gogle ottaa 30% jokaisesta lahjoituksesta!</string> - <string name="donations__google_android_market_donate_button">Lahjoita!</string> - <string name="donations__google_android_market_text">Kuinka paljon?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Voit valita, kuinka paljon haluat lahjoittaa painikkeen napsauttamisen jälkeen!</string> - <string name="donations__thanks_dialog_title">Kiitos!</string> - <string name="donations__thanks_dialog">Kiitos lahjoituksestasi!\nArvostan sitä suuresti!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-fr/donations__strings.xml b/libraries/Donations/src/main/res/values-fr/donations__strings.xml deleted file mode 100644 index 882a319..0000000 --- a/libraries/Donations/src/main/res/values-fr/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Fermer</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Cette application vous rend service ?\nParticiper à son développement en effectuant un don !</string> - <string name="donations__flattr_description">Flattr prend 10% de frais mensuels !</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">Donations In-App non-supportées. L\'application Google Play Store est-elle correctement installée ?</string> - <string name="donations__google_android_market_description">Google prend 30% sur chaque don ! </string> - <string name="donations__google_android_market_donate_button">Faites un don !</string> - <string name="donations__google_android_market_text">Combien ?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Vous pouvez faire un don du montant désiré en cliquant sur ce bouton !</string> - <string name="donations__thanks_dialog_title">Merci !</string> - <string name="donations__thanks_dialog">Merci beaucoup pour votre don ! </string> - <string name="donations__alert_dialog_title">Une erreur est survenue</string> - <string name="donations__alert_dialog_no_browser">Aucun navigateur web n\'a été trouvé pour ouvrir le site web !</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-he/donations__strings.xml b/libraries/Donations/src/main/res/values-he/donations__strings.xml deleted file mode 100644 index 432356b..0000000 --- a/libraries/Donations/src/main/res/values-he/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">לא נמצא Busybox. כדי להתקין אותו מהמרקט לחץ על הלחצן מתחת.</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">Flattr מספר הנחה של 10 % לתשלום החודשי!</string> - <string name="donations__google_android_market">אנדרואיד מרקט</string> - <string name="donations__google_android_market_not_supported">תרומות לתוכנה אינם נתמכות. האם המרקט של גוגל אנדרואיד מותקן כראוי?</string> - <string name="donations__google_android_market_description">גוגל מקבלת 30% מסך התרומה!</string> - <string name="donations__google_android_market_donate_button">תרומה!</string> - <string name="donations__google_android_market_text">כמה?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">אתה יכול לבחור כמה אתה רוצה לתרום על ידי לחיצה על הכפתור!</string> - <string name="donations__thanks_dialog_title">תודה!</string> - <string name="donations__thanks_dialog">תודה על תרומתך!\nאני מאוד מעריך זאת!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-hr/donations__strings.xml b/libraries/Donations/src/main/res/values-hr/donations__strings.xml deleted file mode 100644 index 13106fc..0000000 --- a/libraries/Donations/src/main/res/values-hr/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Zatvori</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">Flatter uzima 10% iznosa donacije kao mjesečnu članarinu!</string> - <string name="donations__google_android_market">Google Play Trgovina</string> - <string name="donations__google_android_market_not_supported">Donacije unutar aplikacije nisu podržane. Je li Google Play Trgovina ispravno instalirana?</string> - <string name="donations__google_android_market_description">Google uzima 30% od svake donacije!</string> - <string name="donations__google_android_market_donate_button">Donirajte!</string> - <string name="donations__google_android_market_text">Koliko?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Možete izabrati koliko želite donirati nakon pritiska na gumb.</string> - <string name="donations__thanks_dialog_title">Hvala!</string> - <string name="donations__thanks_dialog">Hvala za donaciju!\n Stvarno cijenim ovo!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-hu/donations__strings.xml b/libraries/Donations/src/main/res/values-hu/donations__strings.xml deleted file mode 100644 index 51ab5e1..0000000 --- a/libraries/Donations/src/main/res/values-hu/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Bezár</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">A Flattr 10 %-ot levesz havi díjként!</string> - <string name="donations__google_android_market">Google Android Market</string> - <string name="donations__google_android_market_not_supported">Az alkalmazáson belüli adományozás nem támogatott. A Google Android Market megfelelően van telepítve?</string> - <string name="donations__google_android_market_description">A Google része 30 % minden adományból!</string> - <string name="donations__google_android_market_donate_button">Adományozok!</string> - <string name="donations__google_android_market_text">Mennyi?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Az adományozott összeget megválaszthatja a gombra való kattintás után.</string> - <string name="donations__thanks_dialog_title">Köszönöm!</string> - <string name="donations__thanks_dialog">Köszönjük a támogatást!\nNagyra értékeljük!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-id/donations__strings.xml b/libraries/Donations/src/main/res/values-id/donations__strings.xml deleted file mode 100644 index 9e0becd..0000000 --- a/libraries/Donations/src/main/res/values-id/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Tutup</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Apakah aplikasi ini berguna?\nDukung pengembangan aplikasi dengan memberikan donasi!</string> - <string name="donations__flattr_description">Flattr mengambil 10 % sebagai biaya bulanan!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">Donasi di dalam aplikasi tidak didukung. apakah Google Play Store terpasang dengan benar?</string> - <string name="donations__google_android_market_description">Google mengambil 30 % dari setiap donasi!</string> - <string name="donations__google_android_market_donate_button">Donasi!</string> - <string name="donations__google_android_market_text">Berapa banyak?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Anda dapat memilih berapa banyak Anda ingin sumbangkan setelah mengklik tombol!</string> - <string name="donations__thanks_dialog_title">Terima Kasih!</string> - <string name="donations__thanks_dialog">Terimkasih atas donasi anda!\n\nSaya sangat menghargai ini!</string> - <string name="donations__alert_dialog_title">Terjadi galat</string> - <string name="donations__alert_dialog_no_browser">Tidak di temukan browser untuk membuka laman website</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-it/donations__strings.xml b/libraries/Donations/src/main/res/values-it/donations__strings.xml deleted file mode 100644 index 377fb8f..0000000 --- a/libraries/Donations/src/main/res/values-it/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Chiudi</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Pensi che questa applicazione sia utile?\nSupporta il suo sviluppo mandando una donazione allo sviluppatore!</string> - <string name="donations__flattr_description">Flattr riceve il 10% come canone mensile!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">Donazioni In-App non supportate. Google Play Store è installato correttamente?</string> - <string name="donations__google_android_market_description">Google riceve il 30% di ogni donazione!</string> - <string name="donations__google_android_market_donate_button">Dona!</string> - <string name="donations__google_android_market_text">Quanto?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Puoi scegliere quanto donare dopo aver premuto il pulsante!</string> - <string name="donations__thanks_dialog_title">Grazie!</string> - <string name="donations__thanks_dialog">Grazie per la donazione!\nLo apprezzo molto!</string> - <string name="donations__alert_dialog_title">Si è verificato un errore</string> - <string name="donations__alert_dialog_no_browser">Non è stato trovato un browser per aprire un sito internet!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-iw-rIL/donations__strings.xml b/libraries/Donations/src/main/res/values-iw-rIL/donations__strings.xml deleted file mode 100644 index 432356b..0000000 --- a/libraries/Donations/src/main/res/values-iw-rIL/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">לא נמצא Busybox. כדי להתקין אותו מהמרקט לחץ על הלחצן מתחת.</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">Flattr מספר הנחה של 10 % לתשלום החודשי!</string> - <string name="donations__google_android_market">אנדרואיד מרקט</string> - <string name="donations__google_android_market_not_supported">תרומות לתוכנה אינם נתמכות. האם המרקט של גוגל אנדרואיד מותקן כראוי?</string> - <string name="donations__google_android_market_description">גוגל מקבלת 30% מסך התרומה!</string> - <string name="donations__google_android_market_donate_button">תרומה!</string> - <string name="donations__google_android_market_text">כמה?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">אתה יכול לבחור כמה אתה רוצה לתרום על ידי לחיצה על הכפתור!</string> - <string name="donations__thanks_dialog_title">תודה!</string> - <string name="donations__thanks_dialog">תודה על תרומתך!\nאני מאוד מעריך זאת!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-ja/donations__strings.xml b/libraries/Donations/src/main/res/values-ja/donations__strings.xml deleted file mode 100644 index 59f8088..0000000 --- a/libraries/Donations/src/main/res/values-ja/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">閉じる</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">このアプリは役に立ちましたか?\n開発者に寄付をして開発を応援してください!</string> - <string name="donations__flattr_description">Flattr は月額として10 %手に入れます!</string> - <string name="donations__google_android_market">Google Playストア</string> - <string name="donations__google_android_market_not_supported">アプリ内寄付は非対応です。GooglePlayストアはインストールされていますか?</string> - <string name="donations__google_android_market_description">Googleは寄付の30%を持って行きます…。</string> - <string name="donations__google_android_market_donate_button">寄付する!</string> - <string name="donations__google_android_market_text">いくら?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">ボタンを押した後寄付したい額を選べます!</string> - <string name="donations__thanks_dialog_title">ありがとう!</string> - <string name="donations__thanks_dialog">寄付ありがとう!\n本当に感謝しています!</string> - <string name="donations__alert_dialog_title">エラーが発生しました</string> - <string name="donations__alert_dialog_no_browser">サイトを開くためのブラウザが見つかりません!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-km/donations__strings.xml b/libraries/Donations/src/main/res/values-km/donations__strings.xml deleted file mode 100644 index c757504..0000000 --- a/libraries/Donations/src/main/res/values-km/donations__strings.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources/> diff --git a/libraries/Donations/src/main/res/values-ko/donations__strings.xml b/libraries/Donations/src/main/res/values-ko/donations__strings.xml deleted file mode 100644 index c757504..0000000 --- a/libraries/Donations/src/main/res/values-ko/donations__strings.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources/> diff --git a/libraries/Donations/src/main/res/values-mn/donations__strings.xml b/libraries/Donations/src/main/res/values-mn/donations__strings.xml deleted file mode 100644 index c7fbb1d..0000000 --- a/libraries/Donations/src/main/res/values-mn/donations__strings.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Хаах</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-nl/donations__strings.xml b/libraries/Donations/src/main/res/values-nl/donations__strings.xml deleted file mode 100644 index ff18224..0000000 --- a/libraries/Donations/src/main/res/values-nl/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Sluiten</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Vindt u dit applicatie nuttig?\nDraag bij aan de ontwikkeling ervan door een donatie te sturen aan de ontwikkelaar!</string> - <string name="donations__flattr_description">Flattr neemt 10% als maandelijkse kosten</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">Helaas, in-App donaties worden niet ondersteund. Is Google Play Store correct geïnstalleerd?</string> - <string name="donations__google_android_market_description">Google houdt 30% van elke donatie in</string> - <string name="donations__google_android_market_donate_button">Doneer!</string> - <string name="donations__google_android_market_text">Welke bedrag?</string> - <string name="donations__paypal">Paypal</string> - <string name="donations__paypal_description">U kunt kiezen hoeveel u wilt doneren, na het klikken van de knop</string> - <string name="donations__thanks_dialog_title">Dank u wel</string> - <string name="donations__thanks_dialog">Bedankt voor uw donatie! Ik stel het heel erg op prijs.</string> - <string name="donations__alert_dialog_title">Er is iets fout gegaan!</string> - <string name="donations__alert_dialog_no_browser">Er is geen browser gevonden om een website te openen!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-no-rNO/donations__strings.xml b/libraries/Donations/src/main/res/values-no-rNO/donations__strings.xml deleted file mode 100644 index e434f9b..0000000 --- a/libraries/Donations/src/main/res/values-no-rNO/donations__strings.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Lukk</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-pl/donations__strings.xml b/libraries/Donations/src/main/res/values-pl/donations__strings.xml deleted file mode 100644 index 8bfc3a4..0000000 --- a/libraries/Donations/src/main/res/values-pl/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Zamknij</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Czy aplikacja jest dla Ciebie przydatna?\nWspomóż jej rozwój poprzez dotację dla autora!</string> - <string name="donations__flattr_description">Flattr pobiera 10% jako miesięczną opłatę!</string> - <string name="donations__google_android_market">Sklep Google Play</string> - <string name="donations__google_android_market_not_supported">Brak wsparcia dla wbudowanych płatności. Czy aplikacja Sklep Google Play jest zainstalowana prawidłowo?</string> - <string name="donations__google_android_market_description">Google pobiera 30% kwoty z każdej darowizny!</string> - <string name="donations__google_android_market_donate_button">Przekaż!</string> - <string name="donations__google_android_market_text">Kwota do przekazania?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Wybór kwoty do przekazania nastąpi po kliknięciu przycisku \"Przekaż\"!</string> - <string name="donations__thanks_dialog_title">Dzięki!</string> - <string name="donations__thanks_dialog">Dziekuję za darowiznę!\nNaprawdę to doceniam!</string> - <string name="donations__alert_dialog_title">Wystąpił błąd</string> - <string name="donations__alert_dialog_no_browser">Brak przeglądarki! Nie można otworzyć strony www.</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-pt-rBR/donations__strings.xml b/libraries/Donations/src/main/res/values-pt-rBR/donations__strings.xml deleted file mode 100644 index c5fbcd2..0000000 --- a/libraries/Donations/src/main/res/values-pt-rBR/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Fechar</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Você achou esta aplicação útil?\nSuporte o seu desenvolvimento mandando uma doação programador!</string> - <string name="donations__flattr_description">Flattr possui uma taxa mensal de 10%!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">Doações dentro do aplicativo não são suportadas. O Google Play Store foi instalado corretamente?</string> - <string name="donations__google_android_market_description">Google retém 30% de cada doação!</string> - <string name="donations__google_android_market_donate_button">Doar!</string> - <string name="donations__google_android_market_text">Quanto?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Você pode escolher quanto deseja doar após clicar no botão!</string> - <string name="donations__thanks_dialog_title">Obrigado!</string> - <string name="donations__thanks_dialog">Obrigado pela sua doação!</string> - <string name="donations__alert_dialog_title">Erro ocorrido</string> - <string name="donations__alert_dialog_no_browser">Nenhum navegador foi encontrado para abrir um site!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-ro-rRO/donations__strings.xml b/libraries/Donations/src/main/res/values-ro-rRO/donations__strings.xml deleted file mode 100644 index 76c552d..0000000 --- a/libraries/Donations/src/main/res/values-ro-rRO/donations__strings.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Inchide</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-ru/donations__strings.xml b/libraries/Donations/src/main/res/values-ru/donations__strings.xml deleted file mode 100644 index accda6a..0000000 --- a/libraries/Donations/src/main/res/values-ru/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Закрыть</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Считаете ли вы приложение полезным?\nПоддержите его развитие, отправив пожертвование для разработчиков!</string> - <string name="donations__flattr_description">Flattr взимает 10% в виде ежемесячной абонентской платы!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">Пожертвования через приложение не поддерживаются. Google Play Store установлен правильно?</string> - <string name="donations__google_android_market_description">Google взимает 30% с каждого пожертвования!</string> - <string name="donations__google_android_market_donate_button">Пожертвовать!</string> - <string name="donations__google_android_market_text">Сколько?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">После нажатия на кнопку вы можете выбрать сколько хотите пожертвовать!</string> - <string name="donations__thanks_dialog_title">Благодарю!</string> - <string name="donations__thanks_dialog">Благодарю за пожертвование! Я очень это ценю!</string> - <string name="donations__alert_dialog_title">Произошла ошибка</string> - <string name="donations__alert_dialog_no_browser">Не найден подходящий браузер для открытия этого веб-сайта!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-sl-rSI/donations__strings.xml b/libraries/Donations/src/main/res/values-sl-rSI/donations__strings.xml deleted file mode 100644 index fa91764..0000000 --- a/libraries/Donations/src/main/res/values-sl-rSI/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Zapri</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">Flattr vzame 10% kot mesečni strošek!</string> - <string name="donations__google_android_market">Google Trgovina (Play Store)</string> - <string name="donations__google_android_market_not_supported">Donacije znotraj aplikacije niso možne. Imate nameščeno Google Trgovino (Play Store)?</string> - <string name="donations__google_android_market_description">Google vzame 30% od vsake donacije!</string> - <string name="donations__google_android_market_donate_button">Doniraj!</string> - <string name="donations__google_android_market_text">Koliko?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">O velikosti donacije boste odločili po tem ko pritisnete gumb!</string> - <string name="donations__thanks_dialog_title">Hvala!</string> - <string name="donations__thanks_dialog">Hvala za donacijo!\nRes cenim to!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-sr/donations__strings.xml b/libraries/Donations/src/main/res/values-sr/donations__strings.xml deleted file mode 100644 index 295a2e6..0000000 --- a/libraries/Donations/src/main/res/values-sr/donations__strings.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Zatvori</string> - <string name="donations__description">Da li vam je ovo korisna aplikacija?\nPodržite njen razvitak slanjem donacije razvijaču!</string> - <string name="donations__flattr_description">Flattr uzima 10 % provizije mesečno!</string> - <string name="donations__google_android_market">Google Play prodavnica</string> - <string name="donations__google_android_market_not_supported">Donacije u aplikaciji nisu dostupne. Da li je Google Play prodavnica ispravno instalirana?</string> - <string name="donations__google_android_market_description">Google uzima 30 % od svae donacije!</string> - <string name="donations__google_android_market_donate_button">Doniraj!</string> - <string name="donations__google_android_market_text">Koliko?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Možete odabrati koliko ćete donirati posle pritiska na dugme!</string> - <string name="donations__thanks_dialog_title">Hvala!</string> - <string name="donations__thanks_dialog">Hvala za donaciju!\nZaista cenim to!</string> - <string name="donations__alert_dialog_title">Došlo je do greške</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-sv/donations__strings.xml b/libraries/Donations/src/main/res/values-sv/donations__strings.xml deleted file mode 100644 index 5a31d2f..0000000 --- a/libraries/Donations/src/main/res/values-sv/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Avsluta</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__flattr_description">Flattr tar 10% som månadskostnad</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">In-App-donationer stödjs inte. Är Google Play Store installerad korrekt?</string> - <string name="donations__google_android_market_description">Google tar 30% av varje donation</string> - <string name="donations__google_android_market_donate_button">Donera!</string> - <string name="donations__google_android_market_text">Hur mycket?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Du kan välja hur mycket du vill donera efter du har tryckt på knappen!</string> - <string name="donations__thanks_dialog_title">Tack!</string> - <string name="donations__thanks_dialog">Tack för donationen!\nDet uppskattas verkligen!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-tr/donations__strings.xml b/libraries/Donations/src/main/res/values-tr/donations__strings.xml deleted file mode 100644 index ad4cad9..0000000 --- a/libraries/Donations/src/main/res/values-tr/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Kapat</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Bu uygulamayı kullanışlı mı buluyorsunuz?\nGeliştiriciye bağış yaparak gelişmesine yardımcı olun!</string> - <string name="donations__flattr_description">Flattr takes 10 % as a monthly fee!</string> - <string name="donations__google_android_market">Google Play Store</string> - <string name="donations__google_android_market_not_supported">Uygulama içi bağışlar desteklenmiyor. Google Play Store düzgünce kuruldu mu?</string> - <string name="donations__google_android_market_description">Google her bağışın %30\'unu alıyor!</string> - <string name="donations__google_android_market_donate_button">Bağış Yap!</string> - <string name="donations__google_android_market_text">Ne kadar?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Butona bastıktan sonra ne kadar bağış yapacağınızı seçebilirsiniz!</string> - <string name="donations__thanks_dialog_title">Teşekkürler!</string> - <string name="donations__thanks_dialog">Bağış için teşekkürler!\nBunu gerçekten takdir ediyorum!</string> - <string name="donations__alert_dialog_title">Hata oluştu</string> - <string name="donations__alert_dialog_no_browser">Website açmak için tarayıcı bulunamadı</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-uk/donations__strings.xml b/libraries/Donations/src/main/res/values-uk/donations__strings.xml deleted file mode 100644 index 9eea84b..0000000 --- a/libraries/Donations/src/main/res/values-uk/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Закрити</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Ви вважаєте програму корисною?\n Підтримайте її розробку надіславши пожертву розробнику!</string> - <string name="donations__flattr_description">Flattr стягує 10% у вигляді щомісячної абонентської плати!</string> - <string name="donations__google_android_market">магазин Google Play</string> - <string name="donations__google_android_market_not_supported">Пожертвування через програму не підтримуються. Магазин Google Play встановлений правильно?</string> - <string name="donations__google_android_market_description">Google стягує 30% з кожного пожертвування!</string> - <string name="donations__google_android_market_donate_button">Пожертвувати!</string> - <string name="donations__google_android_market_text">Скільки?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Після натискання на кнопку ви можете вибрати скільки хочете пожертвувати!</string> - <string name="donations__thanks_dialog_title">Дякую!</string> - <string name="donations__thanks_dialog">Дякую за пожертвування! Я дуже це ціную!</string> - <string name="donations__alert_dialog_title">Трапилася помилка</string> - <string name="donations__alert_dialog_no_browser">Не знайдено жодного переглядача, щоб відкрити веб-сайт!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-vi-rVN/donations__strings.xml b/libraries/Donations/src/main/res/values-vi-rVN/donations__strings.xml deleted file mode 100644 index 6b71575..0000000 --- a/libraries/Donations/src/main/res/values-vi-rVN/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Đóng</string> - <string name="donations__flattr">Đánh giá</string> - <string name="donations__description">Bạn có thấy ứng này hữu ích?\nHãy hỗ trợ việc phát triển của phần mềm bằng cách ủng hộ tài chính!</string> - <string name="donations__flattr_description">Đánh giá cao mất 10% như phí tháng! </string> - <string name="donations__google_android_market">CH Google Play</string> - <string name="donations__google_android_market_not_supported">Không hỗ trợ chức năng ủng hộ trong ứng dụng. CH Google Play có hoạt động chính xác?</string> - <string name="donations__google_android_market_description">Google hưởng 30% giá trị ủng hộ!</string> - <string name="donations__google_android_market_donate_button">Ủng hộ!</string> - <string name="donations__google_android_market_text">Bao nhiêu?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">Bạn có thể bấm nút chọn số tiền cần ủng hộ!</string> - <string name="donations__thanks_dialog_title">Xin cám ơn!</string> - <string name="donations__thanks_dialog">Cám ơn bạn đã ủng hộ!\nTôi thực sự cảm kích! </string> - <string name="donations__alert_dialog_title">Lỗi đã xảy ra</string> - <string name="donations__alert_dialog_no_browser">Không có trinnhf duyệt nào được tìm thấy để mở ra liên kết đến website!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-vi/donations__strings.xml b/libraries/Donations/src/main/res/values-vi/donations__strings.xml deleted file mode 100644 index 0c62253..0000000 --- a/libraries/Donations/src/main/res/values-vi/donations__strings.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">Đóng</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-zh-rCN/donations__strings.xml b/libraries/Donations/src/main/res/values-zh-rCN/donations__strings.xml deleted file mode 100644 index 9eb8c7b..0000000 --- a/libraries/Donations/src/main/res/values-zh-rCN/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">关闭</string> - <string name="donations__flattr">Flattr®</string> - <string name="donations__description">喜欢这个应用程序?\n通过捐赠来支持我们!</string> - <string name="donations__flattr_description">Flattr® 将从月费中提成10%!</string> - <string name="donations__google_android_market">Google Play 商店</string> - <string name="donations__google_android_market_not_supported">不支持 In-App 捐赠。你的 Google Play 商店是否安装正确了呢?</string> - <string name="donations__google_android_market_description">Google 要从捐赠中抽取3成!\n</string> - <string name="donations__google_android_market_donate_button">捐赠!</string> - <string name="donations__google_android_market_text">捐赠多少?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">点击这个按钮之后选择你想要捐赠多少!</string> - <string name="donations__thanks_dialog_title">谢谢!</string> - <string name="donations__thanks_dialog">谢谢捐赠!\n非常感谢您!</string> - <string name="donations__alert_dialog_title">发生错误</string> - <string name="donations__alert_dialog_no_browser">未找到浏览器来打开网页</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-zh-rHK/donations__strings.xml b/libraries/Donations/src/main/res/values-zh-rHK/donations__strings.xml deleted file mode 100644 index 92236c4..0000000 --- a/libraries/Donations/src/main/res/values-zh-rHK/donations__strings.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">關閉</string> - <string name="donations__flattr">透過 Flattr 捐款</string> - <string name="donations__description">這個廣告攔截程式對您有用嗎?\n您可透過以下方式進行捐款去支持本程式及其開發者!</string> - <string name="donations__flattr_description">Flattr 會收取 10% 月費!</string> - <string name="donations__google_android_market">透過 Google Play 捐款</string> - <string name="donations__google_android_market_not_supported">捐款不支援 In-App 模式。您的 Google Play 是否安裝正確?</string> - <string name="donations__google_android_market_description">Google 會在每項捐款中收取 30% 手續費!</string> - <string name="donations__google_android_market_donate_button">按此進行捐款!</string> - <string name="donations__google_android_market_text">要捐多少?</string> - <string name="donations__paypal">透過 PayPal 捐款</string> - <string name="donations__paypal_description">點擊按鈕您就可以選擇捐多少!</string> - <string name="donations__thanks_dialog_title">感謝!</string> - <string name="donations__thanks_dialog">感謝您的捐款!\n真的非常感激!</string> - <string name="donations__alert_dialog_title">發生錯誤</string> - <string name="donations__alert_dialog_no_browser">沒有找到任何瀏覽器去開啟網頁!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values-zh-rTW/donations__strings.xml b/libraries/Donations/src/main/res/values-zh-rTW/donations__strings.xml deleted file mode 100644 index 9034cac..0000000 --- a/libraries/Donations/src/main/res/values-zh-rTW/donations__strings.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<resources> - <string name="donations__button_close">關閉</string> - <string name="donations__flattr">Flattr®</string> - <string name="donations__flattr_description">Flattr®將從資助金額中扣取10%作為手續費!</string> - <string name="donations__google_android_market">Google Play 商店</string> - <string name="donations__google_android_market_not_supported">不支援In-App資助。你的Google Play 商店是否正確安裝?</string> - <string name="donations__google_android_market_description">Google 會從每筆資助金額中抽取3成!</string> - <string name="donations__google_android_market_donate_button">資助開發者!</string> - <string name="donations__google_android_market_text">多少?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">你可以選擇你想資助多少後點擊按鈕!</string> - <string name="donations__thanks_dialog_title">謝謝!</string> - <string name="donations__thanks_dialog">謝謝您的資助!\n真的很感謝您!</string> -</resources> diff --git a/libraries/Donations/src/main/res/values/donations__strings.xml b/libraries/Donations/src/main/res/values/donations__strings.xml deleted file mode 100644 index 896c042..0000000 --- a/libraries/Donations/src/main/res/values/donations__strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources> - - <string name="donations__button_close">Close</string> - <string name="donations__flattr">Flattr</string> - <string name="donations__description">Do you find this application useful?\nSupport it\'s development by sending a donation to the developer!</string> - <string name="donations__flattr_description">Flattr takes 10 % as a monthly fee!</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 takes 30 % off every donation!</string> - <string name="donations__google_android_market_donate_button">Donate!</string> - <string name="donations__google_android_market_text">How much?</string> - <string name="donations__paypal">PayPal</string> - <string name="donations__paypal_description">You can choose how much you want to donate after clicking the button!</string> - <string name="donations__thanks_dialog_title">Thanks!</string> - <string name="donations__thanks_dialog">Thanks for donating!\nI really appreciate this!</string> - <string name="donations__alert_dialog_title">Error occurred</string> - <string name="donations__alert_dialog_no_browser">No browser was found to open a website!</string> - -</resources> diff --git a/libraries/HtmlTextView/.gitignore b/libraries/HtmlTextView/.gitignore deleted file mode 100644 index afa9dfc..0000000 --- a/libraries/HtmlTextView/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -#Android specific -bin -gen -obj -libs/armeabi -lint.xml -local.properties -release.properties -ant.properties -*.class -*.apk - -#Gradle -.gradle -build -gradle.properties -gradlew -gradlew.bat -gradle - -#Maven -target -pom.xml.* - -#Eclipse -.project -.classpath -.settings -.metadata - -#IntelliJ IDEA -.idea -*.iml diff --git a/libraries/HtmlTextView/LICENSE b/libraries/HtmlTextView/LICENSE deleted file mode 100644 index d645695..0000000 --- a/libraries/HtmlTextView/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/libraries/HtmlTextView/README.md b/libraries/HtmlTextView/README.md deleted file mode 100644 index 05714f7..0000000 --- a/libraries/HtmlTextView/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# HtmlTextView for Android - -This HtmlTextView supports all HTML tags supported by Android's Html class (see [The CommonsBlog](http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html) and [history of Html class](https://github.com/android/platform_frameworks_base/commits/master/core/java/android/text/Html.java) for newer additions). -Additionally, list tags are supported (``<ul>``, ``<ol>``, ``<dd>``) and code tags with ``<code>``. - -This also includes a workaround to prevent TextView crashing on [specific Android versions](http://code.google.com/p/android/issues/detail?id=35466). - -This library is kept very tiny with no external dependencies. -I am using it to provide Help/About Activities in my apps. - -## Example - -``` -HtmlTextView text = new HtmlTextView(this); - -// loads html from string -text.setHtmlFromString("<b>Hello</b><ul><li>world</li><li>cats</li></ul>"); -``` -or -``` -HtmlTextView text = new HtmlTextView(this); - -// loads html from raw resource, i.e., a html file in res/raw/, this allows translatable resource (e.g., res/raw-de/ for german) -text.setHtmlFromRawResource(this, R.raw.help); -``` - -## Use library as Gradle dependency (Android library project) - -1. Copy this folder to your project and include it in ``settings.gradle`` with ``include ':html-textview'`` -2. Add dependency ``compile project(':html-textview')`` to your project's ``build.gradle``. - -## License - -Apache License v2 - -## Authors -- This library was hacked together by Dominik Schürmann -- Original [TagHandler](https://gist.github.com/mlakkadshaw/5983704) developed by [Mohammed Lakkadshaw](http://blog.mohammedlakkadshaw.com/) -- Original [UrlImageGetter](https://gist.github.com/Antarix/4167655) developed by Antarix Tandon -- [JellyBeanSpanFixTextView](https://gist.github.com/pyricau/3424004) (with fix from comment) developed by Pierre-Yves Ricau - -## Contributions - -Feel free to fork and do pull requests. I am more than happy to merge them. -Please do not introduce external dependencies. \ No newline at end of file diff --git a/libraries/HtmlTextView/build.gradle b/libraries/HtmlTextView/build.gradle deleted file mode 100644 index 1b1b849..0000000 --- a/libraries/HtmlTextView/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply plugin: 'android-library' - -android { - compileSdkVersion 21 - buildToolsVersion "21.1.2" - - defaultConfig { - minSdkVersion 16 - targetSdkVersion 21 - } - - // Do not abort build if lint finds errors - lintOptions { - abortOnError false - } -} diff --git a/libraries/HtmlTextView/src/main/AndroidManifest.xml b/libraries/HtmlTextView/src/main/AndroidManifest.xml deleted file mode 100644 index 1c747c1..0000000 --- a/libraries/HtmlTextView/src/main/AndroidManifest.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="org.sufficientlysecure.htmltextview" - android:versionCode="1" - android:versionName="1.0"> - - <uses-sdk - android:minSdkVersion="7" - android:targetSdkVersion="17"/> - - <application/> - -</manifest> \ No newline at end of file diff --git a/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/HtmlTagHandler.java b/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/HtmlTagHandler.java deleted file mode 100644 index c40c8de..0000000 --- a/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/HtmlTagHandler.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2013 Mohammed Lakkadshaw - * - * 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 org.sufficientlysecure.htmltextview; - -import java.util.Vector; - -import org.xml.sax.XMLReader; - -import android.text.Editable; -import android.text.Html; -import android.text.Spannable; -import android.text.style.BulletSpan; -import android.text.style.LeadingMarginSpan; -import android.text.style.TypefaceSpan; -import android.util.Log; - -public class HtmlTagHandler implements Html.TagHandler { - private int mListItemCount = 0; - private Vector<String> mListParents = new Vector<String>(); - - @Override - public void handleTag(final boolean opening, final String tag, Editable output, final XMLReader xmlReader) { - - if (tag.equals("ul") || tag.equals("ol") || tag.equals("dd")) { - if (opening) { - mListParents.add(tag); - } else mListParents.remove(tag); - - mListItemCount = 0; - } else if (tag.equals("li") && !opening) { - handleListTag(output); - } else if (tag.equalsIgnoreCase("code")) { - if (opening) { - output.setSpan(new TypefaceSpan("monospace"), output.length(), output.length(), Spannable.SPAN_MARK_MARK); - } else { - Log.d(HtmlTextView.TAG, "Code tag encountered"); - Object obj = getLast(output, TypefaceSpan.class); - int where = output.getSpanStart(obj); - output.setSpan(new TypefaceSpan("monospace"), where, output.length(), 0); - } - } - } - - private Object getLast(Editable text, Class kind) { - Object[] objs = text.getSpans(0, text.length(), kind); - if (objs.length == 0) { - return null; - } else { - for (int i = objs.length; i > 0; i--) { - if (text.getSpanFlags(objs[i - 1]) == Spannable.SPAN_MARK_MARK) { - return objs[i - 1]; - } - } - return null; - } - } - - private void handleListTag(Editable output) { - if (mListParents.lastElement().equals("ul")) { - output.append("\n"); - String[] split = output.toString().split("\n"); - - int lastIndex = split.length - 1; - int start = output.length() - split[lastIndex].length() - 1; - output.setSpan(new BulletSpan(15 * mListParents.size()), start, output.length(), 0); - } else if (mListParents.lastElement().equals("ol")) { - mListItemCount++; - - output.append("\n"); - String[] split = output.toString().split("\n"); - - int lastIndex = split.length - 1; - int start = output.length() - split[lastIndex].length() - 1; - output.insert(start, mListItemCount + ". "); - output.setSpan(new LeadingMarginSpan.Standard(15 * mListParents.size()), start, output.length(), 0); - } - } -} diff --git a/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/HtmlTextView.java b/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/HtmlTextView.java deleted file mode 100644 index 317c25a..0000000 --- a/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/HtmlTextView.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * 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 org.sufficientlysecure.htmltextview; - -import android.content.Context; -import android.text.Html; -import android.text.method.LinkMovementMethod; -import android.util.AttributeSet; - -import java.io.InputStream; - -public class HtmlTextView extends JellyBeanSpanFixTextView { - - public static final String TAG = "HtmlTextView"; - - public HtmlTextView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public HtmlTextView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public HtmlTextView(Context context) { - super(context); - } - - /** - * http://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string - * - * @param is - * @return - */ - static private String convertStreamToString(java.io.InputStream is) { - java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A"); - return s.hasNext() ? s.next() : ""; - } - - /** - * Loads HTML from a raw resource, i.e., a HTML file in res/raw/. - * This allows translatable resource (e.g., res/raw-de/ for german). - * The containing HTML is parsed to Android's Spannable format and then displayed. - * - * @param context - * @param id for example: R.raw.help - */ - public void setHtmlFromRawResource(Context context, int id) { - // load html from html file from /res/raw - InputStream inputStreamText = context.getResources().openRawResource(id); - - setHtmlFromString(convertStreamToString(inputStreamText)); - } - - /** - * Parses String containing HTML to Android's Spannable format and displays it in this TextView. - * - * @param html String containing HTML, for example: "<b>Hello world!</b>" - */ - public void setHtmlFromString(String html) { - // this uses Android's Html class for basic parsing, and HtmlTagHandler - setText(Html.fromHtml(html, new UrlImageGetter(this, getContext()), new HtmlTagHandler())); - - // make links work - setMovementMethod(LinkMovementMethod.getInstance()); - - // no flickering when clicking textview for Android < 4 -// text.setTextColor(getResources().getColor(android.R.color.secondary_text_dark_nodisable)); - } -} diff --git a/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/JellyBeanSpanFixTextView.java b/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/JellyBeanSpanFixTextView.java deleted file mode 100644 index 94bf458..0000000 --- a/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/JellyBeanSpanFixTextView.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> - * Copyright (C) 2012 Pierre-Yves Ricau <py.ricau@gmail.com> - * - * 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 org.sufficientlysecure.htmltextview; - -import java.util.ArrayList; -import java.util.List; - -import android.content.Context; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.util.AttributeSet; -import android.util.Log; -import android.widget.TextView; - -/** - * <p> - * A {@link android.widget.TextView} that insert spaces around its text spans where needed to prevent - * {@link IndexOutOfBoundsException} in {@link #onMeasure(int, int)} on Jelly Bean. - * <p> - * When {@link #onMeasure(int, int)} throws an exception, we try to fix the text by adding spaces - * around spans, until it works again. We then try removing some of the added spans, to minimize the - * insertions. - * <p> - * The fix is time consuming (a few ms, it depends on the size of your text), but it should only - * happen once per text change. - * <p> - * See http://code.google.com/p/android/issues/detail?id=35466 - * - */ -public class JellyBeanSpanFixTextView extends TextView { - - private static class FixingResult { - public final boolean fixed; - public final List<Object> spansWithSpacesBefore; - public final List<Object> spansWithSpacesAfter; - - public static FixingResult fixed(List<Object> spansWithSpacesBefore, - List<Object> spansWithSpacesAfter) { - return new FixingResult(true, spansWithSpacesBefore, spansWithSpacesAfter); - } - - public static FixingResult notFixed() { - return new FixingResult(false, null, null); - } - - private FixingResult(boolean fixed, List<Object> spansWithSpacesBefore, - List<Object> spansWithSpacesAfter) { - this.fixed = fixed; - this.spansWithSpacesBefore = spansWithSpacesBefore; - this.spansWithSpacesAfter = spansWithSpacesAfter; - } - } - - public JellyBeanSpanFixTextView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public JellyBeanSpanFixTextView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public JellyBeanSpanFixTextView(Context context) { - super(context); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - try { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } catch (IndexOutOfBoundsException e) { - fixOnMeasure(widthMeasureSpec, heightMeasureSpec); - } - } - - /** - * If possible, fixes the Spanned text by adding spaces around spans when needed. - */ - private void fixOnMeasure(int widthMeasureSpec, int heightMeasureSpec) { - CharSequence text = getText(); - if (text instanceof Spanned) { - SpannableStringBuilder builder = new SpannableStringBuilder(text); - fixSpannedWithSpaces(builder, widthMeasureSpec, heightMeasureSpec); - } else { - if (BuildConfig.DEBUG) { - Log.d(HtmlTextView.TAG, "The text isn't a Spanned"); - } - fallbackToString(widthMeasureSpec, heightMeasureSpec); - } - } - - /** - * Add spaces around spans until the text is fixed, and then removes the unneeded spaces - */ - private void fixSpannedWithSpaces(SpannableStringBuilder builder, int widthMeasureSpec, - int heightMeasureSpec) { - long startFix = System.currentTimeMillis(); - - FixingResult result = addSpacesAroundSpansUntilFixed(builder, widthMeasureSpec, - heightMeasureSpec); - - if (result.fixed) { - removeUnneededSpaces(widthMeasureSpec, heightMeasureSpec, builder, result); - } else { - fallbackToString(widthMeasureSpec, heightMeasureSpec); - } - - if (BuildConfig.DEBUG) { - long fixDuration = System.currentTimeMillis() - startFix; - Log.d(HtmlTextView.TAG, "fixSpannedWithSpaces() duration in ms: " + fixDuration); - } - } - - private FixingResult addSpacesAroundSpansUntilFixed(SpannableStringBuilder builder, - int widthMeasureSpec, int heightMeasureSpec) { - - Object[] spans = builder.getSpans(0, builder.length(), Object.class); - List<Object> spansWithSpacesBefore = new ArrayList<Object>(spans.length); - List<Object> spansWithSpacesAfter = new ArrayList<Object>(spans.length); - - for (Object span : spans) { - int spanStart = builder.getSpanStart(span); - if (isNotSpace(builder, spanStart - 1)) { - builder.insert(spanStart, " "); - spansWithSpacesBefore.add(span); - } - - int spanEnd = builder.getSpanEnd(span); - if (isNotSpace(builder, spanEnd)) { - builder.insert(spanEnd, " "); - spansWithSpacesAfter.add(span); - } - - try { - setTextAndMeasure(builder, widthMeasureSpec, heightMeasureSpec); - return FixingResult.fixed(spansWithSpacesBefore, spansWithSpacesAfter); - } catch (IndexOutOfBoundsException notFixed) { - } - } - if (BuildConfig.DEBUG) { - Log.d(HtmlTextView.TAG, "Could not fix the Spanned by adding spaces around spans"); - } - return FixingResult.notFixed(); - } - - private boolean isNotSpace(CharSequence text, int where) { - if (where < 0) - return true; - return text.charAt(where) != ' '; - } - - private void setTextAndMeasure(CharSequence text, int widthMeasureSpec, int heightMeasureSpec) { - setText(text); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - - private void removeUnneededSpaces(int widthMeasureSpec, int heightMeasureSpec, - SpannableStringBuilder builder, FixingResult result) { - - for (Object span : result.spansWithSpacesAfter) { - int spanEnd = builder.getSpanEnd(span); - builder.delete(spanEnd, spanEnd + 1); - try { - setTextAndMeasure(builder, widthMeasureSpec, heightMeasureSpec); - } catch (IndexOutOfBoundsException ignored) { - builder.insert(spanEnd, " "); - } - } - - boolean needReset = true; - for (Object span : result.spansWithSpacesBefore) { - int spanStart = builder.getSpanStart(span); - builder.delete(spanStart - 1, spanStart); - try { - setTextAndMeasure(builder, widthMeasureSpec, heightMeasureSpec); - needReset = false; - } catch (IndexOutOfBoundsException ignored) { - needReset = true; - int newSpanStart = spanStart - 1; - builder.insert(newSpanStart, " "); - } - } - - if (needReset) { - setText(builder); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - } - - private void fallbackToString(int widthMeasureSpec, int heightMeasureSpec) { - if (BuildConfig.DEBUG) { - Log.d(HtmlTextView.TAG, "Fallback to unspanned text"); - } - String fallbackText = getText().toString(); - setTextAndMeasure(fallbackText, widthMeasureSpec, heightMeasureSpec); - } - -} \ No newline at end of file diff --git a/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/UrlImageGetter.java b/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/UrlImageGetter.java deleted file mode 100644 index e4fc41c..0000000 --- a/libraries/HtmlTextView/src/main/java/org/sufficientlysecure/htmltextview/UrlImageGetter.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2013 Antarix Tandon - * - * 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 org.sufficientlysecure.htmltextview; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.text.Html.ImageGetter; -import android.view.View; - -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; - -public class UrlImageGetter implements ImageGetter { - Context c; - View container; - - /** - * Construct the URLImageParser which will execute AsyncTask and refresh the container - * - * @param t - * @param c - */ - public UrlImageGetter(View t, Context c) { - this.c = c; - this.container = t; - } - - public Drawable getDrawable(String source) { - UrlDrawable urlDrawable = new UrlDrawable(); - - // get the actual source - ImageGetterAsyncTask asyncTask = new ImageGetterAsyncTask(urlDrawable); - - asyncTask.execute(source); - - // return reference to URLDrawable where I will change with actual image from - // the src tag - return urlDrawable; - } - - public class ImageGetterAsyncTask extends AsyncTask<String, Void, Drawable> { - UrlDrawable urlDrawable; - - public ImageGetterAsyncTask(UrlDrawable d) { - this.urlDrawable = d; - } - - @Override - protected Drawable doInBackground(String... params) { - String source = params[0]; - return fetchDrawable(source); - } - - @Override - protected void onPostExecute(Drawable result) { - // set the correct bound according to the result from HTTP call - urlDrawable.setBounds(0, 0, 0 + result.getIntrinsicWidth(), 0 + result.getIntrinsicHeight()); - - // change the reference of the current drawable to the result - // from the HTTP call - urlDrawable.drawable = result; - - // redraw the image by invalidating the container - UrlImageGetter.this.container.invalidate(); - } - - /** - * Get the Drawable from URL - * - * @param urlString - * @return - */ - public Drawable fetchDrawable(String urlString) { - try { - InputStream is = fetch(urlString); - Drawable drawable = Drawable.createFromStream(is, "src"); - drawable.setBounds(0, 0, 0 + drawable.getIntrinsicWidth(), 0 + drawable.getIntrinsicHeight()); - return drawable; - } catch (Exception e) { - return null; - } - } - - private InputStream fetch(String urlString) throws MalformedURLException, IOException { - DefaultHttpClient httpClient = new DefaultHttpClient(); - HttpGet request = new HttpGet(urlString); - HttpResponse response = httpClient.execute(request); - return response.getEntity().getContent(); - } - } - - @SuppressWarnings("deprecation") - public class UrlDrawable extends BitmapDrawable { - // the drawable that you need to set, you could set the initial drawing - // with the loading image if you need to - protected Drawable drawable; - - @Override - public void draw(Canvas canvas) { - // override the draw to facilitate refresh function later - if (drawable != null) { - drawable.draw(canvas); - } - } - } -} diff --git a/libraries/RootCommands/build.gradle b/libraries/RootCommands/build.gradle index f972937..8b0a263 100644 --- a/libraries/RootCommands/build.gradle +++ b/libraries/RootCommands/build.gradle @@ -1,8 +1,8 @@ -apply plugin: 'android-library' +apply plugin: 'com.android.library' android { compileSdkVersion 21 - buildToolsVersion "21.1.2" + buildToolsVersion "25.0.0" defaultConfig { minSdkVersion 16