/*
* Copyright 2015 Daniel Dittmar
*
* 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 dan.dit.whatsthat.system.store;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.FrameLayout;
import com.anjlab.android.iab.v3.BillingProcessor;
import com.anjlab.android.iab.v3.Constants;
import com.anjlab.android.iab.v3.TransactionDetails;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import dan.dit.whatsthat.R;
import dan.dit.whatsthat.achievement.AchievementManager;
import dan.dit.whatsthat.preferences.User;
import dan.dit.whatsthat.riddle.RiddleInitializer;
import dan.dit.whatsthat.system.InitActivity;
import dan.dit.whatsthat.testsubject.TestSubject;
/**
* For billing library see: https://github.com/anjlab/android-inapp-billing-v3
* Created by daniel on 10.06.15.
*/
public class StoreActivity extends FragmentActivity implements BillingProcessor.IBillingHandler, BillingCallback {
public static final String GOOGLE_PUBKEY =
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn6hUO5Q7mp16xluE7lRKlXJeFAvNktJjEHaDeD624XNcVcfRs7F5+LooYu2fCgHPnX74MyYG6p3ZDXDsHfaubenWVodBYHUo9ZfLWk3bo/kfd3vdFDiRVErQflZgQ88MUwcHl0caexKVYAP/LOCkniJvZKQ7+B/bj93us1nyqbaJOV+iBNveZwoODAgYembc0pOCJ4YgjY+J112o1+cgKZkuDunVLSapokhIWriVDp3XHU6b/1WyegzAA3cSiJV6y6rxy6kMFwGIc1e15oZPV8S7ae6GbZMc/GkeYGzxY1Qi1i4edk0K44rNjm0gfGd1Tz5WYD19cdECY9PXn4WD6QIDAQAB";
private static final int CATEGORY_MENU = 0;
private static final int CATEGORY_SHOP = 1; // start categories' index at 1
private static final int CATEGORY_ACHIEVEMENTS = 2;
private static final int CATEGORY_WORKSHOP = 3;
private static final int CATEGORY_ABOUT = 4;
private static final int CATEGORY_DONATE = 5;
private static final int CATEGORY_CREDITS = 6;
private static final int CATEGORIES_COUNT = 7;
private static final int[] mCategoryLayoutId = new int[] {0, R.layout.shop_base, R.layout.achievements_base, R.layout.workshop_base, R.layout.about_base, R.layout.donations_base, R.layout.credits_base};
private static final String KEY_CURR_CATEGORY = "dan.dit.whatsthat.STORE_MENU_CURR_CATEGORY";
private boolean mStateOpening;
private StoreContainer mVisibleCategory;
private int mCurrCategory;
private StoreContainer[] mCategory;
private ViewGroup mCategoriesContainer;
private Button mCategoryTitleBackButton;
private ViewGroup mMenuContainer;
private List<Button> mMenuButtons;
private FrameLayout mCategoryTitleContainer;
private BillingProcessor mBP;
private boolean mBillingAvailable;
private Map<String, ProductPurchasedCallback> mProductPurchaseCallbacks = new HashMap<>();
private boolean mBillingInitialized;
private String mLastStartedPurchaseProductId;
private void showMenu() {
mCurrCategory = CATEGORY_MENU;
closeVisibleCategory(false);
mCategoriesContainer.setVisibility(View.GONE);
for (Button view : mMenuButtons) {
view.clearAnimation();
}
mMenuContainer.setVisibility(View.VISIBLE);
}
private void closeVisibleCategory(boolean pausedOnly) {
if (mVisibleCategory != null) {
mVisibleCategory.stop(this, pausedOnly);
mVisibleCategory = null;
}
}
private void prepareCategory() {
if (mCurrCategory == CATEGORY_MENU) {
Log.e("HomeStuff", "Trying to prepare menu category!");
return;
}
closeVisibleCategory(false);
mMenuContainer.setVisibility(View.GONE);
mCategoriesContainer.removeAllViews();
mCategoriesContainer.setVisibility(View.VISIBLE);
Animation categoryFadeIn = AnimationUtils.loadAnimation(this, R.anim.store_category_fadein);
mCategoriesContainer.startAnimation(categoryFadeIn);
StoreContainer container = mCategory[mCurrCategory];
if (container == null && mCategoryLayoutId[mCurrCategory] != 0) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
container = (StoreContainer) inflater.inflate(mCategoryLayoutId[mCurrCategory], null).findViewById(R.id.store_container);
mCategory[mCurrCategory] = container;
}
if (container != null) {
mCategoriesContainer.addView(container.getView());
mCategoryTitleBackButton.setText(mMenuButtons.get(mCurrCategory - 1).getText());
container.refresh(this, mCategoryTitleContainer);
mVisibleCategory = container;
}
}
private void showCurrCategory() {
if (mCurrCategory == CATEGORY_MENU) {
mCategoryTitleBackButton.setText(R.string.store_category_menu);
mCategoryTitleBackButton.setCompoundDrawablesWithIntrinsicBounds(TestSubject.getInstance().getImageResId(), 0, R.drawable.shop_title_back, 0);
showMenu();
} else {
mCategoryTitleBackButton.setCompoundDrawablesWithIntrinsicBounds(R.drawable.alien_menu_title_back, 0, 0, R.drawable.shop_title_back_bottom);
prepareCategory();
}
mStateOpening = false;
}
private boolean onMenuButtonClicked(View view) {
if (!mStateOpening) {
mStateOpening = true;
List<Button> otherMenuButtons = new ArrayList<>(mMenuButtons);
//noinspection SuspiciousMethodCalls
otherMenuButtons.remove(view);
Animation animFadeOut = AnimationUtils.loadAnimation(this, R.anim.store_button_fadeout);
Animation animScale = new ScaleAnimation(1.f, mCategoryTitleBackButton.getWidth() / (float) view.getWidth(), 1.f, mCategoryTitleBackButton.getHeight() / (float) view.getHeight(),
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
Animation animMoveTop = new TranslateAnimation(Animation.ABSOLUTE, 0.f, Animation.ABSOLUTE, 0.f, Animation.ABSOLUTE, 0.f, Animation.ABSOLUTE, -view.getY() - mCategoryTitleBackButton.getHeight());
AnimationSet onPress = new AnimationSet(true);
onPress.setDuration(400L);
onPress.addAnimation(animScale);
onPress.addAnimation(animMoveTop);
onPress.setFillAfter(true);
for (Button btn : otherMenuButtons) {
btn.startAnimation(animFadeOut);
}
view.startAnimation(onPress);
onPress.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
showCurrCategory();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
return true;
}
return false;
}
@Override
public void onBackPressed() {
if (mCurrCategory != CATEGORY_MENU) {
mCurrCategory = CATEGORY_MENU;
showCurrCategory();
} else {
super.onBackPressed();
overridePendingTransition(R.anim.riddles_enter, R.anim.store_exit);
}
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
outState.putInt(KEY_CURR_CATEGORY, mCurrCategory);
super.onSaveInstanceState(outState);
}
@Override
public void onPause() {
super.onPause();
if (mCategoriesContainer != null) {
closeVisibleCategory(true);
mCategoriesContainer.removeAllViews();
}
}
@Override
public void onResume() {
super.onResume();
if (mVisibleCategory == null) {
showCurrCategory();
}
}
@Override
public void onStop() {
super.onStop();
AchievementManager.commit();
}
@Override
public void onDestroy() {
if (mBP != null) {
mBP.release();
}
if (mProductPurchaseCallbacks != null) {
mProductPurchaseCallbacks.clear();
}
super.onDestroy();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (RiddleInitializer.INSTANCE.isNotInitialized() || !TestSubject.isInitialized()) {
// app got killed by android and is trying to reconstruct this activity when not initialized
Log.d("HomeStuff", "App killed and trying to reconstruct non initialized into StoreActivity.");
Intent reInit = new Intent(getApplicationContext(), InitActivity.class);
reInit.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(reInit);
finish();
return;
}
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.store_activity);
mBP = new BillingProcessor(this, GOOGLE_PUBKEY, this);
mBillingAvailable = BillingProcessor.isIabServiceAvailable(this);
mCategoriesContainer = (ViewGroup) findViewById(R.id.category_container);
mCategoryTitleContainer = (FrameLayout) findViewById(R.id.category_title_container);
mCategoryTitleBackButton = (Button) findViewById(R.id.btn_category_title_back);
mCategoryTitleBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onBackPressed();
}
});
mMenuContainer = (ViewGroup) findViewById(R.id.menu_buttons);
mMenuButtons = new ArrayList<>(CATEGORIES_COUNT);
Button shopButton = (Button) findViewById(R.id.btn_shop);
shopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (onMenuButtonClicked(view)) {
mCurrCategory = CATEGORY_SHOP;
}
}
});
Button achievementsButton = (Button) findViewById(R.id.btn_achievements);
achievementsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (onMenuButtonClicked(view)) {
mCurrCategory = CATEGORY_ACHIEVEMENTS;
}
}
});
Button workshopButton = (Button) findViewById(R.id.btn_workshop);
if (User.getInstance().hasPermission(User.PERMISSION_WORKSHOP)) {
workshopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (onMenuButtonClicked(view)) {
mCurrCategory = CATEGORY_WORKSHOP;
}
}
});
} else {
workshopButton.setVisibility(View.GONE);
}
Button aboutButton = (Button) findViewById(R.id.btn_about);
aboutButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (onMenuButtonClicked(view)) {
mCurrCategory = CATEGORY_ABOUT;
}
}
});
Button donateButton = (Button) findViewById(R.id.btn_donate);
donateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (onMenuButtonClicked(view)) {
mCurrCategory = CATEGORY_DONATE;
}
}
});
Button creditsButton = (Button) findViewById(R.id.btn_credits);
creditsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (onMenuButtonClicked(view)) {
mCurrCategory = CATEGORY_CREDITS;
}
}
});
mMenuButtons.add(shopButton);
mMenuButtons.add(achievementsButton);
mMenuButtons.add(workshopButton);
mMenuButtons.add(aboutButton);
mMenuButtons.add(donateButton);
mMenuButtons.add(creditsButton);
mCategory = new StoreContainer[CATEGORIES_COUNT];
mCurrCategory = CATEGORY_MENU;
if (savedInstanceState != null) {
mCurrCategory = savedInstanceState.getInt(KEY_CURR_CATEGORY, CATEGORY_MENU);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (!mBP.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
Log.d("HomeStuff", "Store activity got activity result!" + resultCode);
/**
* Needed for Google Play In-app Billing. It uses startIntentSenderForResult(). The result is not propagated to
* the Fragment like in startActivityForResult(). Thus we need to propagate manually to our Fragment.
*/
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(DonationsView.FRAGMENT_TAG);
if (fragment != null) {
fragment.onActivityResult(requestCode, resultCode, data);
}
if (resultCode == Activity.RESULT_OK && mCurrCategory == CATEGORY_WORKSHOP) {
// this downcast is not nice but as long as only workshop needs activity results we are fine
((WorkshopView) mCategory[CATEGORY_WORKSHOP]).onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onProductPurchased(String productId, TransactionDetails details) {
/*
* Called when requested PRODUCT ID was successfully purchased
*/
ProductPurchasedCallback callback = mProductPurchaseCallbacks.get(productId);
if (callback != null) {
Log.d("Billing", "Product purchased " + productId + " details: " + details);
int result = callback.onProductPurchased(productId, details);
mProductPurchaseCallbacks.remove(productId);
if (result == ProductPurchasedCallback.CONSUME_PRODUCT) {
if (!mBP.consumePurchase(productId)) {
Log.e("Billing", "Product consuming failed!");
}
}
}
}
@Override
public void onPurchaseHistoryRestored() {
Log.d("Billing", "Purchase history restored.");
/*
* Called when purchase history was restored and the list of all owned PRODUCT ID's
* was loaded from Google Play,
* see: mBP.loadOwnedPurchasesFromGoogle();
*/
}
@Override
public void onBillingError(int errorCode, Throwable error) {
if (errorCode == Constants.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED) {
Log.e("Billing", "Billing error, already owned item: " + error + ", is it " +
mLastStartedPurchaseProductId + "?");
} else {
Log.e("Billing", "Billing error: " + errorCode + " error: " + error);
}
}
@Override
public void onBillingInitialized() {
Log.d("Billing", "Billing initialized.");
/*
* Called when BillingProcessor was initialized and it's ready to purchase
*/
mBillingInitialized = true;
}
@Override
public boolean isAvailable() {
return mBP != null && mBillingAvailable && mBillingInitialized;
}
@Override
public void purchase(String productId, ProductPurchasedCallback callback) {
if (isAvailable() && callback != null) {
if (mBP.purchase(this, productId)) {
Log.d("Billing", "Purchased successfully started " + productId);
mLastStartedPurchaseProductId = productId;
mProductPurchaseCallbacks.put(productId, callback);
}
}
}
public interface ProductPurchasedCallback {
int DO_NOTHING = 0;
int CONSUME_PRODUCT = 1;
int onProductPurchased(String productId, TransactionDetails details);
}
}