me.henrytao.smoothappbarlayoutdemo.activity.BaseActivity.java Source code

Java tutorial

Introduction

Here is the source code for me.henrytao.smoothappbarlayoutdemo.activity.BaseActivity.java

Source

/*
 * Copyright 2015 "Henry Tao <hi@henrytao.me>"
 *
 * 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 me.henrytao.smoothappbarlayoutdemo.activity;

import com.android.vending.billing.IInAppBillingService;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.ServiceConnection;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import butterknife.Bind;
import butterknife.ButterKnife;
import me.henrytao.smoothappbarlayoutdemo.R;

/**
 * Created by henrytao on 10/11/15.
 */
public class BaseActivity extends AppCompatActivity {

    private static final String[] DONATE_ITEMS = { "donate_coffee", "donate_toast", "donate_pizza",
            "donate_dinner" };

    private static IInAppBillingService mBillingService;

    private static List<PurchaseItem> mPurchaseItems;

    private static ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBillingService = IInAppBillingService.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBillingService = null;
        }
    };

    private ProgressDialog mProgressDialog;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_google_play, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_donate:
            showDonateDialog();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1001) {
            int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
            String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
            String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
            if (resultCode == RESULT_OK) {
                new AlertDialog.Builder(BaseActivity.this).setMessage(getString(R.string.text_thanks_for_donate))
                        .setPositiveButton(R.string.close, null).show();
            } else {
                showDonateDialogErrorCallback(null);
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
        serviceIntent.setPackage("com.android.vending");
        bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mBillingService != null) {
            unbindService(mServiceConnection);
        }
        hideProgressDialog();
    }

    public void showDonateDialog() {
        if (mPurchaseItems == null) {
            showProgressDialog(getString(R.string.text_donate_progress_title),
                    getString(R.string.text_donate_progress_message));
        }
        requestItemsForPurchase(new AsyncCallback<List<PurchaseItem>>(this) {
            @Override
            public void onError(Throwable throwable) {
                if (getContext() instanceof BaseActivity && !((BaseActivity) getContext()).isFinishing()) {
                    BaseActivity context = (BaseActivity) getContext();
                    context.hideProgressDialog();
                    context.showDonateDialogErrorCallback(throwable);
                }
            }

            @Override
            public void onSuccess(List<PurchaseItem> data) {
                if (getContext() instanceof BaseActivity && !((BaseActivity) getContext()).isFinishing()) {
                    BaseActivity context = (BaseActivity) getContext();
                    context.hideProgressDialog();
                    context.showDonateDialogSuccessCallback(data);
                }
            }
        });
    }

    private void hideProgressDialog() {
        if (mProgressDialog != null) {
            mProgressDialog.dismiss();
            mProgressDialog = null;
        }
    }

    private void onDonate(PurchaseItem item) {
        if (item == null || !item.isValid() || mBillingService == null) {
            return;
        }
        try {
            Bundle buyIntentBundle = mBillingService.getBuyIntent(3, getPackageName(), item.getId(), "inapp", "");
            PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
            startIntentSenderForResult(pendingIntent.getIntentSender(), 1001, new Intent(), 0, 0, 0);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (IntentSender.SendIntentException e) {
            e.printStackTrace();
        }
    }

    private void requestItemsForPurchase(final AsyncCallback<List<PurchaseItem>> callback) {
        if (mPurchaseItems != null && mPurchaseItems.size() > 0) {
            if (callback != null) {
                callback.onSuccess(mPurchaseItems);
            }
            return;
        }
        new AsyncTask<IInAppBillingService, Void, AsyncResult<List<PurchaseItem>>>() {

            @Override
            protected AsyncResult<List<PurchaseItem>> doInBackground(IInAppBillingService... params) {
                List<PurchaseItem> result = new ArrayList<>();
                Throwable exception = null;
                IInAppBillingService billingService = params[0];

                if (billingService == null) {
                    exception = new Exception("Unknow");
                } else {
                    ArrayList<String> skuList = new ArrayList<>(Arrays.asList(DONATE_ITEMS));
                    Bundle querySkus = new Bundle();
                    querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
                    try {
                        Bundle skuDetails = billingService.getSkuDetails(3, getPackageName(), "inapp", querySkus);
                        int response = skuDetails.getInt("RESPONSE_CODE");
                        if (response == 0) {
                            ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
                            PurchaseItem purchaseItem;
                            for (String item : responseList) {
                                purchaseItem = new PurchaseItem(new JSONObject(item));
                                if (purchaseItem.isValid()) {
                                    result.add(purchaseItem);
                                }
                            }
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                        exception = e;
                    } catch (JSONException e) {
                        e.printStackTrace();
                        exception = e;
                    }
                }
                return new AsyncResult<>(result, exception);
            }

            @Override
            protected void onPostExecute(AsyncResult<List<PurchaseItem>> result) {
                if (!isFinishing() && callback != null) {
                    Throwable error = result.getError();
                    if (error == null && (result.getResult() == null || result.getResult().size() == 0)) {
                        error = new Exception("Unknow");
                    }
                    if (error != null) {
                        callback.onError(error);
                    } else {
                        mPurchaseItems = result.getResult();
                        Collections.sort(mPurchaseItems, new Comparator<PurchaseItem>() {
                            @Override
                            public int compare(PurchaseItem lhs, PurchaseItem rhs) {
                                return (int) ((lhs.getPriceAmountMicros() - rhs.getPriceAmountMicros()) / 1000);
                            }
                        });
                        callback.onSuccess(mPurchaseItems);
                    }
                }
            }
        }.execute(mBillingService);
    }

    private void showDonateDialogErrorCallback(Throwable throwable) {
        new AlertDialog.Builder(BaseActivity.this).setMessage(getString(R.string.text_donate_error))
                .setPositiveButton(R.string.close, null).show();
    }

    private void showDonateDialogSuccessCallback(final List<PurchaseItem> data) {
        PurchaseAdapter adapter = new PurchaseAdapter(this, data);
        AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle(R.string.text_donate)
                .setCancelable(false).setAdapter(adapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        onDonate(data.get(which));
                    }
                }).setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        new AlertDialog.Builder(BaseActivity.this).setMessage(getString(R.string.text_help_offer))
                                .setPositiveButton(R.string.close, null).show();
                    }
                });
        builder.show();
    }

    private void showProgressDialog(CharSequence title, CharSequence message) {
        if (isFinishing()) {
            return;
        }
        hideProgressDialog();
        mProgressDialog = ProgressDialog.show(this, title, message);
    }

    public static abstract class AsyncCallback<T> {

        public abstract void onError(Throwable throwable);

        public abstract void onSuccess(T data);

        private WeakReference<Context> mContextWeakReference;

        public AsyncCallback(Context context) {
            mContextWeakReference = new WeakReference<>(context);
        }

        public Context getContext() {
            return mContextWeakReference.get();
        }
    }

    public static class AsyncResult<T> {

        private Throwable mError;

        private T mResult;

        public AsyncResult(T result, Throwable error) {
            mResult = result;
            mError = error;
        }

        public Throwable getError() {
            return mError;
        }

        public T getResult() {
            return mResult;
        }
    }

    public static class PurchaseAdapter extends ArrayAdapter<PurchaseItem> {

        @Bind(R.id.description)
        TextView vDescription;

        @Bind(R.id.title)
        TextView vTitle;

        private List<PurchaseItem> mItems;

        public PurchaseAdapter(Context context, List<PurchaseItem> items) {
            super(context, 0);
            mItems = items == null ? new ArrayList<PurchaseItem>() : items;
        }

        @Override
        public int getCount() {
            return mItems.size();
        }

        @Override
        public PurchaseItem getItem(int position) {
            return mItems.get(position);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_purchase, parent,
                        false);
            }
            ButterKnife.bind(this, convertView);
            vTitle.setText(getItem(position).getDescription());
            vDescription.setText(getItem(position).getPrice());
            return convertView;
        }
    }

    public static class PurchaseItem {

        private String mDescription;

        private String mId;

        private String mPrice;

        private long mPriceAmountMicros;

        private String mPriceCurrencyCode;

        private String mTitle;

        private String mType;

        public PurchaseItem(JSONObject item) {
            try {
                if (item != null) {
                    mId = item.getString("productId");
                    mType = item.getString("type");
                    mTitle = item.getString("title");
                    mDescription = item.getString("description");
                    mPrice = item.getString("price");
                    mPriceAmountMicros = item.getLong("price_amount_micros");
                    mPriceCurrencyCode = item.getString("price_currency_code");
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        public String getDescription() {
            return mDescription;
        }

        public String getId() {
            return mId;
        }

        public String getPrice() {
            return mPrice;
        }

        public long getPriceAmountMicros() {
            return mPriceAmountMicros;
        }

        public String getPriceCurrencyCode() {
            return mPriceCurrencyCode;
        }

        public String getTitle() {
            return mTitle;
        }

        public String getType() {
            return mType;
        }

        public boolean isValid() {
            return !TextUtils.isEmpty(mId);
        }
    }
}