mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-18 19:59:00 +00:00
start working on subscriptions
This commit is contained in:
parent
8d1ab45424
commit
b575287f85
21 changed files with 639 additions and 60 deletions
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="15"
|
||||
android:targetSdkVersion="24" />
|
||||
android:targetSdkVersion="25" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ dependencies {
|
|||
compile 'org.greenrobot:eventbus:3.0.0'
|
||||
|
||||
// IAP Handling / Verification
|
||||
compile 'org.solovyev.android:checkout:0.7.5@aar'
|
||||
compile 'org.solovyev.android:checkout:0.9.1@aar'
|
||||
|
||||
//Facebook
|
||||
compile('com.facebook.android:facebook-android-sdk:4.17.0') {
|
||||
|
|
@ -130,10 +130,10 @@ dependencies {
|
|||
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
|
||||
|
||||
//Push Notifications
|
||||
compile 'com.google.firebase:firebase-core:9.4.0'
|
||||
compile 'com.google.firebase:firebase-messaging:9.4.0'
|
||||
compile 'com.google.firebase:firebase-core:10.0.1'
|
||||
compile 'com.google.firebase:firebase-messaging:10.0.1'
|
||||
|
||||
compile 'com.google.android.gms:play-services-auth:9.4.0'
|
||||
compile 'com.google.android.gms:play-services-auth:10.0.1'
|
||||
|
||||
compile(project(':seeds-sdk')) {
|
||||
exclude group: 'com.google.android.gms'
|
||||
|
|
|
|||
19
Habitica/res/drawable/subscription_selected.xml
Normal file
19
Habitica/res/drawable/subscription_selected.xml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<corners android:radius="@dimen/daily_checkbox_corner_radius"/>
|
||||
<solid android:color="@color/brand_100" />
|
||||
<stroke android:color="@color/transparent" android:width="5dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<corners android:radius="@dimen/daily_checkbox_corner_radius"/>
|
||||
<stroke android:color="@color/brand_100" android:width="1dp" />
|
||||
<size android:height="16dp" android:width="16dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
8
Habitica/res/drawable/subscription_unselected.xml
Normal file
8
Habitica/res/drawable/subscription_unselected.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||
<corners android:radius="@dimen/daily_checkbox_corner_radius"/>
|
||||
<stroke android:color="@color/brand_100" android:width="1dp" />
|
||||
<size android:height="16dp" android:width="16dp" />
|
||||
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
|
||||
</shape>
|
||||
|
|
@ -19,10 +19,11 @@
|
|||
android:elevation="0dp"
|
||||
tools:context=".ui.activities.MainActivity">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fragment_container"
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/white"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
|
|
@ -63,7 +64,7 @@
|
|||
</android.support.design.widget.CollapsingToolbarLayout>
|
||||
|
||||
<android.support.design.widget.TabLayout
|
||||
android:id="@+id/detail_tabs"
|
||||
android:id="@+id/tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="54dp"
|
||||
android:layout_gravity="bottom"
|
||||
|
|
@ -78,8 +79,7 @@
|
|||
app:layout_collapseMode="pin"
|
||||
app:tabGravity="fill"
|
||||
app:tabIndicatorColor="@android:color/white"
|
||||
app:tabMode="fixed"
|
||||
android:visibility="gone"/>
|
||||
app:tabMode="fixed" />
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
|
|
|||
122
Habitica/res/layout/fragment_subscription.xml
Normal file
122
Habitica/res/layout/fragment_subscription.xml
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbarSize="3dp"
|
||||
android:scrollbarThumbVertical="@color/md_grey_500"
|
||||
android:scrollbars="vertical">
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:text="@string/subscribe.title"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/best_10"
|
||||
android:drawableTop="@drawable/ic_header_heart"
|
||||
android:textSize="14sp"
|
||||
android:lineSpacingExtra="4dp" />
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<com.habitrpg.android.habitica.ui.SubscriptionOptionView
|
||||
android:id="@+id/subscription1month"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:recurringText="month" />
|
||||
<com.habitrpg.android.habitica.ui.SubscriptionOptionView
|
||||
android:id="@+id/subscription3month"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:recurringText="3 months" />
|
||||
<com.habitrpg.android.habitica.ui.SubscriptionOptionView
|
||||
android:id="@+id/subscription6month"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:recurringText="6 months" />
|
||||
<com.habitrpg.android.habitica.ui.SubscriptionOptionView
|
||||
android:id="@+id/subscription12month"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:recurringText="12 months" />
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:text="@string/subscribe"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/subscribeButton"
|
||||
android:textColor="@color/white"
|
||||
android:background="@drawable/rounded_purple_square"
|
||||
android:enabled="false" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/subscribe.subtitle"
|
||||
android:gravity="center"
|
||||
android:textStyle="normal|bold"
|
||||
android:textColor="@color/brand_100"
|
||||
android:textSize="16sp"
|
||||
android:lineSpacingExtra="4dp"
|
||||
android:layout_marginTop="23dp"
|
||||
android:layout_marginBottom="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:text="@string/subscribe.listitem1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/GemPurchaseListItem"
|
||||
/>
|
||||
<TextView
|
||||
android:text="@string/subscribe.listitem1.description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/GemPurchaseListItemDescription" />
|
||||
|
||||
<TextView
|
||||
android:text="@string/subscribe.listitem2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/GemPurchaseListItem"
|
||||
/>
|
||||
<TextView
|
||||
android:text="@string/subscribe.listitem2.description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/GemPurchaseListItemDescription" />
|
||||
|
||||
<TextView
|
||||
android:text="@string/subscribe.listitem3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/GemPurchaseListItem"
|
||||
/>
|
||||
<TextView
|
||||
android:text="@string/subscribe.listitem3.description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/GemPurchaseListItemDescription" />
|
||||
|
||||
<TextView
|
||||
android:text="@string/subscribe.listitem4"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/GemPurchaseListItem"
|
||||
/>
|
||||
<TextView
|
||||
android:text="@string/subscribe.listitem4.description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/GemPurchaseListItemDescription" />
|
||||
</LinearLayout>
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
40
Habitica/res/layout/purchase_subscription_view.xml
Normal file
40
Habitica/res/layout/purchase_subscription_view.xml
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="horizontal" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/habit_inactive_gray"
|
||||
android:gravity="center"
|
||||
android:minHeight="80dp"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/brand_700">
|
||||
<View
|
||||
android:id="@+id/subscriptionSelectedView"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:background="@drawable/subscription_unselected"
|
||||
android:layout_gravity="center"/>
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/priceLabel"
|
||||
android:textColor="@color/brand_100"
|
||||
android:gravity="center"
|
||||
android:textSize="36sp"
|
||||
tools:text="$ 21"
|
||||
android:layout_marginStart="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/descriptionTextView"
|
||||
android:textColor="@color/brand_100"
|
||||
tools:text="recurring every month"
|
||||
android:layout_marginStart="16dp"/>
|
||||
</LinearLayout>
|
||||
|
|
@ -14,5 +14,7 @@
|
|||
|
||||
<declare-styleable name="MaxHeightScrollView">
|
||||
<attr name="maxHeightMultiplier" format="float" />
|
||||
<declare-styleable name="SubscriptionOptionView">
|
||||
<attr name="recurringText" format="string" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -109,4 +109,5 @@
|
|||
<color name="task_secondary_text">#B2B2B2</color>
|
||||
<color name="header_class_name">#CCBEED</color>
|
||||
<color name="gem_icon_color">#24cc8f</color>
|
||||
<color name="subscription_description_text">#b1000000</color>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -91,5 +91,5 @@
|
|||
|
||||
<dimen name="task_icon_space">12dp</dimen>
|
||||
<dimen name="task_icon_size">18dp</dimen>
|
||||
|
||||
</resources>
|
||||
<dimen name="task_info_bar_bottom_space">-8dp</dimen>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@
|
|||
|
||||
<string name="qr_album_name" translatable="false">habitica</string>
|
||||
<string name="qr_file_name" translatable="false"> habitrpg-qr-code.jpg</string>
|
||||
<string name="habitica_user_count">2,000,000</string>
|
||||
</resources>
|
||||
<string name="habitica_user_count" translatable="false">2,000,000</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -448,6 +448,19 @@ To start, which parts of your life do you want to improve?</string>
|
|||
<string name="belongs_to_challenge">Belongs to Challenge</string>
|
||||
<string name="has_reminder">Has Reminder</string>
|
||||
<string name="has_tag">Has Tag</string>
|
||||
<string name="subscribe.title">Subscribing supports the developers and helps keep Habitica running</string>
|
||||
<string name="subscribe.subtitle">Become a subscriber and you’ll get these useful benefits:</string>
|
||||
<string name="subscribe.listitem1">Buy gems with gold</string>
|
||||
<string name="subscribe.listitem2">Exclusive monthly items</string>
|
||||
<string name="subscribe.listitem3">Retain additional history entries</string>
|
||||
<string name="subscribe.listitem4">Daily drop-caps doubled</string>
|
||||
<string name="subscriptions">Subscriptions</string>
|
||||
<string name="subscription_duration" formatted="false">Recurring every %s</string>
|
||||
<string name="subscribe">Subscribe</string>
|
||||
<string name="subscribe.listitem1.description">Alexander the Merchant will sell you Gems at a cost of 20 gold per gem. His monthly shipments are initially capped at 25 Gems per month, but this cap increases by 5 Gems for every three months of consecutive subscription, up to a maximum of 50 Gems per month!</string>
|
||||
<string name="subscribe.listitem2.description">Makes completed To-Dos and task history available for longer.</string>
|
||||
<string name="subscribe.listitem3.description">Complete your stable faster!</string>
|
||||
<string name="subscribe.listitem4.description">Each month you will receive a unique cosmetic item for your avatar! Plus, for every three months of consecutive subscription, the Mysterious Time Travelers will grant you access to historic (and futuristic!) cosmetic items.</string>
|
||||
|
||||
<string name="byLeader" formatted="false">by %s</string>
|
||||
<string name="challenge_details">Challenge Details</string>
|
||||
|
|
|
|||
|
|
@ -200,4 +200,11 @@
|
|||
<item name="android:paddingTop">@dimen/section_top_padding</item>
|
||||
<item name="android:paddingBottom">@dimen/section_top_padding</item>
|
||||
</style>
|
||||
|
||||
<style name="GemPurchaseListItemDescription">
|
||||
<item name="android:layout_gravity">center_horizontal</item>
|
||||
<item name="android:gravity">center_horizontal</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:textColor">@color/subscription_description_text</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -33,8 +33,8 @@ import com.squareup.leakcanary.LeakCanary;
|
|||
import org.solovyev.android.checkout.Billing;
|
||||
import org.solovyev.android.checkout.Cache;
|
||||
import org.solovyev.android.checkout.Checkout;
|
||||
import org.solovyev.android.checkout.Inventory;
|
||||
import org.solovyev.android.checkout.ProductTypes;
|
||||
import org.solovyev.android.checkout.Products;
|
||||
import org.solovyev.android.checkout.PurchaseVerifier;
|
||||
|
||||
import java.io.File;
|
||||
|
|
@ -336,7 +336,7 @@ public abstract class HabiticaBaseApplication extends MultiDexApplication {
|
|||
});
|
||||
|
||||
|
||||
checkout = Checkout.forApplication(billing, Products.create().add(ProductTypes.IN_APP, PurchaseTypes.allTypes));
|
||||
checkout = Checkout.forApplication(billing);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -344,6 +344,10 @@ public abstract class HabiticaBaseApplication extends MultiDexApplication {
|
|||
return checkout;
|
||||
}
|
||||
|
||||
public Billing getBilling() {
|
||||
return billing;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
public static AppComponent getComponent() {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter
|
|||
import com.habitrpg.android.habitica.ui.adapter.tasks.TodosRecyclerViewAdapter;
|
||||
import com.habitrpg.android.habitica.ui.fragments.GemsPurchaseFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.NewsFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.SubscriptionFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.faq.FAQDetailFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.faq.FAQOverviewFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.inventory.customization.AvatarCustomizationFragment;
|
||||
|
|
@ -220,6 +221,7 @@ public interface AppComponent {
|
|||
|
||||
void inject(TodosRecyclerViewAdapter todosRecyclerViewAdapter);
|
||||
|
||||
void inject(SubscriptionFragment subscriptionFragment);
|
||||
void inject(ChallengeTasksRecyclerViewFragment.ChallengeTasksRecyclerViewAdapter challengeTasksRecyclerViewAdapter);
|
||||
|
||||
void inject(ChallengeTasksRecyclerViewFragment challengeTasksRecyclerViewFragment);
|
||||
|
|
|
|||
|
|
@ -11,5 +11,12 @@ public class PurchaseTypes {
|
|||
public static String Purchase42Gems = "com.habitrpg.android.habitica.iap.42gems";
|
||||
public static String Purchase84Gems = "com.habitrpg.android.habitica.iap.84gems";
|
||||
|
||||
public static List<String> allTypes = Arrays.asList(Purchase4Gems, Purchase21Gems, Purchase42Gems, Purchase84Gems);
|
||||
public static List<String> allGemTypes = Arrays.asList(Purchase4Gems, Purchase21Gems, Purchase42Gems, Purchase84Gems);
|
||||
|
||||
public static String Subscription1Month = "com.habitrpg.android.habitica.subscription.1month";
|
||||
public static String Subscription3Month = "com.habitrpg.android.habitica.subscription.3month";
|
||||
public static String Subscription6Month = "com.habitrpg.android.habitica.subscription.6month";
|
||||
public static String Subscription12Month = "com.habitrpg.android.habitica.subscription.12month";
|
||||
|
||||
public static List<String> allSubscriptionTypes = Arrays.asList(Subscription1Month, Subscription3Month, Subscription6Month, Subscription12Month);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
package com.habitrpg.android.habitica.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
|
||||
public class SubscriptionOptionView extends FrameLayout {
|
||||
|
||||
@BindView(R.id.priceLabel)
|
||||
TextView priceTextView;
|
||||
|
||||
@BindView(R.id.descriptionTextView)
|
||||
TextView descriptionTextView;
|
||||
|
||||
@BindView(R.id.subscriptionSelectedView)
|
||||
View subscriptionSelectedView;
|
||||
|
||||
private String sku;
|
||||
|
||||
public SubscriptionOptionView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
inflate(context, R.layout.purchase_subscription_view, this);
|
||||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
TypedArray a = context.getTheme().obtainStyledAttributes(
|
||||
attrs,
|
||||
R.styleable.SubscriptionOptionView,
|
||||
0, 0);
|
||||
|
||||
descriptionTextView.setText(context.getString(R.string.subscription_duration, a.getText(R.styleable.SubscriptionOptionView_recurringText)));
|
||||
|
||||
}
|
||||
|
||||
public void setOnPurchaseClickListener(Button.OnClickListener listener) {
|
||||
this.setOnClickListener(listener);
|
||||
}
|
||||
|
||||
public void setPriceText(String text) {
|
||||
this.priceTextView.setText(text);
|
||||
}
|
||||
|
||||
public void setSku(String sku) {
|
||||
this.sku = sku;
|
||||
}
|
||||
|
||||
public String getSku() {
|
||||
return sku;
|
||||
}
|
||||
|
||||
public void setIsPurchased(boolean purchased) {
|
||||
if (purchased) {
|
||||
subscriptionSelectedView.setBackgroundResource(R.drawable.subscription_selected);
|
||||
} else {
|
||||
subscriptionSelectedView.setBackgroundResource(R.drawable.subscription_unselected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ import com.habitrpg.android.habitica.R;
|
|||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.helpers.PurchaseTypes;
|
||||
import com.habitrpg.android.habitica.ui.fragments.GemsPurchaseFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.SubscriptionFragment;
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.party.PartyInviteFragment;
|
||||
import com.playseeds.android.sdk.Seeds;
|
||||
import com.playseeds.android.sdk.inappmessaging.InAppMessageListener;
|
||||
|
||||
|
|
@ -14,13 +16,30 @@ import org.solovyev.android.checkout.Checkout;
|
|||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
|
||||
public class GemPurchaseActivity extends BaseActivity implements GemsPurchaseFragment.Listener, InAppMessageListener {
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class GemPurchaseActivity extends BaseActivity implements InAppMessageListener {
|
||||
|
||||
private ActivityCheckout checkout;
|
||||
|
||||
@BindView(R.id.tab_layout)
|
||||
TabLayout tabLayout;
|
||||
|
||||
@BindView(R.id.view_pager)
|
||||
ViewPager viewPager;
|
||||
|
||||
List<CheckoutFragment> fragments = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected int getLayoutResId() {
|
||||
return R.layout.activity_gem_purchase;
|
||||
|
|
@ -58,9 +77,9 @@ public class GemPurchaseActivity extends BaseActivity implements GemsPurchaseFra
|
|||
getSupportActionBar().setTitle(R.string.gem_purchase_toolbartitle);
|
||||
}
|
||||
|
||||
GemsPurchaseFragment firstFragment = new GemsPurchaseFragment();
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.add(R.id.fragment_container, firstFragment).commit();
|
||||
viewPager.setCurrentItem(0);
|
||||
|
||||
setViewPagerAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -81,11 +100,10 @@ public class GemPurchaseActivity extends BaseActivity implements GemsPurchaseFra
|
|||
}
|
||||
|
||||
private void setupCheckout() {
|
||||
checkout = Checkout.forActivity(this, HabiticaApplication.getInstance(this).getCheckout());
|
||||
checkout = Checkout.forActivity(this, HabiticaApplication.getInstance(this).getBilling());
|
||||
checkout.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityCheckout getActivityCheckout() {
|
||||
return checkout;
|
||||
}
|
||||
|
|
@ -135,4 +153,55 @@ public class GemPurchaseActivity extends BaseActivity implements GemsPurchaseFra
|
|||
System.out.println("Exception: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setViewPagerAdapter() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
|
||||
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
CheckoutFragment fragment;
|
||||
if (position == 0) {
|
||||
fragment = new GemsPurchaseFragment();
|
||||
} else {
|
||||
fragment = new SubscriptionFragment();
|
||||
}
|
||||
if (fragments.size() > position) {
|
||||
fragments.set(position, fragment);
|
||||
} else {
|
||||
fragments.add(fragment);
|
||||
}
|
||||
fragment.setListener(GemPurchaseActivity.this);
|
||||
fragment.setupCheckout();
|
||||
return (Fragment)fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return getString(R.string.gems);
|
||||
case 1:
|
||||
return getString(R.string.subscriptions);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
if (tabLayout != null && viewPager != null) {
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
}
|
||||
}
|
||||
|
||||
public interface CheckoutFragment {
|
||||
|
||||
void setupCheckout();
|
||||
void setListener(GemPurchaseActivity listener);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ import com.habitrpg.android.habitica.helpers.PurchaseTypes;
|
|||
import com.habitrpg.android.habitica.proxy.ifce.CrashlyticsProxy;
|
||||
import com.habitrpg.android.habitica.ui.GemPurchaseOptionsView;
|
||||
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity;
|
||||
import com.habitrpg.android.habitica.ui.helpers.ViewHelper;
|
||||
import com.playseeds.android.sdk.Seeds;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.solovyev.android.checkout.ActivityCheckout;
|
||||
|
|
@ -25,6 +23,7 @@ import android.content.Context;
|
|||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -36,7 +35,7 @@ import javax.inject.Inject;
|
|||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class GemsPurchaseFragment extends BaseFragment {
|
||||
public class GemsPurchaseFragment extends BaseFragment implements GemPurchaseActivity.CheckoutFragment {
|
||||
|
||||
@BindView(R.id.gems_4_view)
|
||||
GemPurchaseOptionsView gems4View;
|
||||
|
|
@ -50,19 +49,11 @@ public class GemsPurchaseFragment extends BaseFragment {
|
|||
@Inject
|
||||
CrashlyticsProxy crashlyticsProxy;
|
||||
|
||||
private HashMap<String, String> priceMap;
|
||||
|
||||
private static final int GEMS_TO_ADD = 21;
|
||||
Button btnPurchaseGems;
|
||||
private Listener listener;
|
||||
private GemPurchaseActivity listener;
|
||||
private BillingRequests billingRequests;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
listener = (Listener) context;
|
||||
}
|
||||
private Inventory inventory;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
|
|
@ -70,8 +61,6 @@ public class GemsPurchaseFragment extends BaseFragment {
|
|||
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
priceMap = new HashMap<>();
|
||||
|
||||
return inflater.inflate(R.layout.fragment_gem_purchase, container, false);
|
||||
}
|
||||
|
||||
|
|
@ -90,16 +79,20 @@ public class GemsPurchaseFragment extends BaseFragment {
|
|||
gems84View.setOnPurchaseClickListener(v -> purchaseGems(PurchaseTypes.Purchase84Gems));
|
||||
|
||||
gems84View.seedsImageButton.setOnClickListener(v -> ((GemPurchaseActivity)this.getActivity()).showSeedsPromo(getString(R.string.seeds_interstitial_gems), "store"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupCheckout() {
|
||||
final ActivityCheckout checkout = listener.getActivityCheckout();
|
||||
|
||||
if (checkout != null) {
|
||||
checkout.destroyPurchaseFlow();
|
||||
|
||||
inventory = checkout.makeInventory();
|
||||
|
||||
checkout.createPurchaseFlow(new RequestListener<Purchase>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Purchase purchase) {
|
||||
if (PurchaseTypes.allTypes.contains(purchase.sku)) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku)) {
|
||||
billingRequests.consume(purchase.token, new RequestListener<Object>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Object o) {
|
||||
|
|
@ -139,24 +132,29 @@ public class GemsPurchaseFragment extends BaseFragment {
|
|||
|
||||
@Override
|
||||
public void onReady(@NonNull BillingRequests billingRequests, @NonNull String s, boolean b) {
|
||||
|
||||
checkout.loadInventory().whenLoaded(products -> {
|
||||
|
||||
Inventory.Product gems = products.get(ProductTypes.IN_APP);
|
||||
|
||||
java.util.List<Sku> skus = gems.getSkus();
|
||||
|
||||
for (Sku sku : skus) {
|
||||
priceMap.put(sku.id, sku.price);
|
||||
updateButtonLabel(sku.id, sku.price);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
inventory.load(Inventory.Request.create()
|
||||
.loadAllPurchases().loadSkus(ProductTypes.IN_APP, PurchaseTypes.allGemTypes),
|
||||
products -> {
|
||||
Inventory.Product gems = products.get(ProductTypes.IN_APP);
|
||||
if (!gems.supported) {
|
||||
// billing is not supported, user can't purchase anything
|
||||
return;
|
||||
}
|
||||
java.util.List<Sku> skus = gems.getSkus();
|
||||
for (Sku sku : skus) {
|
||||
updateButtonLabel(sku.id.code, sku.price);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(GemPurchaseActivity listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private void updateButtonLabel(String sku, String price) {
|
||||
GemPurchaseOptionsView matchingView;
|
||||
if (sku.equals(PurchaseTypes.Purchase4Gems)) {
|
||||
|
|
@ -179,7 +177,7 @@ public class GemsPurchaseFragment extends BaseFragment {
|
|||
@Override
|
||||
public void onSuccess(@NonNull Purchases purchases) {
|
||||
for (Purchase purchase : purchases.list) {
|
||||
if (PurchaseTypes.allTypes.contains(purchase.sku)) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku)) {
|
||||
billingRequests.consume(purchase.token, new RequestListener<Object>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Object o) {
|
||||
|
|
@ -223,8 +221,4 @@ public class GemsPurchaseFragment extends BaseFragment {
|
|||
});
|
||||
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
ActivityCheckout getActivityCheckout();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,219 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.events.BoughtGemsEvent;
|
||||
import com.habitrpg.android.habitica.helpers.PurchaseTypes;
|
||||
import com.habitrpg.android.habitica.proxy.ifce.CrashlyticsProxy;
|
||||
import com.habitrpg.android.habitica.ui.SubscriptionOptionView;
|
||||
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
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.ProductTypes;
|
||||
import org.solovyev.android.checkout.Purchase;
|
||||
import org.solovyev.android.checkout.Purchases;
|
||||
import org.solovyev.android.checkout.RequestListener;
|
||||
import org.solovyev.android.checkout.Sku;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
public class SubscriptionFragment extends BaseFragment implements GemPurchaseActivity.CheckoutFragment {
|
||||
|
||||
@Inject
|
||||
CrashlyticsProxy crashlyticsProxy;
|
||||
|
||||
@BindView(R.id.subscription1month)
|
||||
SubscriptionOptionView subscription1MonthView;
|
||||
@BindView(R.id.subscription3month)
|
||||
SubscriptionOptionView subscription3MonthView;
|
||||
@BindView(R.id.subscription6month)
|
||||
SubscriptionOptionView subscription6MonthView;
|
||||
@BindView(R.id.subscription12month)
|
||||
SubscriptionOptionView subscription12MonthView;
|
||||
|
||||
@BindView(R.id.subscribeButton)
|
||||
Button subscriptionButton;
|
||||
|
||||
@Nullable
|
||||
String selectedSubscriptionSku;
|
||||
|
||||
private GemPurchaseActivity listener;
|
||||
private BillingRequests billingRequests;
|
||||
private Inventory inventory;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
return inflater.inflate(R.layout.fragment_subscription, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
this.subscription1MonthView.setOnPurchaseClickListener(view1 -> selectSubscription(PurchaseTypes.Subscription1Month));
|
||||
this.subscription3MonthView.setOnPurchaseClickListener(view1 -> selectSubscription(PurchaseTypes.Subscription3Month));
|
||||
this.subscription6MonthView.setOnPurchaseClickListener(view1 -> selectSubscription(PurchaseTypes.Subscription6Month));
|
||||
this.subscription12MonthView.setOnPurchaseClickListener(view1 -> selectSubscription(PurchaseTypes.Subscription12Month));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupCheckout() {
|
||||
final ActivityCheckout checkout = listener.getActivityCheckout();
|
||||
if (checkout != null) {
|
||||
inventory = checkout.makeInventory();
|
||||
|
||||
checkout.destroyPurchaseFlow();
|
||||
|
||||
checkout.createPurchaseFlow(new RequestListener<Purchase>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Purchase purchase) {
|
||||
if (PurchaseTypes.allSubscriptionTypes.contains(purchase.sku)) {
|
||||
billingRequests.consume(purchase.token, new RequestListener<Object>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Object o) {
|
||||
if (purchase.sku.equals(PurchaseTypes.Purchase84Gems)) {
|
||||
((GemPurchaseActivity)getActivity()).showSeedsPromo(getString(R.string.seeds_interstitial_sharing), "store");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, @NonNull Exception e) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "Consume", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, @NonNull Exception e) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "Error", e);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
checkout.whenReady(new Checkout.Listener() {
|
||||
@Override
|
||||
public void onReady(@NonNull final BillingRequests billingRequests) {
|
||||
SubscriptionFragment.this.billingRequests = billingRequests;
|
||||
|
||||
checkIfPendingPurchases();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady(@NonNull BillingRequests billingRequests, @NonNull String s, boolean b) {
|
||||
inventory.load(Inventory.Request.create()
|
||||
.loadAllPurchases().loadSkus(ProductTypes.SUBSCRIPTION, PurchaseTypes.allSubscriptionTypes),
|
||||
products -> {
|
||||
Inventory.Product subscriptions = products.get(ProductTypes.SUBSCRIPTION);
|
||||
|
||||
java.util.List<Sku> skus = subscriptions.getSkus();
|
||||
|
||||
for (Sku sku : skus) {
|
||||
updateButtonLabel(sku, sku.price, subscriptions);
|
||||
}
|
||||
selectSubscription(PurchaseTypes.Subscription1Month);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateButtonLabel(Sku sku, String price, Inventory.Product subscriptions) {
|
||||
SubscriptionOptionView matchingView = buttonForSku(sku);
|
||||
if (matchingView != null) {
|
||||
matchingView.setPriceText(price);
|
||||
matchingView.setSku(sku.id.code);
|
||||
matchingView.setIsPurchased(subscriptions.isPurchased(sku));
|
||||
}
|
||||
}
|
||||
|
||||
private void selectSubscription(String sku) {
|
||||
if (this.selectedSubscriptionSku != null) {
|
||||
SubscriptionOptionView oldButton = buttonForSku(this.selectedSubscriptionSku);
|
||||
if (oldButton != null) {
|
||||
oldButton.setIsPurchased(false);
|
||||
}
|
||||
}
|
||||
this.selectedSubscriptionSku = sku;
|
||||
SubscriptionOptionView subscriptionOptionButton = buttonForSku(this.selectedSubscriptionSku);
|
||||
if (subscriptionOptionButton != null) {
|
||||
subscriptionOptionButton.setIsPurchased(true);
|
||||
}
|
||||
this.subscriptionButton.setEnabled(true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private SubscriptionOptionView buttonForSku(Sku sku) {
|
||||
return buttonForSku(sku.id.code);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private SubscriptionOptionView buttonForSku(String sku) {
|
||||
if (sku.equals(PurchaseTypes.Subscription1Month)) {
|
||||
return subscription1MonthView;
|
||||
} else if (sku.equals(PurchaseTypes.Subscription3Month)) {
|
||||
return subscription3MonthView;
|
||||
} else if (sku.equals(PurchaseTypes.Subscription6Month)) {
|
||||
return subscription6MonthView;
|
||||
} else if (sku.equals(PurchaseTypes.Subscription12Month)) {
|
||||
return subscription12MonthView;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(GemPurchaseActivity listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private void checkIfPendingPurchases() {
|
||||
billingRequests.getAllPurchases(ProductTypes.SUBSCRIPTION, new RequestListener<Purchases>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Purchases purchases) {
|
||||
for (Purchase purchase : purchases.list) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku)) {
|
||||
billingRequests.consume(purchase.token, new RequestListener<Object>() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull Object o) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, @NonNull Exception e) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "Consume", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, @NonNull Exception e) {
|
||||
crashlyticsProxy.fabricLogE("Purchase", "getAllPurchases", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -46,11 +46,11 @@ android {
|
|||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'org.glassfish:javax.json:1.0.4'
|
||||
compile 'com.google.android.gms:play-services:9.2.0'
|
||||
compile 'com.google.android.gms:play-services:10.0.1'
|
||||
compile 'com.google.code.gson:gson:2.4'
|
||||
compile 'com.android.support:multidex:1.0.1'
|
||||
compile 'com.loopj.android:android-async-http:1.4.9'
|
||||
compile 'org.solovyev.android:checkout:0.7.5@aar'
|
||||
compile 'org.solovyev.android:checkout:0.9.1@aar'
|
||||
androidTestCompile 'org.mockito:mockito-core:1.9.5'
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker:1.0'
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.0'
|
||||
|
|
|
|||
Loading…
Reference in a new issue