Java tutorial
/* * Kontalk Android client * Copyright (C) 2017 Kontalk Devteam <devteam@kontalk.org> * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kontalk.ui; import java.util.Arrays; import org.kontalk.BuildConfig; import org.kontalk.R; import org.kontalk.billing.BillingResult; import org.kontalk.billing.BillingServiceManager; import org.kontalk.billing.IBillingService; import org.kontalk.billing.IInventory; import org.kontalk.billing.IProductDetails; import org.kontalk.billing.IPurchase; import org.kontalk.billing.OnBillingSetupFinishedListener; import org.kontalk.billing.OnConsumeFinishedListener; import org.kontalk.billing.OnPurchaseFinishedListener; import org.kontalk.billing.QueryInventoryFinishedListener; import org.kontalk.util.SystemUtils; import android.app.Activity; import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.text.ClipboardManager; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Toast; /** * Donation fragment. * @author Daniele Ricci * @author Andrea Cappelli */ public class DonationFragment extends Fragment implements OnClickListener { // for Google Play private IBillingService mBillingService; private static final int IAB_REQUEST_CODE = 10001; OnPurchaseFinishedListener mPurchaseFinishedListener = new OnPurchaseFinishedListener() { public void onPurchaseFinished(BillingResult result, IPurchase purchase) { if (mBillingService == null) return; if (result.isSuccess()) { // consume purchase in the background mBillingService.consumeAsync(purchase, mConsumeFinishedListener); } } }; OnConsumeFinishedListener mConsumeFinishedListener = new OnConsumeFinishedListener() { public void onConsumeFinished(IPurchase purchase, BillingResult result) { int msg; if (result.isSuccess()) msg = R.string.msg_iab_thankyou; else msg = R.string.msg_iab_thankyou_warning; Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG).show(); } }; private final class OnPreConsumeFinishedListener implements OnConsumeFinishedListener { private int mConsumedItems; private String[] mItems; public void onConsumeFinished(IPurchase purchase, BillingResult result) { mConsumedItems++; if (mConsumedItems >= mItems.length) { mConsumedItems = 0; showDonationSelector(mItems); } } public void setDonationItems(String[] items) { mItems = items; mConsumedItems = 0; } } OnPreConsumeFinishedListener mPreConsumeFinishedListener = new OnPreConsumeFinishedListener(); public IBillingService getBillingService() { return mBillingService; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.about_donation, container, false); View button = view.findViewById(R.id.donate_google); if (BillingServiceManager.isEnabled()) button.setOnClickListener(this); else button.setVisibility(View.GONE); view.findViewById(R.id.donate_paypal).setOnClickListener(this); view.findViewById(R.id.donate_bitcoin).setOnClickListener(this); view.findViewById(R.id.donate_flattr).setOnClickListener(this); return view; } public void onClick(View v) { switch (v.getId()) { case R.id.donate_google: donateGoogle(); break; case R.id.donate_paypal: donatePaypal(); break; case R.id.donate_bitcoin: donateBitcoin(); break; case R.id.donate_flattr: donateFlattr(); break; } } private void donateFlattr() { SystemUtils.openURL(getContext(), getString(R.string.flattr_url)); } private void donateBitcoin() { final String address = getString(R.string.bitcoin_address); Uri uri = Uri.parse("bitcoin:" + address); Intent intent = SystemUtils.externalIntent(Intent.ACTION_VIEW, Uri.parse(uri.toString())); Activity ctx = getActivity(); final PackageManager pm = ctx.getPackageManager(); if (pm.resolveActivity(intent, 0) != null) startActivity(intent); else new MaterialDialog.Builder(getActivity()).title(R.string.title_bitcoin_dialog) .content(getString(R.string.text_bitcoin_dialog, address)).positiveText(android.R.string.ok) .neutralText(R.string.copy_clipboard).onNeutral(new MaterialDialog.SingleButtonCallback() { @Override public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { ClipboardManager cpm = (ClipboardManager) getActivity() .getSystemService(Context.CLIPBOARD_SERVICE); cpm.setText(address); Toast.makeText(getActivity(), R.string.bitcoin_clipboard_copied, Toast.LENGTH_LONG) .show(); } }).show(); } private void donatePaypal() { // just start Paypal donate button URL SystemUtils.openURL(getContext(), getString(R.string.paypal_url)); } private void setupGoogle(final Dialog progress) { if (mBillingService == null) { mBillingService = BillingServiceManager.getInstance(getActivity()); mBillingService.enableDebugLogging(BuildConfig.DEBUG); mBillingService.startSetup(new OnBillingSetupFinishedListener() { public void onSetupFinished(BillingResult result) { if (!result.isSuccess()) { alert(getString(R.string.iab_error_setup, result.getResponse())); mBillingService = null; progress.dismiss(); return; } queryInventory(progress); } }); } else { queryInventory(progress); } } private void queryInventory(final Dialog progress) { final String[] iabItems = getResources().getStringArray(R.array.iab_items); QueryInventoryFinishedListener gotInventoryListener = new QueryInventoryFinishedListener() { public void onQueryInventoryFinished(BillingResult result, IInventory inventory) { if (mBillingService == null) return; // dismiss progress progress.dismiss(); if (result.isFailure()) { alert(getString(R.string.iab_error_query, result.getResponse())); } else { // prepare items for the dialog String[] dialogItems = new String[iabItems.length]; for (int i = 0; i < iabItems.length; i++) { IProductDetails sku = inventory.getSkuDetails(iabItems[i]); if (sku != null) { dialogItems[i] = sku.getDescription(); } else { dialogItems[i] = iabItems[i]; } } // setup pre-consume listener mPreConsumeFinishedListener.setDonationItems(dialogItems); int purchases = 0; // consume purchases just to be sure for (String item : iabItems) { IPurchase purchase = inventory.getPurchase(item); if (purchase != null) { purchases++; mBillingService.consumeAsync(purchase, mPreConsumeFinishedListener); } } // no purchases to be consumed, show donation now if (purchases == 0) showDonationSelector(dialogItems); } } }; if (mBillingService != null) mBillingService.queryInventoryAsync(true, Arrays.asList(iabItems), gotInventoryListener); } private void showDonationSelector(CharSequence[] dialogItems) { final String[] iabItems = getResources().getStringArray(R.array.iab_items); // show dialog with choices new MaterialDialog.Builder(getActivity()).items(dialogItems) .itemsCallback(new MaterialDialog.ListCallback() { @Override public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) { // start the purchase String itemId = iabItems[position]; mBillingService.launchPurchaseFlow(getActivity(), itemId, IAB_REQUEST_CODE, mPurchaseFinishedListener); } }).negativeText(android.R.string.cancel).show(); } private void donateGoogle() { // progress dialog Dialog dialog = new MaterialDialog.Builder(getActivity()).content(R.string.msg_connecting_iab) .cancelable(true).progress(true, 0).cancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // FIXME this doesn't seem to work in some cases if (mBillingService != null) { mBillingService.dispose(); mBillingService = null; } } }).show(); setupGoogle(dialog); } @Override public void onDestroy() { super.onDestroy(); if (mBillingService != null) { mBillingService.dispose(); mBillingService = null; } } private void alert(String message) { new MaterialDialog.Builder(getActivity()).content(message).positiveText(android.R.string.ok).show(); } }