ads + billing + fix for MiOne devices' tabs

This commit is contained in:
Sergey Solovyev 2012-01-05 19:09:33 +04:00
parent d26a084e50
commit 0d6656f52c
8 changed files with 163 additions and 30 deletions

View File

@ -144,7 +144,7 @@
так как приложение стало довольно большим и сложным.\n так как приложение стало довольно большим и сложным.\n
Если вы хотите поддержать проект и избавиться от рекламы, вы можете купить специальную опцию в настройках приложения,\n Если вы хотите поддержать проект и избавиться от рекламы, вы можете купить специальную опцию в настройках приложения,\n
если вы не хотите или не можете этого сделать - вы всё равно можете отблагодарить автора программы по почте: se.solovyev@gmail.com, высоко оценить приложение на андроид.маркете\n если вы не хотите или не можете этого сделать - вы всё равно можете отблагодарить автора программы по почте: se.solovyev@gmail.com, высоко оценить приложение на андроид.маркете\n
или помочь в переводе приложения на свой роной язык. или помочь в переводе приложения на свой родной язык.
</string> </string>
</resources> </resources>

View File

@ -10,6 +10,8 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -35,33 +37,51 @@ public final class AndroidUtils {
} }
public static void centerAndWrapTabsFor(@NotNull TabHost tabHost) { public static void centerAndWrapTabsFor(@NotNull TabHost tabHost) {
int tabCount = tabHost.getTabWidget().getTabCount(); if (allowCenterAndWrappingTabs()) {
for (int i = 0; i < tabCount; i++) { int tabCount = tabHost.getTabWidget().getTabCount();
final View view = tabHost.getTabWidget().getChildTabViewAt(i); for (int i = 0; i < tabCount; i++) {
if (view != null) { final View view = tabHost.getTabWidget().getChildTabViewAt(i);
if (view.getLayoutParams().height > 0) { if (view != null) {
// reduce height of the tab if (view.getLayoutParams().height > 0) {
view.getLayoutParams().height *= 0.8; // reduce height of the tab
} view.getLayoutParams().height *= 0.8;
}
// get title text view // get title text view
final View textView = view.findViewById(android.R.id.title); final View textView = view.findViewById(android.R.id.title);
if (textView instanceof TextView) { if (textView instanceof TextView) {
// just in case check the type // just in case check the type
// center text // center text
((TextView) textView).setGravity(Gravity.CENTER); ((TextView) textView).setGravity(Gravity.CENTER);
// wrap text // wrap text
((TextView) textView).setSingleLine(false); ((TextView) textView).setSingleLine(false);
// explicitly set layout parameters // explicitly set layout parameters
textView.getLayoutParams().height = ViewGroup.LayoutParams.FILL_PARENT; textView.getLayoutParams().height = ViewGroup.LayoutParams.FILL_PARENT;
textView.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; textView.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
}
} }
} }
} }
} }
private static boolean allowCenterAndWrappingTabs() {
boolean result = true;
String deviceModel = Build.MODEL;
if (deviceModel != null) {
deviceModel = deviceModel.toUpperCase();
if (deviceModel.contains("M1") || deviceModel.contains("MIONE") || deviceModel.contains("MI-ONE")) {
// Xiaomi Phone MiOne => do not allow to center and wrap tabs
result = false;
Log.i(AndroidUtils.class.getName(), "Device model doesn't support center and wrap of tabs: " + Build.MODEL);
}
}
return result;
}
public static void addTab(@NotNull Context context, public static void addTab(@NotNull Context context,
@NotNull TabHost tabHost, @NotNull TabHost tabHost,
@NotNull String tabId, @NotNull String tabId,

View File

@ -26,6 +26,8 @@ import android.widget.TextView;
import com.google.ads.AdView; import com.google.ads.AdView;
import jscl.AngleUnit; import jscl.AngleUnit;
import jscl.NumeralBase; import jscl.NumeralBase;
import net.robotmedia.billing.BillingController;
import net.robotmedia.billing.IBillingObserver;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils; import org.solovyev.android.AndroidUtils;
@ -53,6 +55,9 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
private static final int HVGA_WIDTH_PIXELS = 320; private static final int HVGA_WIDTH_PIXELS = 320;
@Nullable
private IBillingObserver billingObserver;
public static class Preferences { public static class Preferences {
@NotNull @NotNull
private static final String APP_VERSION_P_KEY = "application.version"; private static final String APP_VERSION_P_KEY = "application.version";
@ -377,6 +382,10 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
private synchronized void firstTimeInit(@NotNull SharedPreferences preferences) { private synchronized void firstTimeInit(@NotNull SharedPreferences preferences) {
if (!initialized) { if (!initialized) {
billingObserver = new CalculatorBillingObserver(this);
BillingController.registerObserver(billingObserver);
BillingController.checkBillingSupported(this);
final int savedVersion = Preferences.appVersion.getPreference(preferences); final int savedVersion = Preferences.appVersion.getPreference(preferences);
final int appVersion = AndroidUtils.getAppVersionCode(this, CalculatorActivity.class.getPackage().getName()); final int appVersion = AndroidUtils.getAppVersionCode(this, CalculatorActivity.class.getPackage().getName());
@ -627,6 +636,11 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
if ( adView != null ) { if ( adView != null ) {
adView.destroy(); adView.destroy();
} }
if (billingObserver != null) {
BillingController.unregisterObserver(billingObserver);
}
super.onDestroy(); super.onDestroy();
} }

View File

@ -36,20 +36,24 @@ public class CalculatorApplication extends android.app.Application {
return instance; return instance;
} }
public static boolean isAdFreeApprox(@NotNull Context context) { private static boolean isAdFreePurchased(@NotNull Context context) {
return BillingController.isPurchased(context.getApplicationContext(), AD_FREE_PRODUCT_ID); return BillingController.isPurchased(context.getApplicationContext(), AD_FREE_PRODUCT_ID);
} }
private static boolean transactionsRestored = false;
public static boolean isAdFree(@NotNull Context context) { public static boolean isAdFree(@NotNull Context context) {
// check if user already bought this product // check if user already bought this product
boolean purchased = isAdFreeApprox(context); boolean purchased = isAdFreePurchased(context);
if (!purchased) { if (!purchased && !transactionsRestored) {
// we must to restore all transactions done by user to guarantee that product was purchased or not // we must to restore all transactions done by user to guarantee that product was purchased or not
BillingController.restoreTransactions(context); BillingController.restoreTransactions(context);
transactionsRestored = true;
// todo serso: may be call net.robotmedia.billing.BillingController.restoreTransactions() always before first check and get rid of second check // todo serso: may be call net.robotmedia.billing.BillingController.restoreTransactions() always before first check and get rid of second check
// check the billing one more time // check the billing one more time
purchased = isAdFreeApprox(context); purchased = isAdFreePurchased(context);
} }
return purchased; return purchased;
} }
@ -62,9 +66,8 @@ public class CalculatorApplication extends android.app.Application {
@Nullable @Nullable
public static AdView inflateAd(@NotNull Activity activity, int parentViewId) { public static AdView inflateAd(@NotNull Activity activity, int parentViewId) {
AdView result = null; AdView result = null;
if ( !isAdFreeApprox(activity) ) { if ( !isAdFree(activity) ) {
Log.d(activity.getClass().getName(), "Application is not ad free - inflating ad!"); Log.d(activity.getClass().getName(), "Application is not ad free - inflating ad!");
//final List<String> keywords = Arrays.asList("math", "mathematics", "finance", "physics", "dynamics");
final List<String> keywords = Collections.emptyList(); final List<String> keywords = Collections.emptyList();
result = AndroidUtils.createAndInflateAdView(activity, ADMOB_USER_ID, parentViewId, keywords); result = AndroidUtils.createAndInflateAdView(activity, ADMOB_USER_ID, parentViewId, keywords);
} else { } else {
@ -78,6 +81,7 @@ public class CalculatorApplication extends android.app.Application {
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
//BillingController.setDebug(true);
BillingController.setConfiguration(new BillingController.IConfiguration() { BillingController.setConfiguration(new BillingController.IConfiguration() {
@Override @Override
@ -90,7 +94,5 @@ public class CalculatorApplication extends android.app.Application {
return CalculatorSecurity.getPK(); return CalculatorSecurity.getPK();
} }
}); });
BillingController.checkBillingSupported(this);
} }
} }

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2009-2012. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import android.app.Activity;
import net.robotmedia.billing.BillingRequest;
import net.robotmedia.billing.helper.AbstractBillingObserver;
import net.robotmedia.billing.model.Transaction;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 1/5/12
* Time: 4:51 PM
*/
public class CalculatorBillingObserver extends AbstractBillingObserver {
public CalculatorBillingObserver(@NotNull Activity activity) {
super(activity);
}
@Override
public void onBillingChecked(boolean supported) {
// do nothing
}
@Override
public void onPurchaseStateChanged(String itemId, Transaction.PurchaseState state) {
// do nothing
}
@Override
public void onRequestPurchaseResponse(String itemId, BillingRequest.ResponseCode response) {
// do nothing
}
}

View File

@ -6,11 +6,16 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.util.Log;
import net.robotmedia.billing.BillingController; import net.robotmedia.billing.BillingController;
import net.robotmedia.billing.BillingRequest;
import net.robotmedia.billing.IBillingObserver;
import net.robotmedia.billing.model.Transaction;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.view.widgets.VibratorContainer; import org.solovyev.android.view.widgets.VibratorContainer;
@ -19,7 +24,7 @@ import org.solovyev.android.view.widgets.VibratorContainer;
* Date: 7/16/11 * Date: 7/16/11
* Time: 6:37 PM * Time: 6:37 PM
*/ */
public class CalculatorPreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { public class CalculatorPreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener, IBillingObserver {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -35,10 +40,13 @@ public class CalculatorPreferencesActivity extends PreferenceActivity implements
// check billing availability // check billing availability
if (BillingController.checkBillingSupported(CalculatorPreferencesActivity.this) != BillingController.BillingStatus.SUPPORTED) { if (BillingController.checkBillingSupported(CalculatorPreferencesActivity.this) != BillingController.BillingStatus.SUPPORTED) {
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported - warn user!");
// warn about not supported billing // warn about not supported billing
new AlertDialog.Builder(CalculatorPreferencesActivity.this).setTitle(R.string.c_error).setMessage(R.string.c_billing_error).create().show(); new AlertDialog.Builder(CalculatorPreferencesActivity.this).setTitle(R.string.c_error).setMessage(R.string.c_billing_error).create().show();
} else { } else {
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is supported - continue!");
if (!CalculatorApplication.isAdFree(CalculatorPreferencesActivity.this)) { if (!CalculatorApplication.isAdFree(CalculatorPreferencesActivity.this)) {
Log.d(CalculatorPreferencesActivity.class.getName(), "Item not purchased - try to purchase!");
// not purchased => show purchase window for user // not purchased => show purchase window for user
BillingController.requestPurchase(CalculatorPreferencesActivity.this, CalculatorApplication.AD_FREE_PRODUCT_ID, true); BillingController.requestPurchase(CalculatorPreferencesActivity.this, CalculatorApplication.AD_FREE_PRODUCT_ID, true);
} }
@ -51,18 +59,67 @@ public class CalculatorPreferencesActivity extends PreferenceActivity implements
addFreePreference.setEnabled(false); addFreePreference.setEnabled(false);
} }
BillingController.registerObserver(this);
final SharedPreferences preferences = getPreferenceManager().getSharedPreferences(); final SharedPreferences preferences = getPreferenceManager().getSharedPreferences();
preferences.registerOnSharedPreferenceChangeListener(this); preferences.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(preferences, CalculatorEngine.Preferences.roundResult.getKey()); onSharedPreferenceChanged(preferences, CalculatorEngine.Preferences.roundResult.getKey());
onSharedPreferenceChanged(preferences, VibratorContainer.HAPTIC_FEEDBACK_P_KEY); onSharedPreferenceChanged(preferences, VibratorContainer.HAPTIC_FEEDBACK_P_KEY);
} }
@Override
protected void onDestroy() {
BillingController.unregisterObserver(this);
super.onDestroy();
}
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (CalculatorEngine.Preferences.roundResult.getKey().equals(key)) { if (CalculatorEngine.Preferences.roundResult.getKey().equals(key)) {
findPreference(CalculatorEngine.Preferences.roundResult.getKey()).setEnabled(preferences.getBoolean(key, CalculatorEngine.Preferences.roundResult.getDefaultValue())); findPreference(CalculatorEngine.Preferences.precision.getKey()).setEnabled(preferences.getBoolean(key, CalculatorEngine.Preferences.roundResult.getDefaultValue()));
} else if (VibratorContainer.HAPTIC_FEEDBACK_P_KEY.equals(key)) { } else if (VibratorContainer.HAPTIC_FEEDBACK_P_KEY.equals(key)) {
findPreference(VibratorContainer.HAPTIC_FEEDBACK_DURATION_P_KEY).setEnabled(preferences.getBoolean(key, VibratorContainer.HAPTIC_FEEDBACK_DEFAULT)); findPreference(VibratorContainer.HAPTIC_FEEDBACK_DURATION_P_KEY).setEnabled(preferences.getBoolean(key, VibratorContainer.HAPTIC_FEEDBACK_DEFAULT));
} }
} }
@Override
public void onBillingChecked(boolean supported) {
// do nothing
}
@Override
public void onPurchaseIntent(String itemId, PendingIntent purchaseIntent) {
// do nothing
}
@Override
public void onPurchaseStateChanged(String itemId, Transaction.PurchaseState state) {
if (CalculatorApplication.AD_FREE_PRODUCT_ID.equals(itemId)) {
final Preference addFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
if (addFreePreference != null) {
switch (state) {
case PURCHASED:
addFreePreference.setEnabled(false);
break;
case CANCELLED:
addFreePreference.setEnabled(true);
break;
case REFUNDED:
addFreePreference.setEnabled(true);
break;
}
} else {
}
}
}
@Override
public void onRequestPurchaseResponse(String itemId, BillingRequest.ResponseCode response) {
// do nothing
}
@Override
public void onTransactionsRestored() {
// do nothing
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB