kz.tanikin.inapppurchase2.SkusFragment.java Source code

Java tutorial

Introduction

Here is the source code for kz.tanikin.inapppurchase2.SkusFragment.java

Source

/*
 * Copyright 2014 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 kz.tanikin.inapppurchase2;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import org.solovyev.android.checkout.ActivityCheckout;
import org.solovyev.android.checkout.BillingRequests;
import org.solovyev.android.checkout.Checkout;
import org.solovyev.android.checkout.Inventory;
import org.solovyev.android.checkout.Purchase;
import org.solovyev.android.checkout.RequestListener;
import org.solovyev.android.checkout.ResponseCodes;
import org.solovyev.android.checkout.Sku;

import java.util.Comparator;

import static android.view.animation.AnimationUtils.loadAnimation;
import static org.solovyev.android.checkout.ProductTypes.IN_APP;

public class SkusFragment extends Fragment {

    protected ActivityCheckout checkout;
    private boolean listShown;
    protected ListView listView;
    protected ProgressBar progressBar;
    protected TextView emptyView;
    protected TextView titleView;
    protected Inventory inventory;
    private ArrayAdapter<SkuUi> adapter;
    String tag = "SkusFragment";

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        checkout = ((MainActivity) activity).getCheckout();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        inventory = checkout.loadInventory();
        for (Inventory.Product product : inventory.getProducts()) {
            Log.i(tag, product.getPurchases() + " produ");
        }
        checkout.createPurchaseFlow(new PurchaseListener());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.fragment_list, container, false);
        titleView = (TextView) view.findViewById(R.id.list_title);
        listView = (ListView) view.findViewById(android.R.id.list);
        progressBar = (ProgressBar) view.findViewById(android.R.id.progress);
        emptyView = (TextView) view.findViewById(android.R.id.empty);
        adapter = new SkusAdapter(inflater.getContext());
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new OnSkuClickListener());
        titleView.setText(R.string.items_for_purchase);
        emptyView.setText(R.string.skus_empty);
        Log.i(tag, adapter.getCount() + "");
        return view;
    }

    public void setListShown(boolean shown, boolean animate) {
        if (listShown == shown) {
            return;
        }
        listShown = shown;
        if (shown) {
            final View view = listView.getCount() > 0 ? listView : emptyView;
            if (animate) {
                progressBar.startAnimation(loadAnimation(getActivity(), android.R.anim.fade_out));
                view.startAnimation(loadAnimation(getActivity(), android.R.anim.fade_in));
            }
            progressBar.setVisibility(View.GONE);
            view.setVisibility(View.VISIBLE);
        } else {
            final View view = listView.getVisibility() == View.VISIBLE ? listView : emptyView;
            if (animate) {
                progressBar.startAnimation(loadAnimation(getActivity(), android.R.anim.fade_in));
                view.startAnimation(loadAnimation(getActivity(), android.R.anim.fade_out));
            }
            progressBar.setVisibility(View.VISIBLE);
            view.setVisibility(View.INVISIBLE);
        }
    }

    public void setListShown(boolean shown) {
        setListShown(shown, true);
    }

    public void setListShownNoAnimation(boolean shown) {
        setListShown(shown, false);
    }

    @Override
    public void onDestroy() {
        checkout.destroyPurchaseFlow();
        super.onDestroy();
    }

    private class PurchaseListener extends BaseRequestListener<Purchase> {
        @Override
        public void onSuccess(Purchase purchase) {
            onPurchased();
        }

        private void onPurchased() {
            // let's update purchase information in local inventory
            inventory.load().whenLoaded(new InventoryLoadedListener());
            Toast.makeText(getActivity(), R.string.msg_thank_you_for_purchase, Toast.LENGTH_SHORT).show();
            Log.i(tag, getString(R.string.msg_thank_you_for_purchase));
        }

        @Override
        public void onError(int response, Exception e) {
            // it is possible that our data is not synchronized with data on Google Play => need to handle some errors
            if (response == ResponseCodes.ITEM_ALREADY_OWNED) {
                onPurchased();
            } else {
                super.onError(response, e);
            }
        }
    }

    private class OnSkuClickListener implements AdapterView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            final SkuUi sku = adapter.getItem(position);
            purchase(sku);
        }
    }

    private void purchase(final SkuUi skuUi) {
        if (!skuUi.isPurchased()) {
            purchase(skuUi.sku);
        } else {
            consume(skuUi.token, new ConsumeListener());
        }
    }

    private void consume(final String token, final RequestListener<Object> onConsumed) {
        checkout.whenReady(new Checkout.ListenerAdapter() {
            @Override
            public void onReady(BillingRequests requests) {
                requests.consume(token, onConsumed);
            }
        });
    }

    private void purchase(final Sku sku) {
        checkout.whenReady(new Checkout.ListenerAdapter() {
            @Override
            public void onReady(BillingRequests requests) {
                requests.purchase(sku, null, checkout.getPurchaseFlow());
            }
        });
    }

    private static class SkuComparator implements Comparator<SkuUi> {
        @Override
        public int compare(SkuUi l, SkuUi r) {
            return l.sku.title.compareTo(r.sku.title);
        }
    }

    private class InventoryLoadedListener implements Inventory.Listener {
        @Override
        public void onLoaded(Inventory.Products products) {
            final Inventory.Product product = products.get(IN_APP);
            adapter.setNotifyOnChange(false);
            adapter.clear();
            if (product.supported) {
                for (Sku sku : product.getSkus()) {
                    final Purchase purchase = product.getPurchaseInState(sku, Purchase.State.PURCHASED);
                    adapter.add(SkuUi.create(sku, purchase != null ? purchase.token : null));
                }
                adapter.sort(new SkuComparator());
            } else {
                emptyView.setText(R.string.billing_not_supported);
            }
            adapter.notifyDataSetChanged();
            setListShown(true);
        }
    }

    private abstract class BaseRequestListener<R> implements RequestListener<R> {

        @Override
        public void onError(int response, Exception e) {
            // todo serso: add alert dialog or console
        }
    }

    private class ConsumeListener extends BaseRequestListener<Object> {
        @Override
        public void onSuccess(Object result) {
            onConsumed();
        }

        private void onConsumed() {
            inventory.load().whenLoaded(new InventoryLoadedListener());
            Toast.makeText(getActivity(), R.string.msg_item_consumed, Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onError(int response, Exception e) {
            // it is possible that our data is not synchronized with data on Google Play => need to handle some errors
            if (response == ResponseCodes.ITEM_NOT_OWNED) {
                onConsumed();
            } else {
                super.onError(response, e);
            }
        }
    }
}