remove non-functioning billing implementation

Google Play doesn't allow an app signed with a different certificate to
trigger an IAP.
This commit is contained in:
Marcus Hoffmann 2023-11-12 19:45:34 +01:00
parent 0552254213
commit f3cb964d3d
9 changed files with 25 additions and 316 deletions

View File

@ -88,7 +88,6 @@ dependencies {
implementation(project(':jscl')) { implementation(project(':jscl')) {
exclude(module: 'xercesImpl') exclude(module: 'xercesImpl')
} }
implementation 'org.solovyev.android:checkout:1.3.1'
implementation 'com.google.guava:guava:32.1.2-android' implementation 'com.google.guava:guava:32.1.2-android'
implementation('org.simpleframework:simple-xml:2.7.1') { implementation('org.simpleframework:simple-xml:2.7.1') {
exclude(module: 'stax') exclude(module: 'stax')

View File

@ -2,7 +2,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto"> android:installLocation="auto">
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<!-- for onscreen --> <!-- for onscreen -->

View File

@ -1,6 +1,5 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import dagger.Component;
import org.solovyev.android.calculator.converter.ConverterFragment; import org.solovyev.android.calculator.converter.ConverterFragment;
import org.solovyev.android.calculator.errors.FixableErrorFragment; import org.solovyev.android.calculator.errors.FixableErrorFragment;
import org.solovyev.android.calculator.errors.FixableErrorsActivity; import org.solovyev.android.calculator.errors.FixableErrorsActivity;
@ -20,7 +19,6 @@ import org.solovyev.android.calculator.plot.PlotEditFunctionFragment;
import org.solovyev.android.calculator.plot.PlotFunctionsFragment; import org.solovyev.android.calculator.plot.PlotFunctionsFragment;
import org.solovyev.android.calculator.preferences.PreferencesActivity; import org.solovyev.android.calculator.preferences.PreferencesActivity;
import org.solovyev.android.calculator.preferences.PreferencesFragment; import org.solovyev.android.calculator.preferences.PreferencesFragment;
import org.solovyev.android.calculator.preferences.PurchaseDialogActivity;
import org.solovyev.android.calculator.variables.EditVariableFragment; import org.solovyev.android.calculator.variables.EditVariableFragment;
import org.solovyev.android.calculator.variables.VariablesFragment; import org.solovyev.android.calculator.variables.VariablesFragment;
import org.solovyev.android.calculator.view.Tabs; import org.solovyev.android.calculator.view.Tabs;
@ -31,6 +29,8 @@ import org.solovyev.android.calculator.wizard.WizardFragment;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Component;
@Singleton @Singleton
@Component(modules = AppModule.class) @Component(modules = AppModule.class)
public interface AppComponent { public interface AppComponent {
@ -54,7 +54,6 @@ public interface AppComponent {
void inject(WidgetReceiver receiver); void inject(WidgetReceiver receiver);
void inject(DisplayFragment fragment); void inject(DisplayFragment fragment);
void inject(KeyboardFragment fragment); void inject(KeyboardFragment fragment);
void inject(PurchaseDialogActivity activity);
void inject(PreferencesActivity activity); void inject(PreferencesActivity activity);
void inject(BaseKeyboardUi ui); void inject(BaseKeyboardUi ui);
void inject(FloatingCalculatorView view); void inject(FloatingCalculatorView view);

View File

@ -7,19 +7,15 @@ import android.graphics.Typeface;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import androidx.annotation.NonNull;
import android.util.Log; import android.util.Log;
import com.squareup.otto.Bus; import androidx.annotation.NonNull;
import com.squareup.otto.Bus;
import com.squareup.otto.GeneratedHandlerFinder; import com.squareup.otto.GeneratedHandlerFinder;
import org.solovyev.android.calculator.language.Languages; import org.solovyev.android.calculator.language.Languages;
import org.solovyev.android.calculator.wizard.CalculatorWizards; import org.solovyev.android.calculator.wizard.CalculatorWizards;
import org.solovyev.android.checkout.Billing;
import org.solovyev.android.checkout.Checkout;
import org.solovyev.android.checkout.Inventory;
import org.solovyev.android.checkout.RobotmediaDatabase;
import org.solovyev.android.checkout.RobotmediaInventory;
import org.solovyev.android.plotter.Plot; import org.solovyev.android.plotter.Plot;
import org.solovyev.android.plotter.Plotter; import org.solovyev.android.plotter.Plotter;
import org.solovyev.android.wizard.Wizards; import org.solovyev.android.wizard.Wizards;
@ -31,7 +27,6 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -182,28 +177,6 @@ public class AppModule {
return JsclMathEngine.getInstance(); return JsclMathEngine.getInstance();
} }
@Provides
@Singleton
Billing provideBilling() {
return new Billing(application, 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(application)) {
return new RobotmediaInventory(checkout, onLoadExecutor);
} else {
return null;
}
}
});
}
@Singleton @Singleton
@Provides @Provides
Typeface provideTypeface() { Typeface provideTypeface() {

View File

@ -4,19 +4,17 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.util.SparseArray;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.annotation.XmlRes; import androidx.annotation.XmlRes;
import android.util.SparseArray;
import org.solovyev.android.calculator.App; import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.AppComponent; import org.solovyev.android.calculator.AppComponent;
import org.solovyev.android.calculator.BaseActivity; import org.solovyev.android.calculator.BaseActivity;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.language.Languages; import org.solovyev.android.calculator.language.Languages;
import org.solovyev.android.checkout.ActivityCheckout;
import org.solovyev.android.checkout.Billing;
import org.solovyev.android.checkout.Checkout;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.inject.Inject; import javax.inject.Inject;
@ -42,10 +40,6 @@ public class PreferencesActivity extends BaseActivity implements SharedPreferenc
preferenceDefs.append(R.xml.preferences_widget, new PrefDef("screen-widget", R.string.cpp_widget)); preferenceDefs.append(R.xml.preferences_widget, new PrefDef("screen-widget", R.string.cpp_widget));
} }
ActivityCheckout checkout;
@Inject
Billing billing;
@Inject @Inject
Languages languages; Languages languages;
@ -84,9 +78,6 @@ public class PreferencesActivity extends BaseActivity implements SharedPreferenc
.add(R.id.main, PreferencesFragment.create(preference)) .add(R.id.main, PreferencesFragment.create(preference))
.commit(); .commit();
} }
checkout = Checkout.forActivity(this, billing);
checkout.start();
} }
@Override @Override
@ -95,17 +86,6 @@ public class PreferencesActivity extends BaseActivity implements SharedPreferenc
component.inject(this); component.inject(this);
} }
@Override
protected void onDestroy() {
checkout.stop();
super.onDestroy();
}
@Nonnull
ActivityCheckout getCheckout() {
return checkout;
}
static class PrefDef { static class PrefDef {
@Nonnull @Nonnull
public final String id; public final String id;

View File

@ -5,31 +5,24 @@ import static org.solovyev.android.calculator.Engine.Preferences.angleUnitName;
import static org.solovyev.android.calculator.Engine.Preferences.numeralBaseName; import static org.solovyev.android.calculator.Engine.Preferences.numeralBaseName;
import static org.solovyev.android.calculator.wizard.CalculatorWizards.DEFAULT_WIZARD_FLOW; import static org.solovyev.android.calculator.wizard.CalculatorWizards.DEFAULT_WIZARD_FLOW;
import static org.solovyev.android.wizard.WizardUi.startWizard; import static org.solovyev.android.wizard.WizardUi.startWizard;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.util.SparseArray; import android.util.SparseArray;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceDialogFragmentCompat; import androidx.preference.PreferenceDialogFragmentCompat;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import jscl.AngleUnit;
import jscl.JsclMathEngine;
import jscl.NumeralBase;
import org.solovyev.android.calculator.ActivityLauncher; import org.solovyev.android.calculator.ActivityLauncher;
import org.solovyev.android.calculator.Engine; import org.solovyev.android.calculator.Engine;
import org.solovyev.android.calculator.Preferences; import org.solovyev.android.calculator.Preferences;
@ -38,14 +31,20 @@ import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.feedback.FeedbackReporter; import org.solovyev.android.calculator.feedback.FeedbackReporter;
import org.solovyev.android.calculator.language.Language; import org.solovyev.android.calculator.language.Language;
import org.solovyev.android.calculator.language.Languages; import org.solovyev.android.calculator.language.Languages;
import org.solovyev.android.checkout.BillingRequests;
import org.solovyev.android.checkout.Checkout;
import org.solovyev.android.checkout.ProductTypes;
import org.solovyev.android.checkout.RequestListener;
import org.solovyev.android.prefs.StringPreference; import org.solovyev.android.prefs.StringPreference;
import org.solovyev.android.wizard.Wizards; import org.solovyev.android.wizard.Wizards;
import org.solovyev.common.text.CharacterMapper; import org.solovyev.common.text.CharacterMapper;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import jscl.AngleUnit;
import jscl.JsclMathEngine;
import jscl.NumeralBase;
public class PreferencesFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener { public class PreferencesFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
@Nonnull @Nonnull
@ -100,7 +99,9 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Sha
} }
} }
/** @noinspection deprecation*/ /**
* @noinspection deprecation
*/
@Override @Override
public void onDisplayPreferenceDialog(@NonNull Preference preference) { public void onDisplayPreferenceDialog(@NonNull Preference preference) {
String fragmentTag = "fragment:" + preference.getKey(); String fragmentTag = "fragment:" + preference.getKey();
@ -125,7 +126,6 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Sha
prepareIntroduction(); prepareIntroduction();
prepareReportBug(); prepareReportBug();
prepareAbout(); prepareAbout();
prepareSupportProject();
prepareMode(); prepareMode();
prepareAngles(); prepareAngles();
prepareRadix(); prepareRadix();
@ -140,26 +140,6 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Sha
prepareLanguagePreference(preference); prepareLanguagePreference(preference);
prepareThemePreference(preference); prepareThemePreference(preference);
getCheckout().whenReady(new Checkout.EmptyListener() {
@Override
public void onReady(@Nonnull BillingRequests requests) {
requests.isPurchased(ProductTypes.IN_APP, "ad_free", new RequestListener<Boolean>() {
@Override
public void onSuccess(@Nonnull Boolean purchased) {
final Preference supportProject = findPreference("prefs.supportProject");
if (supportProject != null) {
supportProject.setEnabled(!purchased);
supportProject.setSelectable(!purchased);
}
}
@Override
public void onError(int i, @Nonnull Exception e) {
}
});
}
});
} }
private void prepareReportBug() { private void prepareReportBug() {
@ -171,20 +151,6 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Sha
return true; return true;
} }
}); });
}
private void prepareSupportProject() {
final Preference supportProject = findPreference("prefs.supportProject");
supportProject.setEnabled(false);
supportProject.setSelectable(false);
supportProject.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
startActivity(new Intent(getActivity(), PurchaseDialogActivity.class));
return true;
}
});
} }
private void prepareScreens() { private void prepareScreens() {
@ -379,11 +345,6 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Sha
}); });
} }
@Nonnull
private Checkout getCheckout() {
return ((PreferencesActivity) getActivity()).getCheckout();
}
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (Preferences.Onscreen.showAppIcon.isSameKey(key)) { if (Preferences.Onscreen.showAppIcon.isSameKey(key)) {

View File

@ -1,157 +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 static org.solovyev.android.calculator.App.cast;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.BaseDialogFragment;
import org.solovyev.android.calculator.R;
import org.solovyev.android.checkout.ActivityCheckout;
import org.solovyev.android.checkout.Billing;
import org.solovyev.android.checkout.BillingRequests;
import org.solovyev.android.checkout.Checkout;
import org.solovyev.android.checkout.ProductTypes;
import org.solovyev.android.checkout.Purchase;
import org.solovyev.android.checkout.RequestListener;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
public class PurchaseDialogActivity extends AppCompatActivity implements RequestListener<Purchase> {
@Inject
Billing billing;
ActivityCheckout checkout;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
cast(getApplication()).getComponent().inject(this);
if (savedInstanceState == null) {
App.showDialog(new PurchaseDialogFragment(), PurchaseDialogFragment.FRAGMENT_TAG, getSupportFragmentManager());
}
checkout = Checkout.forActivity(this, billing);
checkout.start();
checkout.createPurchaseFlow(this);
}
private void purchase() {
checkout.whenReady(new Checkout.EmptyListener() {
@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();
}
public void onDialogClosed() {
final Fragment fragment = getSupportFragmentManager().findFragmentByTag(PurchaseDialogFragment.FRAGMENT_TAG);
if (fragment == null) {
// activity is closing
return;
}
finish();
}
@Override
public void onSuccess(@Nonnull Purchase result) {
finish();
}
@Override
public void onError(int response, @Nonnull Exception e) {
finish();
}
public static class PurchaseDialogFragment extends BaseDialogFragment {
public static final String FRAGMENT_TAG = "purchase-dialog";
@Nullable
private PurchaseDialogActivity activity;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.activity = (PurchaseDialogActivity) activity;
}
@Override
protected void onPrepareDialog(@NonNull AlertDialog.Builder builder) {
super.onPrepareDialog(builder);
builder.setTitle(R.string.cpp_purchase_title);
builder.setMessage(R.string.cpp_purchase_text);
builder.setPositiveButton(R.string.cpp_continue, null);
}
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
if (activity != null) {
activity.purchase();
}
break;
default:
super.onClick(dialog, which);
break;
}
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (activity != null) {
activity.onDialogClosed();
activity = null;
}
}
}
}

View File

@ -1,39 +0,0 @@
package org.solovyev.android.checkout;
import androidx.annotation.NonNull;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* App-wide {@link Checkout} which counts how many times it has been started.
*/
@Singleton
public class CppCheckout extends Checkout {
private int started = 0;
@Inject
public CppCheckout(@NonNull Billing billing) {
super(null, billing);
}
@Override
public void stop() {
Check.isMainThread();
Check.isTrue(started > 0, "Must be started first");
started--;
if (started == 0) {
super.stop();
}
started = Math.max(0, started);
}
@Override
public void start(Listener listener) {
Check.isMainThread();
started++;
if (started == 1) {
super.start(listener);
}
}
}

View File

@ -24,13 +24,7 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="screen-main"> android:key="screen-main">
<Preference
android:defaultValue="false"
android:key="prefs.supportProject"
android:summary="@string/c_calc_ad_free_summary"
android:title="@string/c_calc_ad_free_title" />
<PreferenceCategory <PreferenceCategory
android:key="category-basic" android:key="category-basic"
android:title="@string/cpp_prefs_basic"> android:title="@string/cpp_prefs_basic">