From 9e303e5fa0d1da191630edb9b93801462e973c86 Mon Sep 17 00:00:00 2001 From: survivingwithandroid Date: Thu, 27 Feb 2014 16:20:52 +0100 Subject: [PATCH] Initial Commit --- TorchApp/.gitignore | 4 + TorchApp/build.gradle | 16 + TorchApp/gradle.properties | 18 + TorchApp/torch/.gitignore | 1 + TorchApp/torch/build.gradle | 25 + TorchApp/torch/proguard-rules.txt | 17 + TorchApp/torch/src/main/AndroidManifest.xml | 25 + .../vending/billing/IInAppBillingService.aidl | 144 +++ TorchApp/torch/src/main/ic_launcher-web.png | Bin 0 -> 47065 bytes .../torch/MainActivity.java | 266 +++++ .../survivingwithandroid/torch/SwAUtil.java | 61 ++ .../torch/util/Base64.java | 570 ++++++++++ .../torch/util/Base64DecoderException.java | 32 + .../torch/util/IabException.java | 43 + .../torch/util/IabHelper.java | 991 ++++++++++++++++++ .../torch/util/IabResult.java | 45 + .../torch/util/Inventory.java | 91 ++ .../torch/util/Purchase.java | 63 ++ .../torch/util/Security.java | 123 +++ .../torch/util/SkuDetails.java | 58 + .../torch/util/SwABillingUtil.java | 74 ++ .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 8381 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 4394 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 12664 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 22544 bytes .../main/res/drawable-xxxhdpi/ic_launcher.png | Bin 0 -> 32618 bytes TorchApp/torch/src/main/res/drawable/off.png | Bin 0 -> 23996 bytes TorchApp/torch/src/main/res/drawable/on.png | Bin 0 -> 23497 bytes .../src/main/res/layout/about_layout.xml | 71 ++ .../src/main/res/layout/activity_main.xml | 24 + .../src/main/res/layout/fragment_main.xml | 74 ++ .../src/main/res/layout/popdonate_layout.xml | 54 + TorchApp/torch/src/main/res/menu/main.xml | 40 + .../src/main/res/values-w820dp/dimens.xml | 6 + TorchApp/torch/src/main/res/values/dimens.xml | 6 + .../torch/src/main/res/values/strings.xml | 14 + TorchApp/torch/src/main/res/values/styles.xml | 13 + 37 files changed, 2969 insertions(+) create mode 100644 TorchApp/.gitignore create mode 100644 TorchApp/build.gradle create mode 100644 TorchApp/gradle.properties create mode 100644 TorchApp/torch/.gitignore create mode 100644 TorchApp/torch/build.gradle create mode 100644 TorchApp/torch/proguard-rules.txt create mode 100644 TorchApp/torch/src/main/AndroidManifest.xml create mode 100644 TorchApp/torch/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl create mode 100644 TorchApp/torch/src/main/ic_launcher-web.png create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/MainActivity.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/SwAUtil.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Base64.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Base64DecoderException.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabException.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabHelper.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabResult.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Inventory.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Purchase.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Security.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/SkuDetails.java create mode 100644 TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/SwABillingUtil.java create mode 100644 TorchApp/torch/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 TorchApp/torch/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 TorchApp/torch/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 TorchApp/torch/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 TorchApp/torch/src/main/res/drawable-xxxhdpi/ic_launcher.png create mode 100644 TorchApp/torch/src/main/res/drawable/off.png create mode 100644 TorchApp/torch/src/main/res/drawable/on.png create mode 100644 TorchApp/torch/src/main/res/layout/about_layout.xml create mode 100644 TorchApp/torch/src/main/res/layout/activity_main.xml create mode 100644 TorchApp/torch/src/main/res/layout/fragment_main.xml create mode 100644 TorchApp/torch/src/main/res/layout/popdonate_layout.xml create mode 100644 TorchApp/torch/src/main/res/menu/main.xml create mode 100644 TorchApp/torch/src/main/res/values-w820dp/dimens.xml create mode 100644 TorchApp/torch/src/main/res/values/dimens.xml create mode 100644 TorchApp/torch/src/main/res/values/strings.xml create mode 100644 TorchApp/torch/src/main/res/values/styles.xml diff --git a/TorchApp/.gitignore b/TorchApp/.gitignore new file mode 100644 index 0000000..d6bfc95 --- /dev/null +++ b/TorchApp/.gitignore @@ -0,0 +1,4 @@ +.gradle +/local.properties +/.idea/workspace.xml +.DS_Store diff --git a/TorchApp/build.gradle b/TorchApp/build.gradle new file mode 100644 index 0000000..6b42096 --- /dev/null +++ b/TorchApp/build.gradle @@ -0,0 +1,16 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:0.8.+' + } +} + +allprojects { + repositories { + mavenCentral() + } +} diff --git a/TorchApp/gradle.properties b/TorchApp/gradle.properties new file mode 100644 index 0000000..5d08ba7 --- /dev/null +++ b/TorchApp/gradle.properties @@ -0,0 +1,18 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Settings specified in this file will override any Gradle settings +# configured through the IDE. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true \ No newline at end of file diff --git a/TorchApp/torch/.gitignore b/TorchApp/torch/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/TorchApp/torch/.gitignore @@ -0,0 +1 @@ +/build diff --git a/TorchApp/torch/build.gradle b/TorchApp/torch/build.gradle new file mode 100644 index 0000000..79b816c --- /dev/null +++ b/TorchApp/torch/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'android' + +android { + compileSdkVersion 17 + buildToolsVersion "19.0.0" + + defaultConfig { + minSdkVersion 11 + targetSdkVersion 19 + versionCode 2 + versionName "1_1" + } + buildTypes { + release { + runProguard false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + + } + } +} + +dependencies { + compile 'com.android.support:appcompat-v7:+' + compile fileTree(dir: 'libs', include: ['*.jar']) +} diff --git a/TorchApp/torch/proguard-rules.txt b/TorchApp/torch/proguard-rules.txt new file mode 100644 index 0000000..5da226c --- /dev/null +++ b/TorchApp/torch/proguard-rules.txt @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in D:/DevMobile/sdk1/eclipse_Android_SDK/android-sdk_r18-windows/android-sdk-windows/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} \ No newline at end of file diff --git a/TorchApp/torch/src/main/AndroidManifest.xml b/TorchApp/torch/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b1a7911 --- /dev/null +++ b/TorchApp/torch/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + diff --git a/TorchApp/torch/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl b/TorchApp/torch/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl new file mode 100644 index 0000000..2a492f7 --- /dev/null +++ b/TorchApp/torch/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.vending.billing; + +import android.os.Bundle; + +/** + * InAppBillingService is the service that provides in-app billing version 3 and beyond. + * This service provides the following features: + * 1. Provides a new API to get details of in-app items published for the app including + * price, type, title and description. + * 2. The purchase flow is synchronous and purchase information is available immediately + * after it completes. + * 3. Purchase information of in-app purchases is maintained within the Google Play system + * till the purchase is consumed. + * 4. An API to consume a purchase of an inapp item. All purchases of one-time + * in-app items are consumable and thereafter can be purchased again. + * 5. An API to get current purchases of the user immediately. This will not contain any + * consumed purchases. + * + * All calls will give a response code with the following possible values + * RESULT_OK = 0 - success + * RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog + * RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested + * RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase + * RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API + * RESULT_ERROR = 6 - Fatal error during the API action + * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned + * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned + */ +interface IInAppBillingService { + /** + * Checks support for the requested billing API version, package and in-app type. + * Minimum API version supported by this interface is 3. + * @param apiVersion the billing version which the app is using + * @param packageName the package name of the calling app + * @param type type of the in-app item being purchased "inapp" for one-time purchases + * and "subs" for subscription. + * @return RESULT_OK(0) on success, corresponding result code on failures + */ + int isBillingSupported(int apiVersion, String packageName, String type); + + /** + * Provides details of a list of SKUs + * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle + * with a list JSON strings containing the productId, price, title and description. + * This API can be called with a maximum of 20 SKUs. + * @param apiVersion billing API version that the Third-party is using + * @param packageName the package name of the calling app + * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST" + * @return Bundle containing the following key-value pairs + * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on + * failure as listed above. + * "DETAILS_LIST" with a StringArrayList containing purchase information + * in JSON format similar to: + * '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00", + * "title : "Example Title", "description" : "This is an example description" }' + */ + Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle); + + /** + * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU, + * the type, a unique purchase token and an optional developer payload. + * @param apiVersion billing API version that the app is using + * @param packageName package name of the calling app + * @param sku the SKU of the in-app item as published in the developer console + * @param type the type of the in-app item ("inapp" for one-time purchases + * and "subs" for subscription). + * @param developerPayload optional argument to be sent back with the purchase information + * @return Bundle containing the following key-value pairs + * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on + * failure as listed above. + * "BUY_INTENT" - PendingIntent to start the purchase flow + * + * The Pending intent should be launched with startIntentSenderForResult. When purchase flow + * has completed, the onActivityResult() will give a resultCode of OK or CANCELED. + * If the purchase is successful, the result data will contain the following key-value pairs + * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on + * failure as listed above. + * "INAPP_PURCHASE_DATA" - String in JSON format similar to + * '{"orderId":"12999763169054705758.1371079406387615", + * "packageName":"com.example.app", + * "productId":"exampleSku", + * "purchaseTime":1345678900000, + * "purchaseToken" : "122333444455555", + * "developerPayload":"example developer payload" }' + * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that + * was signed with the private key of the developer + * TODO: change this to app-specific keys. + */ + Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type, + String developerPayload); + + /** + * Returns the current SKUs owned by the user of the type and package name specified along with + * purchase information and a signature of the data to be validated. + * This will return all SKUs that have been purchased in V3 and managed items purchased using + * V1 and V2 that have not been consumed. + * @param apiVersion billing API version that the app is using + * @param packageName package name of the calling app + * @param type the type of the in-app items being requested + * ("inapp" for one-time purchases and "subs" for subscription). + * @param continuationToken to be set as null for the first call, if the number of owned + * skus are too many, a continuationToken is returned in the response bundle. + * This method can be called again with the continuation token to get the next set of + * owned skus. + * @return Bundle containing the following key-value pairs + * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on + * failure as listed above. + * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs + * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information + * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures + * of the purchase information + * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the + * next set of in-app purchases. Only set if the + * user has more owned skus than the current list. + */ + Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken); + + /** + * Consume the last purchase of the given SKU. This will result in this item being removed + * from all subsequent responses to getPurchases() and allow re-purchase of this item. + * @param apiVersion billing API version that the app is using + * @param packageName package name of the calling app + * @param purchaseToken token in the purchase information JSON that identifies the purchase + * to be consumed + * @return 0 if consumption succeeded. Appropriate error values for failures. + */ + int consumePurchase(int apiVersion, String packageName, String purchaseToken); +} diff --git a/TorchApp/torch/src/main/ic_launcher-web.png b/TorchApp/torch/src/main/ic_launcher-web.png new file mode 100644 index 0000000000000000000000000000000000000000..4b14629c415332bd53a76a230dccf2d32a9829c4 GIT binary patch literal 47065 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 literal 0 HcmV?d00001 diff --git a/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/MainActivity.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/MainActivity.java new file mode 100644 index 0000000..103c5b4 --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/MainActivity.java @@ -0,0 +1,266 @@ +package com.survivingwithandroid.torch; + +import android.app.Activity; +import android.app.ActionBar; +import android.app.Fragment; +import android.content.Intent; +import android.hardware.Camera; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; + +import android.widget.ImageView; +import android.widget.SeekBar; +import android.widget.Toast; + +import com.survivingwithandroid.torch.util.IabHelper; +import com.survivingwithandroid.torch.util.IabResult; +import com.survivingwithandroid.torch.util.SwABillingUtil; + + +/* + * Copyright (C) 2014 Francesco Azzola - Surviving with Android (http://www.survivingwithandroid.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. + */ +public class MainActivity extends Activity { + private IabHelper mHelper ; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + String base64EncodedPublicKey= SwABillingUtil.KEY; + mHelper = new IabHelper(this, base64EncodedPublicKey); + mHelper.enableDebugLogging(true); + mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { + public void onIabSetupFinished(IabResult result) { + //Log.d("SwA", "Setup finished."); + + if (!result.isSuccess()) { + // Oh noes, there was a problem. + + Toast.makeText(MainActivity.this, "Bwarning continue ["+result.getMessage()+"]", Toast.LENGTH_LONG).show(); + return; + } + + // Have we been disposed of in the meantime? If so, quit. + if (mHelper == null) return; + + // IAB is fully set up. Now, let's get an inventory of stuff we own. + // Log.d("SwA", "Setup successful."); + } + }); + + if (savedInstanceState == null) { + getFragmentManager().beginTransaction() + .add(R.id.container, new PlaceholderFragment()) + .commit(); + } + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + //Log.d("SwA", "onActivityResult(" + requestCode + "," + resultCode + "," + data); + if (mHelper == null) return; + + // Pass on the activity 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 { + // Log.d("SwA", "onActivityResult handled by IABUtil."); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.main, menu); + return true; + } + + + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + if (id == R.id.action_share) { + String playStoreLink = "https://play.google.com/store/apps/details?id=" + + getPackageName(); + + String msg = getResources().getString(R.string.share_msg) + playStoreLink; + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, msg); + sendIntent.setType("text/plain"); + startActivity(sendIntent); + } + else if (id == R.id.action_about) { + SwAUtil.showAboutDialog(this); + } + else if (id == R.id.action_donate) { + SwABillingUtil.showDonateDialog(this, mHelper, this); + } + + return super.onOptionsItemSelected(item); + } + + /** + * A placeholder fragment containing a simple view. + */ + public static class PlaceholderFragment extends Fragment { + private Camera cam; + private Camera.Parameters camParams; + private boolean hasCam; + private int freq; + private StroboRunner sr; + private Thread t; + private boolean isChecked = false; + + public PlaceholderFragment() { + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + try { + //Log.d("TORCH", "Check cam"); + // Get CAM reference + cam = Camera.open(); + camParams = cam.getParameters(); + cam.startPreview(); + hasCam = true; + //Log.d("TORCH", "HAS CAM ["+hasCam+"]"); + } + catch(Throwable t) { + t.printStackTrace(); + } + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_main, container, false); + // Let's get the reference to the toggle + final ImageView tBtn = (ImageView) rootView.findViewById(R.id.iconLight); + tBtn.setImageResource(R.drawable.off); + + tBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isChecked = !isChecked; + + if (isChecked) + tBtn.setImageResource(R.drawable.on); + else + tBtn.setImageResource(R.drawable.off); + + turnOnOff(isChecked); + } + }); + + + // Seekbar + SeekBar skBar = (SeekBar) rootView.findViewById(R.id.seekBar); + skBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + freq = progress; + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + }); + return rootView; + } + + private void turnOnOff(boolean on) { + + if (on) { + if (freq != 0) { + sr = new StroboRunner(); + sr.freq = freq; + t = new Thread(sr); + t.start(); + return ; + } + else + camParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); + } + if (!on) { + if (t != null) { + sr.stopRunning = true; + t = null; + return ; + } + else + camParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + } + + cam.setParameters(camParams); + cam.startPreview(); + } + + + + private class StroboRunner implements Runnable { + + int freq; + boolean stopRunning = false; + + @Override + public void run() { + Camera.Parameters paramsOn = PlaceholderFragment.this.cam.getParameters(); + Camera.Parameters paramsOff = PlaceholderFragment.this.camParams; + paramsOn.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); + paramsOff.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + try { + while (!stopRunning) { + PlaceholderFragment.this.cam.setParameters(paramsOn); + PlaceholderFragment.this.cam.startPreview(); + // We make the thread sleeping + Thread.sleep(100 - freq); + PlaceholderFragment.this.cam.setParameters(paramsOff); + PlaceholderFragment.this.cam.startPreview(); + Thread.sleep(freq); + } + } + catch(Throwable t) {} + } + } + + + } + + +} diff --git a/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/SwAUtil.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/SwAUtil.java new file mode 100644 index 0000000..7ae7588 --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/SwAUtil.java @@ -0,0 +1,61 @@ +package com.survivingwithandroid.torch; + +import android.content.Context; +import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; +import android.widget.PopupWindow; +import android.widget.RelativeLayout; +import android.widget.TextView; + +/* + * Copyright (C) 2014 Francesco Azzola - Surviving with Android (http://www.survivingwithandroid.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. + */ + +public class SwAUtil { + public static void showAboutDialog(final Context ctx) { + LayoutInflater inf = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View v = inf.inflate(R.layout.about_layout, null, false); + createLink(v, R.id.link, " Surviving with Android app "); + createLink(v, R.id.link2, " Surviving with Android "); + + final PopupWindow pw = new PopupWindow(v); + pw.setWidth(RelativeLayout.LayoutParams.WRAP_CONTENT); + pw.setHeight(RelativeLayout.LayoutParams.WRAP_CONTENT); + + Button canBtn = (Button) v.findViewById(R.id.btnCancel); + + + canBtn.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + pw.dismiss(); + } + }); + + pw.showAtLocation(v, Gravity.CENTER, 0, 0); + } + + private static void createLink(View v, int id, String html) { + TextView textView =(TextView) v.findViewById(id); + textView.setClickable(true); + textView.setMovementMethod(LinkMovementMethod.getInstance()); + textView.setText(Html.fromHtml(html)); + } +} diff --git a/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Base64.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Base64.java new file mode 100644 index 0000000..a5d6c82 --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Base64.java @@ -0,0 +1,570 @@ +// 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 com.survivingwithandroid.torch.util; + +// This code was converted from code at http://iharder.sourceforge.net/base64/ +// Lots of extraneous features were removed. +/* The original code said: + *

+ * 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 + * http://iharder.net/xmlizable + * periodically to check for updates or to contribute improvements. + *

+ * + * @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. + * + *

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 source + * and writes the resulting four Base64 bytes to destination. + * The source and destination arrays can be manipulated + * anywhere along their length by specifying + * srcOffset and destOffset. + * This method does not check to make sure your arrays + * are large enough to accommodate srcOffset + 3 for + * the source array or destOffset + 4 for + * the destination array. + * The actual number of significant bytes in your array is + * given by numSigBytes. + * + * @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 destination 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 source + * and writes the resulting bytes (up to three of them) + * to destination. + * The source and destination arrays can be manipulated + * anywhere along their length by specifying + * srcOffset and destOffset. + * This method does not check to make sure your arrays + * are large enough to accommodate srcOffset + 4 for + * the source array or destOffset + 3 for + * the destination 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/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Base64DecoderException.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Base64DecoderException.java new file mode 100644 index 0000000..cdf3d9b --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Base64DecoderException.java @@ -0,0 +1,32 @@ +// 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 com.survivingwithandroid.torch.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/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabException.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabException.java new file mode 100644 index 0000000..8c2f797 --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabException.java @@ -0,0 +1,43 @@ +/* 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 com.survivingwithandroid.torch.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/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabHelper.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabHelper.java new file mode 100644 index 0000000..1739bdf --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabHelper.java @@ -0,0 +1,991 @@ +/* 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 com.survivingwithandroid.torch.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.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"); + serviceIntent.setPackage("com.android.vending"); + 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 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 moreItemSkus, + List 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 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 purchases, List 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 purchases = new ArrayList(); + 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 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 ownedSkus = ownedItems.getStringArrayList( + RESPONSE_INAPP_ITEM_LIST); + ArrayList purchaseDataList = ownedItems.getStringArrayList( + RESPONSE_INAPP_PURCHASE_DATA_LIST); + ArrayList 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 moreSkus) + throws RemoteException, JSONException { + logDebug("Querying SKU details."); + ArrayList skuList = new ArrayList(); + 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 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 purchases, + final OnConsumeFinishedListener singleListener, + final OnConsumeMultiFinishedListener multiListener) { + final Handler handler = new Handler(); + flagStartAsync("consume"); + (new Thread(new Runnable() { + public void run() { + final List results = new ArrayList(); + 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/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabResult.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabResult.java new file mode 100644 index 0000000..fa7dad3 --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/IabResult.java @@ -0,0 +1,45 @@ +/* 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 com.survivingwithandroid.torch.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/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Inventory.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Inventory.java new file mode 100644 index 0000000..99162ce --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Inventory.java @@ -0,0 +1,91 @@ +/* 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 com.survivingwithandroid.torch.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 mSkuMap = new HashMap(); + Map mPurchaseMap = new HashMap(); + + 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 getAllOwnedSkus() { + return new ArrayList(mPurchaseMap.keySet()); + } + + /** Returns a list of all owned product IDs of a given type */ + List getAllOwnedSkus(String itemType) { + List result = new ArrayList(); + for (Purchase p : mPurchaseMap.values()) { + if (p.getItemType().equals(itemType)) result.add(p.getSku()); + } + return result; + } + + /** Returns a list of all purchases. */ + List getAllPurchases() { + return new ArrayList(mPurchaseMap.values()); + } + + void addSkuDetails(SkuDetails d) { + mSkuMap.put(d.getSku(), d); + } + + void addPurchase(Purchase p) { + mPurchaseMap.put(p.getSku(), p); + } +} diff --git a/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Purchase.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Purchase.java new file mode 100644 index 0000000..b5eb282 --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Purchase.java @@ -0,0 +1,63 @@ +/* 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 com.survivingwithandroid.torch.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/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Security.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Security.java new file mode 100644 index 0000000..25657bc --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/Security.java @@ -0,0 +1,123 @@ +/* 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 com.survivingwithandroid.torch.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 (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) || + TextUtils.isEmpty(signature)) { + Log.e(TAG, "Purchase verification failed: missing data."); + return false; + } + + PublicKey key = Security.generatePublicKey(base64PublicKey); + return Security.verify(key, signedData, signature); + } + + /** + * 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/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/SkuDetails.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/SkuDetails.java new file mode 100644 index 0000000..9c2cc55 --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/SkuDetails.java @@ -0,0 +1,58 @@ +/* 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 com.survivingwithandroid.torch.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/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/SwABillingUtil.java b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/SwABillingUtil.java new file mode 100644 index 0000000..24ffed4 --- /dev/null +++ b/TorchApp/torch/src/main/java/com/survivingwithandroid/torch/util/SwABillingUtil.java @@ -0,0 +1,74 @@ +package com.survivingwithandroid.torch.util; + +import android.app.Activity; +import android.content.Context; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; +import android.widget.PopupWindow; +import android.widget.RelativeLayout; +import android.widget.Toast; + +import com.survivingwithandroid.torch.R; + + +/** + * Created by Francesco on 21/02/14. + */ +public class SwABillingUtil { + + public static String KEY = "YOUR_KEY"; + private static String SKU_DONATE = "YOUR_SKU"; + //private static String SKU_DONATE_W2 = "android.test.purchased"; + + + public static void showDonateDialog(final Context ctx, final IabHelper mHelper, final Activity act) { + LayoutInflater inf = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View v = inf.inflate(R.layout.popdonate_layout, null, false); + + final PopupWindow pw = new PopupWindow(v); + pw.setWidth(RelativeLayout.LayoutParams.WRAP_CONTENT); + pw.setHeight(RelativeLayout.LayoutParams.WRAP_CONTENT); + + Button canBtn = (Button) v.findViewById(R.id.btnCancelDonate); + + + canBtn.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + pw.dismiss(); + } + }); + + final Button donBtn = (Button) v.findViewById(R.id.btnDonate); + donBtn.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + String payload="test"; + + mHelper.launchPurchaseFlow(act, SKU_DONATE, 2000, + new IabHelper.OnIabPurchaseFinishedListener() { + @Override + public void onIabPurchaseFinished(IabResult result, Purchase info) { + if (result.isFailure()) { + Log.i("SwA", "Failure = " + result); + //Toast.makeText(getActivity(), "Error purchasing: " + result, Toast.LENGTH_LONG).show(); + return; + } else if (info.getSku().equals(SKU_DONATE)) { + donBtn.setClickable(false); + Toast.makeText(ctx, "Thank you!", Toast.LENGTH_LONG).show(); + } + } + }, payload); + pw.dismiss(); + + } + }); + + pw.showAtLocation(v, Gravity.CENTER, 0, 0); + } +} diff --git a/TorchApp/torch/src/main/res/drawable-hdpi/ic_launcher.png b/TorchApp/torch/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7c149976f892c8d1cb7fbdc2ab3e864ad1bfa3a5 GIT binary patch literal 8381 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 TY4p-*00000NkvXXu0mjfit_XK literal 0 HcmV?d00001 diff --git a/TorchApp/torch/src/main/res/drawable-mdpi/ic_launcher.png b/TorchApp/torch/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a585c007647dc4f099b2f5e6d186ba3a6973d99d GIT binary patch literal 4394 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 literal 0 HcmV?d00001 diff --git a/TorchApp/torch/src/main/res/drawable-xhdpi/ic_launcher.png b/TorchApp/torch/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..28fe12673587b9b6530fe4df6474c5756dbd1cb5 GIT binary patch literal 12664 zcmV-;F^A5HP)^5lAqMCWMS+AVben)u~hO|JPdkoKw}+K=F8=-}k=c-nOc%yPEF*U+Z7P zUVHC&Z0Em!DgyC;>VJLbe>}F6fPb

?B|(0smwK{>lIOogVQ23jy=y#S+IKA4@kh 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Ν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­v5?8%5BT-|WIHZy-3ML)pC7}< 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 literal 0 HcmV?d00001 diff --git a/TorchApp/torch/src/main/res/drawable-xxxhdpi/ic_launcher.png b/TorchApp/torch/src/main/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..9a915653ae8cb07fb06ffb23644d1236fad68a39 GIT binary patch literal 32618 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 tpn?2yJc6 literal 0 HcmV?d00001 diff --git a/TorchApp/torch/src/main/res/drawable/off.png b/TorchApp/torch/src/main/res/drawable/off.png new file mode 100644 index 0000000000000000000000000000000000000000..b5af67be31be75dc138d4f8b3e86df2fcff6c88d GIT binary patch literal 23996 zcmZsDc{tQv`1j1%vxRISp%5ZVjImYrY}vCbTVtP?Oo$mOJ0XNY%OJ9avNN6@`<4+Z z4U?%fgei&;@0p(8@4enX-sifyo~!wu@A;l{FQ5B9_x(AgT(UOhK6LaD1OnkUH#4$> zKw#F4KkTgFm-8;kKf(W)BQBUbu!H|%*?p72-#Nm~Tp}P4kz&Rls5v_EKKM~I()e_*+^R1HDn=a1%PjGs#-|0T1gzl+pSm-Lwz!$qT>|3#Tf^?y`gGPKwq~c1Vdlph1 z(*5U729@7bQnZ_8ivN0RuU4LVb;MiRPESxS`!45vh^2yQmgM)9Uxb*u|Bk~b2)mT_ z8?<_3(e*P{C#7%MqWF=?6mk)fN6G8n4VY%*=*iq0Y%-}1>$5AVYRZf;0*@C@*xC1X zjA6TQx1xL2xGc4}PbU6gr|VGoDYL|r#-ayEF>@o6Ctw&;ZwHc?Nl0jJRtiBLy;wsY zO_nxx%_E7uOjZ??;{%UhVC9->zy4>+kWHzn?|e``^;SxFd%=gMy%(-6=ky-Ju*hliz zF0lE2V2UpUJ7YA$PtXIsL%J=2sCiF>t23gimhjo zJT;7I0+P%IZ)he&6*CRM>S6vz2at(wI0MLR=JwB>$LU!QDgp~B|~%E=}(l- zqmg09%SMQq&#jNsTU?U(pn`H$I0{*o7-LrKR2M2d}tgKnPX%H)UP6Nq#!IYGIhx~<%89W$GuF||zls5I;|a~9exvD{eH zV$RI2e7yemwkem4lT!x1+%ZE{mybCijurH3e(6OT8V2 zSeu+e#j<$+tftGUUvTfUtP-?FNRguC!wt&%0A<~PWJ}V;H)&>ywy(DD^?Tu-q^a${MkH$#r{-F^ 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 W=z+Z)Eq5TTqb!fwnU()RiTi&z5? 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 literal 0 HcmV?d00001 diff --git a/TorchApp/torch/src/main/res/layout/about_layout.xml b/TorchApp/torch/src/main/res/layout/about_layout.xml new file mode 100644 index 0000000..7dc5522 --- /dev/null +++ b/TorchApp/torch/src/main/res/layout/about_layout.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + +