From 761abc013f24f253a13d607ee310b8261c1a2ed1 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 5 Jan 2021 17:26:21 +0100 Subject: [PATCH 1/5] Allow donation through Google --- .gitignore | 1 + app/build.gradle | 19 +- .../fedilab/fedilabtube/DonationActivity.java | 165 ++++++++++++++++++ .../drawable/DonationButtonAdapter.java | 80 +++++++++ .../drawable/DonationHistoryAdapter.java | 80 +++++++++ .../fragment/DonationsFragment.java | 80 +++++++++ .../fragment/MyDonationsFragment.java | 84 +++++++++ .../res/layout/activity_donation.xml | 60 +++++++ .../res/layout/drawer_donation.xml | 23 +++ .../res/layout/fragment_donations.xml | 59 +++++++ .../res/layout/fragment_my_donations.xml | 59 +++++++ app/src/google_full/AndroidManifest.xml | 7 +- .../app/fedilab/fedilabtube/MainActivity.java | 7 + .../drawable/ic_baseline_attach_money_24.xml | 10 ++ app/src/main/res/menu/main_menu.xml | 6 + app/src/main/res/values/strings.xml | 6 + .../fedilab/fedilabtube/DonationActivity.java | 20 +++ 17 files changed, 756 insertions(+), 10 deletions(-) create mode 100644 app/src/google_donation/java/app/fedilab/fedilabtube/DonationActivity.java create mode 100644 app/src/google_donation/java/app/fedilab/fedilabtube/drawable/DonationButtonAdapter.java create mode 100644 app/src/google_donation/java/app/fedilab/fedilabtube/drawable/DonationHistoryAdapter.java create mode 100644 app/src/google_donation/java/app/fedilab/fedilabtube/fragment/DonationsFragment.java create mode 100644 app/src/google_donation/java/app/fedilab/fedilabtube/fragment/MyDonationsFragment.java create mode 100644 app/src/google_donation/res/layout/activity_donation.xml create mode 100644 app/src/google_donation/res/layout/drawer_donation.xml create mode 100644 app/src/google_donation/res/layout/fragment_donations.xml create mode 100644 app/src/google_donation/res/layout/fragment_my_donations.xml create mode 100644 app/src/main/res/drawable/ic_baseline_attach_money_24.xml create mode 100644 app/src/no_google_donation/java/app/fedilab/fedilabtube/DonationActivity.java diff --git a/.gitignore b/.gitignore index 32cb1b4..0f4f918 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ /app/fdroid_full/release/ /app/google_full/ /app/google_acad/ +/app/src/google_donation/res/values/data.xml diff --git a/app/build.gradle b/app/build.gradle index 2a0cf72..6230546 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { minSdkVersion 21 targetSdkVersion 30 - versionCode 34 - versionName "1.11.0" + versionCode 35 + versionName "1.11.1-test" multiDexEnabled true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -117,27 +117,27 @@ android { sourceSets { fdroid_peertube_apps_educ { res.srcDirs = ['src/main/res', 'src/acad/res'] - java.srcDirs = ['src/main/java', 'src/acad/java'] + java.srcDirs = ['src/main/java', 'src/acad/java', 'src/no_google_donation/java'] } google_peertube_apps_educ { res.srcDirs = ['src/main/res', 'src/acad/res'] - java.srcDirs = ['src/main/java', 'src/acad/java'] + java.srcDirs = ['src/main/java', 'src/acad/java', 'src/no_google_donation/java'] } fdroid_full { res.srcDirs = ['src/main/res', 'src/full/res'] - java.srcDirs = ['src/main/java', 'src/full/java'] + java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java'] } google_full { - res.srcDirs = ['src/main/res', 'src/full/res'] - java.srcDirs = ['src/main/java', 'src/full/java'] + res.srcDirs = ['src/main/res', 'src/full/res', 'src/google_donation/res'] + java.srcDirs = ['src/main/java', 'src/full/java', 'src/google_donation/java'] } queermotion { res.srcDirs = ['src/main/res', 'src/queermotion/res'] - java.srcDirs = ['src/main/java', 'src/full/java'] + java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java'] } bittube { res.srcDirs = ['src/main/res', 'src/bittube/res'] - java.srcDirs = ['src/main/java', 'src/full/java'] + java.srcDirs = ['src/main/java', 'src/full/java', 'src/no_google_donation/java'] } } } @@ -200,6 +200,7 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-core:2.12.0' implementation 'org.slf4j:slf4j-simple:1.7.30' + google_fullImplementation 'com.anjlab.android.iab.v3:library:1.0.44' fdroid_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2' google_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2' diff --git a/app/src/google_donation/java/app/fedilab/fedilabtube/DonationActivity.java b/app/src/google_donation/java/app/fedilab/fedilabtube/DonationActivity.java new file mode 100644 index 0000000..eb990cb --- /dev/null +++ b/app/src/google_donation/java/app/fedilab/fedilabtube/DonationActivity.java @@ -0,0 +1,165 @@ +package app.fedilab.fedilabtube; +/* Copyright 2021 Thomas Schneider + * + * This file is a part of TubeLab + * + * 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. + * + * TubeLab 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 TubeLab; if not, + * see . */ + +import android.content.Intent; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.anjlab.android.iab.v3.BillingProcessor; +import com.anjlab.android.iab.v3.TransactionDetails; +import com.google.android.material.tabs.TabLayout; + +import org.jetbrains.annotations.NotNull; + +import app.fedilab.fedilabtube.databinding.ActivityDonationBinding; +import app.fedilab.fedilabtube.fragment.DonationsFragment; +import app.fedilab.fedilabtube.fragment.MyDonationsFragment; + + +public class DonationActivity extends AppCompatActivity implements BillingProcessor.IBillingHandler { + + BillingProcessor bp; + DonationsFragment donationsFragment; + MyDonationsFragment myDonationsFragment; + private ActivityDonationBinding binding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityDonationBinding.inflate(getLayoutInflater()); + View view = binding.getRoot(); + setContentView(view); + bp = new BillingProcessor(this, getString(R.string.google_key), this); + bp.initialize(); + if (getSupportActionBar() != null) + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + donationsFragment = new DonationsFragment(); + myDonationsFragment = new MyDonationsFragment(); + + binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.donate))); + binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.my_donations))); + binding.viewpager.setOffscreenPageLimit(2); + + PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); + binding.viewpager.setAdapter(mPagerAdapter); + binding.viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + TabLayout.Tab tab = binding.tablayout.getTabAt(position); + if (tab != null) + tab.select(); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + binding.tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + @Override + public void onTabSelected(TabLayout.Tab tab) { + binding.viewpager.setCurrentItem(tab.getPosition()); + } + + @Override + public void onTabUnselected(TabLayout.Tab tab) { + + } + + @Override + public void onTabReselected(TabLayout.Tab tab) { + } + }); + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onProductPurchased(@NotNull String productId, TransactionDetails details) { + + } + + @Override + public void onPurchaseHistoryRestored() { + + } + + @Override + public void onBillingError(int errorCode, Throwable error) { + + } + + @Override + public void onBillingInitialized() { + donationsFragment.initialized(bp); + myDonationsFragment.initialized(bp); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (!bp.handleActivityResult(requestCode, resultCode, data)) { + super.onActivityResult(requestCode, resultCode, data); + } + } + + /** + * Pager adapter for the 2 fragments + */ + private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { + + ScreenSlidePagerAdapter(FragmentManager fm) { + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); + } + + @NotNull + @Override + public Fragment getItem(int position) { + if (position == 0) { + return donationsFragment; + } else { + return myDonationsFragment; + } + } + + + @Override + public int getCount() { + return 2; + } + } +} diff --git a/app/src/google_donation/java/app/fedilab/fedilabtube/drawable/DonationButtonAdapter.java b/app/src/google_donation/java/app/fedilab/fedilabtube/drawable/DonationButtonAdapter.java new file mode 100644 index 0000000..cafa466 --- /dev/null +++ b/app/src/google_donation/java/app/fedilab/fedilabtube/drawable/DonationButtonAdapter.java @@ -0,0 +1,80 @@ +package app.fedilab.fedilabtube.drawable; +/* Copyright 2021 Thomas Schneider + * + * This file is a part of TubeLab + * + * 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. + * + * TubeLab 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 TubeLab; if not, + * see . */ + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.anjlab.android.iab.v3.BillingProcessor; +import com.anjlab.android.iab.v3.SkuDetails; + +import java.util.List; +import java.util.Locale; + +import app.fedilab.fedilabtube.DonationActivity; +import app.fedilab.fedilabtube.databinding.DrawerDonationBinding; +import app.fedilab.fedilabtube.helper.Helper; + + +public class DonationButtonAdapter extends RecyclerView.Adapter { + + private final List items; + private final BillingProcessor billingProcessor; + private Context context; + + public DonationButtonAdapter(List items, BillingProcessor billingProcessor) { + this.items = items; + this.billingProcessor = billingProcessor; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + context = parent.getContext(); + DrawerDonationBinding itemBinding = DrawerDonationBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); + return new ViewHolder(itemBinding); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { + final ViewHolder holder = (ViewHolder) viewHolder; + String item = items.get(position); + String product_item = "tubelab_donation_" + item; + SkuDetails skuDetails = billingProcessor.getPurchaseListingDetails(product_item); + String currency = skuDetails.currency; + Double price = skuDetails.priceValue; + holder.binding.buttonDonation.setText(String.format(Locale.getDefault(), "%.2f %s", price, currency)); + holder.binding.buttonDonation.setOnClickListener(v -> billingProcessor.purchase((DonationActivity) context, product_item)); + } + + + @Override + public int getItemCount() { + return items.size(); + } + + static class ViewHolder extends RecyclerView.ViewHolder { + DrawerDonationBinding binding; + + ViewHolder(DrawerDonationBinding itemView) { + super(itemView.getRoot()); + binding = itemView; + } + } +} diff --git a/app/src/google_donation/java/app/fedilab/fedilabtube/drawable/DonationHistoryAdapter.java b/app/src/google_donation/java/app/fedilab/fedilabtube/drawable/DonationHistoryAdapter.java new file mode 100644 index 0000000..39a87f0 --- /dev/null +++ b/app/src/google_donation/java/app/fedilab/fedilabtube/drawable/DonationHistoryAdapter.java @@ -0,0 +1,80 @@ +package app.fedilab.fedilabtube.drawable; +/* Copyright 2021 Thomas Schneider + * + * This file is a part of TubeLab + * + * 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. + * + * TubeLab 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 TubeLab; if not, + * see . */ + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.anjlab.android.iab.v3.BillingProcessor; +import com.anjlab.android.iab.v3.SkuDetails; + +import java.util.List; +import java.util.Locale; + +import app.fedilab.fedilabtube.DonationActivity; +import app.fedilab.fedilabtube.databinding.DrawerDonationBinding; +import app.fedilab.fedilabtube.helper.Helper; + + +public class DonationHistoryAdapter extends RecyclerView.Adapter { + + private final List items; + private final BillingProcessor billingProcessor; + private Context context; + + public DonationHistoryAdapter(List items, BillingProcessor billingProcessor) { + this.items = items; + this.billingProcessor = billingProcessor; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + context = parent.getContext(); + DrawerDonationBinding itemBinding = DrawerDonationBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); + return new ViewHolder(itemBinding); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { + final ViewHolder holder = (ViewHolder) viewHolder; + SkuDetails item = items.get(position); + String product_item = "tubelab_donation_" + item; + SkuDetails skuDetails = billingProcessor.getPurchaseListingDetails(product_item); + String currency = skuDetails.currency; + Double price = skuDetails.priceValue; + holder.binding.buttonDonation.setText(String.format(Locale.getDefault(), "%.2f %s", price, currency)); + holder.binding.buttonDonation.setOnClickListener(v -> billingProcessor.purchase((DonationActivity) context, product_item)); + } + + + @Override + public int getItemCount() { + return items.size(); + } + + static class ViewHolder extends RecyclerView.ViewHolder { + DrawerDonationBinding binding; + + ViewHolder(DrawerDonationBinding itemView) { + super(itemView.getRoot()); + binding = itemView; + } + } +} diff --git a/app/src/google_donation/java/app/fedilab/fedilabtube/fragment/DonationsFragment.java b/app/src/google_donation/java/app/fedilab/fedilabtube/fragment/DonationsFragment.java new file mode 100644 index 0000000..b63ebb7 --- /dev/null +++ b/app/src/google_donation/java/app/fedilab/fedilabtube/fragment/DonationsFragment.java @@ -0,0 +1,80 @@ +package app.fedilab.fedilabtube.fragment; +/* Copyright 2021 Thomas Schneider + * + * This file is a part of TubeLab + * + * 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. + * + * TubeLab 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 TubeLab; if not, + * see . */ + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; + +import com.anjlab.android.iab.v3.BillingProcessor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import app.fedilab.fedilabtube.databinding.FragmentDonationsBinding; +import app.fedilab.fedilabtube.drawable.DonationButtonAdapter; + + +public class DonationsFragment extends Fragment { + + public static final String[] donations = {"1", "2", "5", "10"}; + private FragmentDonationsBinding binding; + private View rootView; + private Context context; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + binding = FragmentDonationsBinding.inflate(LayoutInflater.from(context)); + rootView = binding.getRoot(); + context = getContext(); + binding.loader.setVisibility(View.VISIBLE); + binding.lvProducts.setVisibility(View.GONE); + return rootView; + } + + public void initialized(BillingProcessor bp) { + binding.loader.setVisibility(View.GONE); + binding.lvProducts.setVisibility(View.VISIBLE); + List donationsList = new ArrayList<>(); + Collections.addAll(donationsList, donations); + DonationButtonAdapter donationButtonAdapter = new DonationButtonAdapter(donationsList, bp); + binding.lvProducts.setAdapter(donationButtonAdapter); + binding.lvProducts.setLayoutManager(new LinearLayoutManager(context)); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + rootView = null; + } + + @Override + public void onCreate(Bundle saveInstance) { + super.onCreate(saveInstance); + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + this.context = context; + } +} diff --git a/app/src/google_donation/java/app/fedilab/fedilabtube/fragment/MyDonationsFragment.java b/app/src/google_donation/java/app/fedilab/fedilabtube/fragment/MyDonationsFragment.java new file mode 100644 index 0000000..45e411a --- /dev/null +++ b/app/src/google_donation/java/app/fedilab/fedilabtube/fragment/MyDonationsFragment.java @@ -0,0 +1,84 @@ +package app.fedilab.fedilabtube.fragment; +/* Copyright 2021 Thomas Schneider + * + * This file is a part of TubeLab + * + * 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. + * + * TubeLab 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 TubeLab; if not, + * see . */ + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; + +import com.anjlab.android.iab.v3.BillingProcessor; +import com.anjlab.android.iab.v3.SkuDetails; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import app.fedilab.fedilabtube.databinding.FragmentMyDonationsBinding; +import app.fedilab.fedilabtube.drawable.DonationHistoryAdapter; + +import static app.fedilab.fedilabtube.fragment.DonationsFragment.donations; + + +public class MyDonationsFragment extends Fragment { + + private FragmentMyDonationsBinding binding; + private View rootView; + private Context context; + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + binding = FragmentMyDonationsBinding.inflate(LayoutInflater.from(context)); + rootView = binding.getRoot(); + context = getContext(); + binding.loader.setVisibility(View.VISIBLE); + binding.lvPurchases.setVisibility(View.GONE); + return rootView; + } + + public void initialized(BillingProcessor bp) { + binding.loader.setVisibility(View.GONE); + binding.lvPurchases.setVisibility(View.VISIBLE); + ArrayList donationsList = new ArrayList<>(); + Collections.addAll(donationsList, donations); + List skuDetailsList = bp.getPurchaseListingDetails(donationsList); + DonationHistoryAdapter donationHistoryAdapter = new DonationHistoryAdapter(skuDetailsList, bp); + binding.lvPurchases.setAdapter(donationHistoryAdapter); + binding.lvPurchases.setLayoutManager(new LinearLayoutManager(context)); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + rootView = null; + } + + @Override + public void onCreate(Bundle saveInstance) { + super.onCreate(saveInstance); + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + this.context = context; + } +} diff --git a/app/src/google_donation/res/layout/activity_donation.xml b/app/src/google_donation/res/layout/activity_donation.xml new file mode 100644 index 0000000..9c07a5a --- /dev/null +++ b/app/src/google_donation/res/layout/activity_donation.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/google_donation/res/layout/drawer_donation.xml b/app/src/google_donation/res/layout/drawer_donation.xml new file mode 100644 index 0000000..4f8fff0 --- /dev/null +++ b/app/src/google_donation/res/layout/drawer_donation.xml @@ -0,0 +1,23 @@ + + + +