package au.com.newint.newinternationalist;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.os.AsyncTask;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
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.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.ecommerce.Product;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import au.com.newint.newinternationalist.util.IabException;
import au.com.newint.newinternationalist.util.IabHelper;
import au.com.newint.newinternationalist.util.IabResult;
import au.com.newint.newinternationalist.util.Inventory;
import au.com.newint.newinternationalist.util.Purchase;
import au.com.newint.newinternationalist.util.SkuDetails;
public class SubscribeActivity extends ActionBarActivity {
static IabHelper mHelper;
static ArrayList<SkuDetails> mProducts;
static int mPositionTapped;
static ArrayList<Issue> mIssueList;
static IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_subscribe);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new SubscribeActivityFragment())
.commit();
}
mProducts = new ArrayList<>();
}
@Override
public void onResume() {
super.onResume();
// Send Google Analytics if the user allows it
Helpers.sendGoogleAnalytics(getResources().getString(R.string.title_activity_subscribe));
}
@Override
public void onDestroy() {
super.onDestroy();
// Dispose of the in-app helper
if (mHelper != null) mHelper.dispose();
mHelper = null;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("Subscribe", "onActivityResult(" + requestCode + "," + resultCode + "," + data);
// 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("Subscribe", "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.menu_subscribe, 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.
switch (item.getItemId()) {
case R.id.action_settings:
// Helpers.debugLog("Menu", "Settings pressed.");
// Settings intent
Intent settingsIntent = new Intent(this, SettingsActivity.class);
startActivity(settingsIntent);
return true;
case R.id.about:
// Helpers.debugLog("Menu", "About pressed.");
// About intent
Intent aboutIntent = new Intent(this, AboutActivity.class);
startActivity(aboutIntent);
return true;
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Subscribe fragment
*/
public static class SubscribeActivityFragment extends Fragment {
public SubscribeActivityFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_subscribe, container, false);
// Setup view
final RecyclerView recList = (RecyclerView) rootView.findViewById(R.id.subscribe_card_list);
recList.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(rootView.getContext());
llm.setOrientation(LinearLayoutManager.VERTICAL);
recList.setLayoutManager(llm);
final SubscribeAdapter adapter = new SubscribeAdapter();
recList.setAdapter(adapter);
// Setup in-app billing
mHelper = Helpers.setupIabHelper(getActivity().getApplicationContext());
if (!Helpers.emulator) {
// Only startSetup if not running in an emulator
// Get inventory from Google Play
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d("Subscribe", "Problem setting up In-app Billing: " + result);
}
// Hooray, IAB is fully set up!
Helpers.debugLog("Subscribe", "In-app billing setup result: " + result);
// Consume the test purchase..
if (BuildConfig.DEBUG) {
try {
Inventory inventory = mHelper.queryInventory(false, null);
Purchase purchase = inventory.getPurchase("android.test.purchased");
if (purchase != null) {
mHelper.consumeAsync(inventory.getPurchase("android.test.purchased"), null);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Ask Google Play for a products list on a background thread
final ArrayList<String> additionalSkuList = new ArrayList<String>();
additionalSkuList.add(Helpers.TWELVE_MONTH_SUBSCRIPTION_ID);
additionalSkuList.add(Helpers.ONE_MONTH_SUBSCRIPTION_ID);
mIssueList = Publisher.INSTANCE.getIssuesFromFilesystem();
for (Issue issue : mIssueList) {
additionalSkuList.add(Helpers.singleIssuePurchaseID(issue.getNumber()));
}
final ProgressDialog progress = new ProgressDialog(getActivity());
progress.setTitle(getResources().getString(R.string.subscribe_loading_progress_title));
progress.setMessage(getResources().getString(R.string.subscribe_loading_progress_message));
progress.show();
new AsyncTask<Void, Integer, Void>() {
@Override
protected Void doInBackground(Void... params) {
int partitionSize = Helpers.GOOGLE_PLAY_MAX_SKU_LIST_SIZE;
for (int i = 0; i < additionalSkuList.size(); i+=partitionSize) {
final int loopNumber = i;
final List<String> partition = additionalSkuList.subList(i, Math.min(i + partitionSize, additionalSkuList.size()));
try {
Inventory inventory = mHelper.queryInventory(true, partition);
// Check subscription inventory
Helpers.debugLog("Subscribe", "Inventory (" + loopNumber + "): " + inventory);
// Loop through products and add them to mProducts
for (String sku : partition) {
SkuDetails product = inventory.getSkuDetails(sku);
if (product != null) {
mProducts.add(product);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(Void nothing) {
super.onPostExecute(nothing);
// Update adapter
adapter.notifyDataSetChanged();
progress.dismiss();
}
}.execute();
mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, final Purchase purchase)
{
if (result.isFailure()) {
if (result.getResponse() == 7) {
// Already purchased!
Activity alertActivity = getActivity();
if (alertActivity != null) {
AlertDialog.Builder builder = new AlertDialog.Builder(alertActivity);
builder.setMessage(R.string.subscribe_already_purchased_message).setTitle(R.string.subscribe_already_purchased_title);
builder.setPositiveButton(R.string.subscribe_already_purchased_read_issue_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User clicked Read this issue button
Intent issueIntent = new Intent(rootView.getContext(), TableOfContentsActivity.class);
int issueNumber = Integer.parseInt(mProducts.get(mPositionTapped).getSku().replaceAll("[\\D]", ""));
Issue issueForIntent = null;
for (Issue issue : mIssueList) {
if (issue.getNumber() == issueNumber) {
issueForIntent = issue;
}
}
if (issueForIntent != null) {
issueIntent.putExtra("issue", issueForIntent);
startActivity(issueIntent);
}
}
});
builder.setNegativeButton(R.string.subscribe_already_purchased_cancel_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
} else {
Log.d("Subscribe", "Error purchasing: " + result);
}
return;
} else if (result.getResponse() == IabHelper.IABHELPER_USER_CANCELLED) {
// User cancelled the purchase, so ignore, move on
Helpers.debugLog("Subscribe", "User cancelled purchase.");
return;
} else if (purchase.getSku().equals(Helpers.TWELVE_MONTH_SUBSCRIPTION_ID)) {
// Update subscription status.
Helpers.debugLog("Subscribe", "Purchase succeeded: " + purchase.getItemType());
// Send analytics event if user permits
SkuDetails productPurchased = null;
productPurchased = getProductForPurchase(purchase);
Helpers.sendGoogleAnalyticsEvent("Google Play", "Subscription", purchase.getItemType(), productPurchased.getPrice());
Helpers.sendGoogleAdwordsConversion(productPurchased);
} else if (purchase.getSku().equals(Helpers.ONE_MONTH_SUBSCRIPTION_ID)) {
// Update subscription status.
Helpers.debugLog("Subscribe", "Purchase succeeded: " + purchase.getItemType());
// Send analytics event if user permits
SkuDetails productPurchased = null;
productPurchased = getProductForPurchase(purchase);
Helpers.sendGoogleAnalyticsEvent("Google Play", "Subscription", purchase.getItemType(), productPurchased.getPrice());
Helpers.sendGoogleAdwordsConversion(productPurchased);
} else {
// Handle individual purchases
Helpers.debugLog("Subscribe", "Individual purchase: " + purchase.getItemType());
adapter.notifyDataSetChanged();
// Send analytics event if user permits
SkuDetails productPurchased = null;
productPurchased = getProductForPurchase(purchase);
Helpers.sendGoogleAnalyticsEvent("Google Play", "Purchase", purchase.getItemType(), productPurchased.getPrice());
Helpers.sendGoogleAdwordsConversion(productPurchased);
}
}
};
}
});
}
return rootView;
}
// Adapter for CardView
public class SubscribeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_PRODUCT = 1;
private static final int TYPE_FOOTER = 2;
public SubscribeAdapter() {
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = null;
if (viewType == 0) {
// Header
itemView = LayoutInflater.
from(parent.getContext()).
inflate(R.layout.fragment_subscribe_header_view, parent, false);
return new SubscribeHeaderViewHolder(itemView);
} else if (viewType == 1) {
// Product
itemView = LayoutInflater.
from(parent.getContext()).
inflate(R.layout.fragment_subscribe_card_view, parent, false);
return new SubscribeViewHolder(itemView);
} else if (viewType == 2) {
// Footer
itemView = LayoutInflater.
from(parent.getContext()).
inflate(R.layout.fragment_subscribe_footer_view, parent, false);
return new SubscribeFooterViewHolder(itemView);
} else {
// Uh oh... didn't match view type.
return null;
}
}
@Override
public int getItemCount() {
// return mProducts.size() + 3; // 3 = 2 x header + footer
// Don't need the footer in the end...
// return mProducts.size() + 1; // Plus footer
return mProducts.size();
}
@Override
public int getItemViewType(int position) {
if (isPositionHeader(position)) {
return TYPE_HEADER;
} else if (isPositionFooter(position)) {
return TYPE_FOOTER;
}
return TYPE_PRODUCT;
}
private boolean isPositionHeader(int position) {
// return position == 0;
return false;
}
private boolean isPositionFooter(int position) {
// Don't need the restore footer in the end...
// return position == mProducts.size();
return false;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// Recycling the viewHolder for all but the purchases
holder.setIsRecyclable(false);
if (holder instanceof SubscribeHeaderViewHolder) {
// Header
// TODO: Do we need headers separating the Subscriptions from the single issues?
((SubscribeHeaderViewHolder) holder).productType.setText("TODO: Set type text.");
} else if (holder instanceof SubscribeViewHolder) {
// In-app product
SkuDetails product = mProducts.get(position);
String productSku = product.getSku();
final SubscribeViewHolder viewHolder = ((SubscribeViewHolder) holder);
// Setup product image
if (productSku.contains("single")) {
// It's a single magazine purchase, so load the cover
int productID = Integer.parseInt(productSku.replaceAll("\\D+",""));
int issueListPosition = 0;
boolean issueFound = false;
for (int i = 0; i < mIssueList.size(); i++) {
if (mIssueList.get(i).getNumber() == productID) {
issueListPosition = i;
issueFound = true;
}
}
if (issueFound) {
Issue issue = mIssueList.get(issueListPosition);
int coverWidth = Math.round(getResources().getDimension(R.dimen.subscribe_cover_width));
issue.getCoverCacheStreamFactoryForSize(coverWidth).preload(new CacheStreamFactory.CachePreloadCallback() {
@Override
public void onLoad(byte[] payload) {
if (payload != null && payload.length > 0) {
final Bitmap coverBitmap = Helpers.bitmapDecode(payload);
Animation fadeOutAnimation = new AlphaAnimation(1.0f, 0.0f);
final Animation fadeInAnimation = new AlphaAnimation(0.0f, 1.0f);
fadeOutAnimation.setDuration(100);
fadeInAnimation.setDuration(200);
fadeOutAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
viewHolder.productImage.setImageBitmap(coverBitmap);
viewHolder.productImage.startAnimation(fadeInAnimation);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
viewHolder.productImage.startAnimation(fadeOutAnimation);
}
}
@Override
public void onLoadBackground(byte[] payload) {
}
});
}
}
// Setup product
viewHolder.productTitle.setText(product.getTitle().replace(" (New Internationalist magazine)", ""));
viewHolder.productDescription.setText(product.getDescription());
viewHolder.productPrice.setText(product.getPrice());
// If product has been purchased
try {
Inventory inventory = mHelper.queryInventory(false, null);
Purchase purchase = inventory.getPurchase(product.getSku());
// NOTE: Purchase is double checked via Rails when actually trying to get the article body
if (purchase != null) {
CardView cardView = (CardView) viewHolder.itemView.findViewById(R.id.subscribe_card_view);
cardView.setCardBackgroundColor(getResources().getColor(R.color.material_deep_teal_200));
viewHolder.productPrice.setText(product.getPrice() + " (Purchased!)");
viewHolder.setIsRecyclable(false);
}
} catch (IabException e) {
e.printStackTrace();
}
} else if (holder instanceof SubscribeFooterViewHolder) {
// Footer
// TODO: Make sure that purchases are restored each time the inventory & purchases are checked
((SubscribeFooterViewHolder) holder).restorePurchases.setText("TODO: Restore purchases!");
}
}
public class SubscribeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ImageView productImage;
public TextView productTitle;
public TextView productDescription;
public TextView productPrice;
public SubscribeViewHolder(View itemView) {
super(itemView);
productImage = (ImageView) itemView.findViewById(R.id.subscribe_product_image);
productTitle = (TextView) itemView.findViewById(R.id.subscribe_product_title);
productDescription = (TextView) itemView.findViewById(R.id.subscribe_product_description);
productPrice = (TextView) itemView.findViewById(R.id.subscribe_product_price);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// Purchase product!
Helpers.debugLog("Subscribe", "Product tapped at position: " + getPosition());
mPositionTapped = getPosition();
// TODO: Generate developerPayload in helper, now just returns an empty string
String developerPayload = Helpers.getDeveloperPayload();
// For testing:
// mHelper.launchPurchaseFlow(getActivity(), "android.test.purchased", Helpers.GOOGLE_PLAY_REQUEST_CODE, mPurchaseFinishedListener, developerPayload);
// For real:
mHelper.launchPurchaseFlow(getActivity(), mProducts.get(getPosition()).getSku(), Helpers.GOOGLE_PLAY_REQUEST_CODE, mPurchaseFinishedListener, developerPayload);
}
}
public class SubscribeHeaderViewHolder extends RecyclerView.ViewHolder {
public TextView productType;
public SubscribeHeaderViewHolder(View itemView) {
super(itemView);
productType = (TextView) itemView.findViewById(R.id.subscribe_header_product_type);
}
}
public class SubscribeFooterViewHolder extends RecyclerView.ViewHolder {
public Button restorePurchases;
public SubscribeFooterViewHolder(View itemView) {
super(itemView);
restorePurchases = (Button) itemView.findViewById(R.id.subscribe_footer_restore);
}
}
}
}
private static SkuDetails getProductForPurchase(Purchase purchase) {
SkuDetails productPurchased = null;
if (mProducts != null && mProducts.size() > 0) {
for (SkuDetails product : mProducts) {
if (product.getSku().equals(purchase.getSku())) {
productPurchased = product;
}
}
}
return productPurchased;
}
}