Admob version update + checkout library instead of old billing

This commit is contained in:
serso
2015-01-24 23:22:04 +01:00
parent 9ab677af81
commit d5e5c9b6ac
42 changed files with 846 additions and 451 deletions

View File

@@ -0,0 +1,90 @@
package org.solovyev.android.calculator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import javax.annotation.Nullable;
public class AdView extends FrameLayout {
@Nullable
private com.google.android.gms.ads.AdView admobView;
public AdView(Context context) {
super(context);
}
public AdView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AdView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void destroy() {
if (admobView != null) {
admobView.destroy();
}
}
public void pause() {
if (admobView != null) {
admobView.pause();
}
}
public void resume() {
if (admobView != null) {
admobView.resume();
}
}
public void show() {
if (admobView != null) {
return;
}
setVisibility(VISIBLE);
LayoutInflater.from(getContext()).inflate(R.layout.admob, this);
admobView = (com.google.android.gms.ads.AdView) findViewById(R.id.admob);
admobView.setVisibility(View.VISIBLE);
admobView.setAdListener(new AdListener() {
@Override
public void onAdFailedToLoad(int errorCode) {
hide();
}
@Override
public void onAdLoaded() {
}
});
final AdRequest.Builder b = new AdRequest.Builder();
b.addTestDevice(AdRequest.DEVICE_ID_EMULATOR);
if (BuildConfig.DEBUG) {
// LG Nexus 5
b.addTestDevice("B80E676D60CE6FDBE1B84A55464E3FE1");
}
admobView.loadAd(b.build());
}
public void hide() {
if(admobView == null) {
return;
}
setVisibility(GONE);
admobView.setVisibility(View.GONE);
admobView.pause();
admobView.destroy();
admobView = null;
}
}

View File

@@ -32,13 +32,9 @@ import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import jscl.math.Generic;
import org.solovyev.android.Android;
import org.solovyev.android.App;
import org.solovyev.android.calculator.about.CalculatorAboutActivity;
import org.solovyev.android.calculator.function.FunctionEditDialogFragment;
import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
@@ -46,14 +42,13 @@ import org.solovyev.android.calculator.math.edit.*;
import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity;
import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
import org.solovyev.android.calculator.plot.CalculatorPlotter;
import org.solovyev.android.calculator.preferences.CalculatorPreferencesActivity;
import org.solovyev.android.calculator.preferences.PreferencesActivity;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
/**
@@ -81,7 +76,7 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
}
public static void showSettings(@Nonnull final Context context, boolean detached) {
final Intent intent = new Intent(context, CalculatorPreferencesActivity.class);
final Intent intent = new Intent(context, PreferencesActivity.class);
Android.addIntentFlags(intent, detached, context);
context.startActivity(intent);
}

View File

@@ -29,16 +29,10 @@ import android.graphics.Typeface;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import net.robotmedia.billing.BillingController;
import net.robotmedia.billing.helper.DefaultBillingObserver;
import net.robotmedia.billing.model.BillingDB;
import org.acra.ACRA;
import org.acra.ReportingInteractionMode;
import org.acra.annotation.ReportsCrashes;
import org.solovyev.android.Android;
import org.solovyev.android.App;
import org.solovyev.android.ServiceLocator;
import org.solovyev.android.ads.AdsController;
import org.solovyev.android.calculator.history.AndroidCalculatorHistory;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenStartActivity;
@@ -46,12 +40,15 @@ import org.solovyev.android.calculator.plot.AndroidCalculatorPlotter;
import org.solovyev.android.calculator.plot.CalculatorPlotterImpl;
import org.solovyev.android.calculator.view.EditorTextProcessor;
import org.solovyev.android.calculator.wizard.CalculatorWizards;
import org.solovyev.android.checkout.*;
import org.solovyev.android.wizard.Wizards;
import org.solovyev.common.msg.MessageType;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
/**
* User: serso
@@ -74,12 +71,14 @@ public class CalculatorApplication extends android.app.Application implements Sh
**********************************************************************
*/
@Nonnull
static final String MAIL = "se.solovyev@gmail.com";
private static final String TAG = "Calculator++ Application";
public static final String AD_FREE_PRODUCT_ID = "ad_free";
public static final String AD_FREE_P_KEY = "org.solovyev.android.calculator_ad_free";
public static final String ADMOB_USER_ID = "a14f02cf9c80cbc";
public static final String ADMOB = "ca-app-pub-2228934497384784/2916398892";
@Nonnull
private static CalculatorApplication instance;
@@ -109,6 +108,25 @@ public class CalculatorApplication extends android.app.Application implements Sh
@Nonnull
private Typeface typeFace;
@Nonnull
private final Billing billing = new Billing(this, new Billing.DefaultConfiguration() {
@Nonnull
@Override
public String getPublicKey() {
return CalculatorSecurity.getPK();
}
@Nullable
@Override
public Inventory getFallbackInventory(@Nonnull Checkout checkout, @Nonnull Executor onLoadExecutor) {
if (RobotmediaDatabase.exists(billing.getContext())) {
return new RobotmediaInventory(checkout, onLoadExecutor);
} else {
return null;
}
}
});
/*
**********************************************************************
*
@@ -137,7 +155,9 @@ public class CalculatorApplication extends android.app.Application implements Sh
@Override
public void onCreate() {
ACRA.init(this);
if (!BuildConfig.DEBUG) {
ACRA.init(this);
}
if (!App.isInitialized()) {
App.init(this);
@@ -178,32 +198,11 @@ public class CalculatorApplication extends android.app.Application implements Sh
Locator.getInstance().getCalculator().init();
BillingDB.init(CalculatorApplication.this);
billing.connect();
if (withAds) {
AdsController.getInstance().init(this, ADMOB_USER_ID, AD_FREE_PRODUCT_ID, new BillingController.IConfiguration() {
@Override
public byte[] getObfuscationSalt() {
return new byte[]{81, -114, 32, -127, -32, -104, -40, -15, -47, 57, -13, -41, -33, 67, -114, 7, -11, 53, 126, 82};
}
@Override
public String getPublicKey() {
return CalculatorSecurity.getPK();
}
});
}
BillingController.registerObserver(new DefaultBillingObserver(this, null));
// init billing controller
new Thread(new Runnable() {
@Override
public void run() {
BillingController.checkBillingSupported(CalculatorApplication.this);
AdsController.getInstance().isAdFree(CalculatorApplication.this);
try {
// prepare engine
Locator.getInstance().getEngine().getMathEngine0().evaluate("1+1");
@@ -261,6 +260,11 @@ public class CalculatorApplication extends android.app.Application implements Sh
return typeFace;
}
@Nonnull
public Billing getBilling() {
return billing;
}
/*
**********************************************************************
*

View File

@@ -23,17 +23,17 @@
package org.solovyev.android.calculator;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.google.ads.AdView;
import org.solovyev.android.checkout.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.ads.AdsController;
import static java.util.Arrays.asList;
/**
* User: serso
@@ -42,6 +42,8 @@ import org.solovyev.android.ads.AdsController;
*/
public class CalculatorFragmentHelperImpl extends AbstractCalculatorHelper implements CalculatorFragmentHelper {
private ActivityCheckout checkout;
@Nullable
private AdView adView;
@@ -51,6 +53,9 @@ public class CalculatorFragmentHelperImpl extends AbstractCalculatorHelper imple
private boolean listenersOnCreate = true;
@Nullable
private Boolean adFree = null;
public CalculatorFragmentHelperImpl(int layoutId) {
this.layoutId = layoutId;
}
@@ -84,26 +89,57 @@ public class CalculatorFragmentHelperImpl extends AbstractCalculatorHelper imple
@Override
public void onCreate(@Nonnull Fragment fragment) {
super.onCreate(fragment.getActivity());
final FragmentActivity activity = fragment.getActivity();
super.onCreate(activity);
checkout = Checkout.forActivity(activity, CalculatorApplication.getInstance().getBilling(), Products.create().add(ProductTypes.IN_APP, asList("ad_free")));
if (listenersOnCreate) {
if (fragment instanceof CalculatorEventListener) {
Locator.getInstance().getCalculator().addCalculatorEventListener((CalculatorEventListener) fragment);
}
}
checkout.start();
}
@Override
public void onResume(@Nonnull Fragment fragment) {
if (adView != null) {
adView.resume();
}
if (!listenersOnCreate) {
if (fragment instanceof CalculatorEventListener) {
Locator.getInstance().getCalculator().addCalculatorEventListener((CalculatorEventListener) fragment);
}
}
checkout.loadInventory().whenLoaded(new Inventory.Listener() {
@Override
public void onLoaded(@Nonnull Inventory.Products products) {
adFree = products.get(ProductTypes.IN_APP).isPurchased("ad_free");
updateAdViewState();
}
});
}
private void updateAdViewState() {
if(adFree == null || adView == null) {
return;
}
if (adFree) {
adView.hide();
} else {
adView.show();
}
}
@Override
public void onPause(@Nonnull Fragment fragment) {
adFree = null;
if (adView != null) {
adView.pause();
}
if (!listenersOnCreate) {
if (fragment instanceof CalculatorEventListener) {
Locator.getInstance().getCalculator().removeCalculatorEventListener((CalculatorEventListener) fragment);
@@ -113,16 +149,15 @@ public class CalculatorFragmentHelperImpl extends AbstractCalculatorHelper imple
@Override
public void onViewCreated(@Nonnull Fragment fragment, @Nonnull View root) {
final ViewGroup adParentView = (ViewGroup) root.findViewById(R.id.ad_parent_view);
adView = (AdView) root.findViewById(R.id.ad);
final ViewGroup mainFragmentLayout = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
if (fragment instanceof CalculatorDisplayFragment || fragment instanceof CalculatorEditorFragment || fragment instanceof CalculatorKeyboardFragment) {
// no ads in those fragments
} else {
if (adParentView != null) {
adView = AdsController.getInstance().inflateAd(fragment.getActivity(), adParentView, R.id.ad_parent_view);
if (adView != null) {
updateAdViewState();
} else if (mainFragmentLayout != null) {
adView = AdsController.getInstance().inflateAd(fragment.getActivity(), mainFragmentLayout, R.id.main_fragment_layout);
}
}
@@ -135,7 +170,10 @@ public class CalculatorFragmentHelperImpl extends AbstractCalculatorHelper imple
@Override
public void onDestroy(@Nonnull Fragment fragment) {
super.onDestroy(fragment.getActivity());
if (adView != null) {
adView.destroy();
adView = null;
}
if (listenersOnCreate) {
if (fragment instanceof CalculatorEventListener) {
@@ -143,9 +181,9 @@ public class CalculatorFragmentHelperImpl extends AbstractCalculatorHelper imple
}
}
if (this.adView != null) {
this.adView.destroy();
}
checkout.stop();
super.onDestroy(fragment.getActivity());
}
@Nonnull

View File

@@ -417,7 +417,7 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
preferences(R.id.menu_plot_settings) {
@Override
public void onClick(@Nonnull MenuItem data, @Nonnull Context context) {
context.startActivity(new Intent(context, CalculatorPlotPreferenceActivity.class));
context.startActivity(new Intent(context, PlotPreferenceActivity.class));
}
};

View File

@@ -23,17 +23,10 @@
package org.solovyev.android.calculator.plot;
import android.os.Bundle;
import com.actionbarsherlock.app.SherlockPreferenceActivity;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.preferences.BasePreferencesActivity;
/**
* User: serso
* Date: 10/4/12
* Time: 9:01 PM
*/
public class CalculatorPlotPreferenceActivity extends SherlockPreferenceActivity {
public class PlotPreferenceActivity extends BasePreferencesActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {

View File

@@ -0,0 +1,92 @@
package org.solovyev.android.calculator.preferences;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import com.actionbarsherlock.app.SherlockPreferenceActivity;
import org.solovyev.android.calculator.AdView;
import org.solovyev.android.calculator.CalculatorApplication;
import org.solovyev.android.calculator.R;
import org.solovyev.android.checkout.*;
import javax.annotation.Nonnull;
import static java.util.Arrays.asList;
public abstract class BasePreferencesActivity extends SherlockPreferenceActivity {
private final ActivityCheckout checkout = Checkout.forActivity(this, CalculatorApplication.getInstance().getBilling(), Products.create().add(ProductTypes.IN_APP, asList("ad_free")));
private Inventory inventory;
private AdView adView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkout.start();
inventory = checkout.loadInventory();
}
private class InventoryListener implements Inventory.Listener {
@Override
public void onLoaded(@Nonnull Inventory.Products products) {
final Inventory.Product product = products.get(ProductTypes.IN_APP);
final boolean adFree = product.isPurchased("ad_free");
onShowAd(!adFree);
}
}
protected void onShowAd(boolean show) {
if (show) {
if (adView != null) {
return;
}
adView = (AdView) LayoutInflater.from(this).inflate(R.layout.ad, null);
adView.show();
getListView().addHeaderView(adView);
} else {
if (adView == null) {
return;
}
getListView().removeHeaderView(adView);
adView.hide();
adView = null;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (checkout.onActivityResult(requestCode, resultCode, data)) {
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
protected void onResume() {
super.onResume();
if (adView != null) {
adView.resume();
}
inventory.whenLoaded(new InventoryListener());
}
@Override
protected void onPause() {
if (adView != null) {
adView.pause();
}
super.onPause();
}
@Override
protected void onDestroy() {
if (adView != null) {
adView.destroy();
}
checkout.stop();
super.onDestroy();
}
}

View File

@@ -1,228 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.preferences;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockPreferenceActivity;
import net.robotmedia.billing.BillingController;
import net.robotmedia.billing.IBillingObserver;
import net.robotmedia.billing.ResponseCode;
import net.robotmedia.billing.helper.AbstractBillingObserver;
import net.robotmedia.billing.model.Transaction;
import org.solovyev.android.Activities;
import org.solovyev.android.App;
import org.solovyev.android.ads.AdsController;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.wizard.CalculatorWizards;
import org.solovyev.android.msg.AndroidMessage;
import org.solovyev.android.view.VibratorContainer;
import org.solovyev.android.wizard.WizardUi;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType;
import javax.annotation.Nonnull;
import static org.solovyev.android.calculator.wizard.CalculatorWizards.DEFAULT_WIZARD_FLOW;
import static org.solovyev.android.wizard.WizardUi.startWizard;
/**
* User: serso
* Date: 7/16/11
* Time: 6:37 PM
*/
public class CalculatorPreferencesActivity extends SherlockPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener, IBillingObserver {
public static final String PREFERENCE_CLEAR_BILLING_INFO = "clear_billing_info";
public static final String PREFERENCE_RESTART_WIZARD = "restart_wizard";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//noinspection deprecation
addPreferencesFromResource(R.xml.preferences);
//noinspection deprecation
addPreferencesFromResource(R.xml.preferences_calculations);
addPreferencesFromResource(R.xml.preferences_appearance);
addPreferencesFromResource(R.xml.preferences_plot);
addPreferencesFromResource(R.xml.preferences_other);
addPreferencesFromResource(R.xml.preferences_onscreen);
final Preference restartWizardPreference = findPreference(PREFERENCE_RESTART_WIZARD);
restartWizardPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
startWizard(CalculatorApplication.getInstance().getWizards(), DEFAULT_WIZARD_FLOW, CalculatorPreferencesActivity.this);
return true;
}
});
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
adFreePreference.setEnabled(false);
// observer must be set before net.robotmedia.billing.BillingController.checkBillingSupported()
BillingController.registerObserver(this);
BillingController.checkBillingSupported(CalculatorPreferencesActivity.this);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
preferences.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(preferences, AndroidCalculatorEngine.Preferences.roundResult.getKey());
onSharedPreferenceChanged(preferences, VibratorContainer.Preferences.hapticFeedbackEnabled.getKey());
final Preference clearBillingInfoPreference = findPreference(PREFERENCE_CLEAR_BILLING_INFO);
if (clearBillingInfoPreference != null) {
clearBillingInfoPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_clearing, Toast.LENGTH_SHORT).show();
removeBillingInformation(CalculatorPreferencesActivity.this, PreferenceManager.getDefaultSharedPreferences(CalculatorPreferencesActivity.this));
return true;
}
});
}
}
public static void removeBillingInformation(@Nonnull Context context, @Nonnull SharedPreferences preferences) {
final SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(AbstractBillingObserver.KEY_TRANSACTIONS_RESTORED, false);
editor.commit();
BillingController.dropBillingData(context);
}
private void setAdFreeAction() {
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
if (!AdsController.getInstance().isAdFree(this)) {
Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - enable preference!");
adFreePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
final Context context = CalculatorPreferencesActivity.this;
context.startActivity(new Intent(context, CalculatorPurchaseDialogActivity.class));
return true;
}
});
adFreePreference.setEnabled(true);
} else {
Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - disable preference!");
adFreePreference.setEnabled(false);
}
}
@Override
protected void onDestroy() {
BillingController.unregisterObserver(this);
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (AndroidCalculatorEngine.Preferences.roundResult.getKey().equals(key)) {
findPreference(AndroidCalculatorEngine.Preferences.precision.getKey()).setEnabled(preferences.getBoolean(key, AndroidCalculatorEngine.Preferences.roundResult.getDefaultValue()));
} else if (VibratorContainer.Preferences.hapticFeedbackEnabled.getKey().equals(key)) {
findPreference(VibratorContainer.Preferences.hapticFeedbackDuration.getKey()).setEnabled(VibratorContainer.Preferences.hapticFeedbackEnabled.getPreference(preferences));
}
}
@Override
public void onCheckBillingSupportedResponse(boolean supported) {
if (supported) {
setAdFreeAction();
} else {
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
adFreePreference.setEnabled(false);
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported!");
}
}
@Override
public void onPurchaseIntentOK(@Nonnull String productId, @Nonnull PendingIntent purchaseIntent) {
// do nothing
}
@Override
public void onPurchaseIntentFailure(@Nonnull String productId, @Nonnull ResponseCode responseCode) {
// do nothing
}
@Override
public void onPurchaseStateChanged(@Nonnull String itemId, @Nonnull Transaction.PurchaseState state) {
if (CalculatorApplication.AD_FREE_PRODUCT_ID.equals(itemId)) {
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
if (adFreePreference != null) {
switch (state) {
case PURCHASED:
adFreePreference.setEnabled(false);
// restart activity to disable ads
Activities.restartActivity(this);
break;
case CANCELLED:
adFreePreference.setEnabled(true);
break;
case REFUNDED:
adFreePreference.setEnabled(true);
break;
}
} else {
}
}
}
@Override
public void onRequestPurchaseResponse(@Nonnull String itemId, @Nonnull ResponseCode response) {
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
if (adFreePreference != null) {
if (response == ResponseCode.RESULT_OK) {
adFreePreference.setEnabled(false);
final Message message = new AndroidMessage(R.string.cpp_purchase_thank_you_text, MessageType.info, App.getApplication());
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_message_dialog, MessageDialogData.newInstance(message, null));
}
}
}
@Override
public void onTransactionsRestored() {
// do nothing
}
@Override
public void onErrorRestoreTransactions(@Nonnull ResponseCode responseCode) {
// do nothing
}
}

View File

@@ -23,28 +23,22 @@
package org.solovyev.android.calculator.preferences;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import net.robotmedia.billing.BillingController;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.ads.AdsController;
import org.solovyev.android.calculator.CalculatorApplication;
import org.solovyev.android.calculator.CalculatorFragment;
import org.solovyev.android.calculator.CalculatorFragmentType;
import org.solovyev.android.calculator.R;
import org.solovyev.android.checkout.*;
import org.solovyev.android.fragments.FragmentUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 1/20/13
@@ -52,6 +46,22 @@ import org.solovyev.android.fragments.FragmentUtils;
*/
public class CalculatorPurchaseDialogActivity extends SherlockFragmentActivity {
@Nonnull
private final ActivityCheckout checkout = Checkout.forActivity(this, CalculatorApplication.getInstance().getBilling(), Products.create().add("ad_free"));
@Nonnull
private final RequestListener<Purchase> purchaseListener = new RequestListener<Purchase>() {
@Override
public void onSuccess(@Nonnull Purchase purchase) {
finish();
}
@Override
public void onError(int i, @Nonnull Exception e) {
finish();
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -59,6 +69,9 @@ public class CalculatorPurchaseDialogActivity extends SherlockFragmentActivity {
setContentView(R.layout.cpp_dialog);
FragmentUtils.createFragment(this, PurchaseDialogFragment.class, R.id.dialog_layout, "purchase-dialog");
checkout.start();
checkout.createPurchaseFlow(purchaseListener);
}
public static class PurchaseDialogFragment extends CalculatorFragment {
@@ -75,36 +88,35 @@ public class CalculatorPurchaseDialogActivity extends SherlockFragmentActivity {
root.findViewById(R.id.cpp_continue_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Activity activity = getActivity();
if (activity != null) {
// check billing availability
if (BillingController.checkBillingSupported(activity) != BillingController.BillingStatus.SUPPORTED) {
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported - warn user!");
// warn about not supported billing
new AlertDialog.Builder(activity).setTitle(R.string.c_error).setMessage(R.string.c_billing_error).create().show();
} else {
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is supported - continue!");
if (!AdsController.getInstance().isAdFree(activity)) {
Log.d(CalculatorPreferencesActivity.class.getName(), "Item not purchased - try to purchase!");
// not purchased => purchasing
Toast.makeText(activity, R.string.c_calc_purchasing, Toast.LENGTH_SHORT).show();
// show purchase window for user
BillingController.requestPurchase(activity, CalculatorApplication.AD_FREE_PRODUCT_ID, true);
} else {
// and show message to user
Toast.makeText(activity, R.string.c_calc_already_purchased, Toast.LENGTH_SHORT).show();
}
}
activity.finish();
((CalculatorPurchaseDialogActivity) activity).purchase();
}
}
});
}
}
private void purchase() {
checkout.whenReady(new Checkout.ListenerAdapter() {
@Override
public void onReady(@Nonnull BillingRequests requests) {
requests.purchase(ProductTypes.IN_APP, "ad_free", null, checkout.getPurchaseFlow());
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
checkout.onActivityResult(requestCode, resultCode, data);
}
@Override
protected void onDestroy() {
checkout.destroyPurchaseFlow();
checkout.stop();
super.onDestroy();
}
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.preferences;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.util.SparseArray;
import org.solovyev.android.calculator.CalculatorApplication;
import org.solovyev.android.calculator.R;
import javax.annotation.Nonnull;
import static org.solovyev.android.calculator.CalculatorApplication.AD_FREE_P_KEY;
import static org.solovyev.android.calculator.model.AndroidCalculatorEngine.Preferences.precision;
import static org.solovyev.android.calculator.model.AndroidCalculatorEngine.Preferences.roundResult;
import static org.solovyev.android.calculator.wizard.CalculatorWizards.DEFAULT_WIZARD_FLOW;
import static org.solovyev.android.view.VibratorContainer.Preferences.hapticFeedbackDuration;
import static org.solovyev.android.view.VibratorContainer.Preferences.hapticFeedbackEnabled;
import static org.solovyev.android.wizard.WizardUi.startWizard;
@SuppressWarnings("deprecation")
public class PreferencesActivity extends BasePreferencesActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
@Nonnull
private static final SparseArray<String> preferences = new SparseArray<String>();
static {
preferences.append(R.xml.preferences, "screen-main");
preferences.append(R.xml.preferences_calculations, "screen-calculations");
preferences.append(R.xml.preferences_appearance, "screen-appearance");
preferences.append(R.xml.preferences_plot, "screen-plot");
preferences.append(R.xml.preferences_other, "screen-other");
preferences.append(R.xml.preferences_onscreen, "screen-onscreen");
}
private Preference adFreePreference;
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
final int preference = intent.getIntExtra("preference", R.xml.preferences);
final String title = intent.getStringExtra("preference-title");
setPreference(preference, preferences.get(preference));
if (preference == R.xml.preferences) {
for (int i = 0; i < preferences.size(); i++) {
final int xml = preferences.keyAt(i);
final String name = preferences.valueAt(i);
setPreferenceIntent(xml, name);
}
final Preference restartWizardPreference = findPreference("restart_wizard");
restartWizardPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
startWizard(CalculatorApplication.getInstance().getWizards(), DEFAULT_WIZARD_FLOW, PreferencesActivity.this);
return true;
}
});
adFreePreference = findPreference(AD_FREE_P_KEY);
adFreePreference.setEnabled(false);
adFreePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
startActivity(new Intent(getApplicationContext(), CalculatorPurchaseDialogActivity.class));
return true;
}
});
}
if (title != null) {
setTitle(title);
}
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
preferences.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(preferences, roundResult.getKey());
onSharedPreferenceChanged(preferences, hapticFeedbackEnabled.getKey());
}
private void setPreference(int xml, @Nonnull String name) {
addPreferencesFromResource(xml);
}
private void setPreferenceIntent(int xml, @Nonnull String name) {
final Preference preference = findPreference(name);
if (preference != null) {
final Intent intent = new Intent(getApplicationContext(), PreferencesActivity.class);
intent.putExtra("preference", xml);
intent.putExtra("preference-title", preference.getTitle());
preference.setIntent(intent);
}
}
@Override
protected void onDestroy() {
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (roundResult.getKey().equals(key)) {
final Preference preference = findPreference(precision.getKey());
if (preference != null) {
preference.setEnabled(preferences.getBoolean(key, roundResult.getDefaultValue()));
}
} else if (hapticFeedbackEnabled.getKey().equals(key)) {
final Preference preference = findPreference(hapticFeedbackDuration.getKey());
if (preference != null) {
preference.setEnabled(hapticFeedbackEnabled.getPreference(preferences));
}
}
}
@Override
protected void onShowAd(boolean show) {
super.onShowAd(show);
if (adFreePreference != null) {
adFreePreference.setEnabled(show);
}
}
}

View File

@@ -25,7 +25,7 @@ package org.solovyev.android.calculator.wizard;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import org.solovyev.android.App;
import org.solovyev.android.calculator.App;
import org.solovyev.android.Views;
import org.solovyev.android.calculator.CalculatorPreferences;
import org.solovyev.android.calculator.R;