mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-07-13 17:51:57 +00:00
[#19] Purchase Gems now working :)
This commit is contained in:
parent
b00d545d1c
commit
65df55f57e
17 changed files with 325 additions and 78 deletions
|
|
@ -88,7 +88,7 @@ dependencies {
|
||||||
compile 'de.greenrobot:eventbus:2.4.0'
|
compile 'de.greenrobot:eventbus:2.4.0'
|
||||||
|
|
||||||
// IAP Handling / Verification
|
// IAP Handling / Verification
|
||||||
compile 'org.solovyev.android:checkout:0.7.4@aar'
|
compile 'org.solovyev.android:checkout:0.7.5@aar'
|
||||||
|
|
||||||
compile 'com.facebook.android:facebook-android-sdk:4.7.0'
|
compile 'com.facebook.android:facebook-android-sdk:4.7.0'
|
||||||
//Material Dialogs
|
//Material Dialogs
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,22 @@
|
||||||
android:orientation="vertical" android:layout_width="match_parent"
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:text="Help support Habitica"
|
||||||
|
android:layout_gravity="center_horizontal">
|
||||||
|
|
||||||
|
</TextView>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Buy"
|
android:text="+ 20"
|
||||||
android:id="@+id/btn.purchase.gems"
|
android:id="@+id/btn.purchase.gems"
|
||||||
android:layout_gravity="center_horizontal" />
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:drawableRight="@drawable/ic_header_gem"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
|
android:textColor="@color/white"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
@ -19,8 +19,11 @@ import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback;
|
||||||
import com.habitrpg.android.habitica.callbacks.TaskDeletionCallback;
|
import com.habitrpg.android.habitica.callbacks.TaskDeletionCallback;
|
||||||
import com.habitrpg.android.habitica.callbacks.TaskScoringCallback;
|
import com.habitrpg.android.habitica.callbacks.TaskScoringCallback;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.api.ApiService;
|
import com.magicmicky.habitrpgwrapper.lib.api.ApiService;
|
||||||
|
import com.magicmicky.habitrpgwrapper.lib.api.InAppPurchasesApiService;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.api.Server;
|
import com.magicmicky.habitrpgwrapper.lib.api.Server;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.api.TypeAdapter.TagsAdapter;
|
import com.magicmicky.habitrpgwrapper.lib.api.TypeAdapter.TagsAdapter;
|
||||||
|
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest;
|
||||||
|
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.models.SkillList;
|
import com.magicmicky.habitrpgwrapper.lib.models.SkillList;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.models.TaskDirection;
|
import com.magicmicky.habitrpgwrapper.lib.models.TaskDirection;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.models.UserAuth;
|
import com.magicmicky.habitrpgwrapper.lib.models.UserAuth;
|
||||||
|
|
@ -50,20 +53,21 @@ public class APIHelper implements ErrorHandler, Profiler {
|
||||||
private static final String TAG = "ApiHelper";
|
private static final String TAG = "ApiHelper";
|
||||||
// I think we don't need the APIHelper anymore we could just use ApiService
|
// I think we don't need the APIHelper anymore we could just use ApiService
|
||||||
public final ApiService apiService;
|
public final ApiService apiService;
|
||||||
|
private final InAppPurchasesApiService inAppPurchasesService;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
private HostConfig cfg;
|
||||||
|
|
||||||
//private OnHabitsAPIResult mResultListener;
|
//private OnHabitsAPIResult mResultListener;
|
||||||
//private HostConfig mConfig;
|
//private HostConfig mConfig;
|
||||||
public APIHelper(Context c, final HostConfig cfg) {
|
public APIHelper(Context c, final HostConfig cfg) {
|
||||||
this.mContext = c;
|
this.mContext = c;
|
||||||
|
this.cfg = cfg;
|
||||||
|
|
||||||
RequestInterceptor requestInterceptor = new RequestInterceptor() {
|
RequestInterceptor requestInterceptor = new RequestInterceptor() {
|
||||||
@Override
|
@Override
|
||||||
public void intercept(RequestInterceptor.RequestFacade request) {
|
public void intercept(RequestInterceptor.RequestFacade request) {
|
||||||
request.addHeader("x-api-key", cfg.getApi());
|
request.addHeader("x-api-key", cfg.getApi());
|
||||||
request.addHeader("x-api-user", cfg.getUser());
|
request.addHeader("x-api-user", cfg.getUser());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -104,6 +108,19 @@ public class APIHelper implements ErrorHandler, Profiler {
|
||||||
.build();
|
.build();
|
||||||
this.apiService = adapter.create(ApiService.class);
|
this.apiService = adapter.create(ApiService.class);
|
||||||
|
|
||||||
|
server = new Server(cfg.getAddress(), false);
|
||||||
|
|
||||||
|
adapter = new RestAdapter.Builder()
|
||||||
|
.setEndpoint(server.toString())
|
||||||
|
.setErrorHandler(this)
|
||||||
|
.setProfiler(this)
|
||||||
|
.setLogLevel(BuildConfig.DEBUG ? RestAdapter.LogLevel.FULL : RestAdapter.LogLevel.NONE)
|
||||||
|
.setRequestInterceptor(requestInterceptor)
|
||||||
|
.setConverter(new GsonConverter(gson))
|
||||||
|
|
||||||
|
.build();
|
||||||
|
|
||||||
|
this.inAppPurchasesService = adapter.create(InAppPurchasesApiService.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final TypeAdapter<Boolean> booleanAsIntAdapter = new TypeAdapter<Boolean>() {
|
private static final TypeAdapter<Boolean> booleanAsIntAdapter = new TypeAdapter<Boolean>() {
|
||||||
|
|
@ -244,4 +261,9 @@ public class APIHelper implements ErrorHandler, Profiler {
|
||||||
public void reviveUser(HabitRPGUserCallback cb) {
|
public void reviveUser(HabitRPGUserCallback cb) {
|
||||||
apiService.revive(cb);
|
apiService.revive(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PurchaseValidationResult validatePurchase(PurchaseValidationRequest request)
|
||||||
|
{
|
||||||
|
return inAppPurchasesService.validatePurchase(cfg.getUser(), cfg.getApi(), request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.facebook.FacebookSdk;
|
||||||
import com.instabug.library.Instabug;
|
import com.instabug.library.Instabug;
|
||||||
import com.raizlabs.android.dbflow.config.FlowManager;
|
import com.raizlabs.android.dbflow.config.FlowManager;
|
||||||
|
|
||||||
|
|
@ -15,15 +16,10 @@ import org.solovyev.android.checkout.Checkout;
|
||||||
import org.solovyev.android.checkout.Inventory;
|
import org.solovyev.android.checkout.Inventory;
|
||||||
import org.solovyev.android.checkout.ProductTypes;
|
import org.solovyev.android.checkout.ProductTypes;
|
||||||
import org.solovyev.android.checkout.Products;
|
import org.solovyev.android.checkout.Products;
|
||||||
import org.solovyev.android.checkout.Purchase;
|
|
||||||
import org.solovyev.android.checkout.PurchaseVerifier;
|
import org.solovyev.android.checkout.PurchaseVerifier;
|
||||||
import org.solovyev.android.checkout.RequestListener;
|
|
||||||
import com.facebook.FacebookSdk;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -33,12 +29,16 @@ public class HabiticaApplication extends Application {
|
||||||
|
|
||||||
public static HabiticaApplication Instance;
|
public static HabiticaApplication Instance;
|
||||||
|
|
||||||
|
public static APIHelper ApiHelper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
Instance = this;
|
Instance = this;
|
||||||
|
|
||||||
|
billing.connect();
|
||||||
|
|
||||||
FlowManager.init(this);
|
FlowManager.init(this);
|
||||||
|
|
||||||
FacebookSdk.sdkInitialize(getApplicationContext());
|
FacebookSdk.sdkInitialize(getApplicationContext());
|
||||||
|
|
@ -73,6 +73,7 @@ public class HabiticaApplication extends Application {
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
// region IAP - Specific
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For better performance billing class should be used as singleton
|
* For better performance billing class should be used as singleton
|
||||||
|
|
@ -82,7 +83,7 @@ public class HabiticaApplication extends Application {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String getPublicKey() {
|
public String getPublicKey() {
|
||||||
return "sdfsdfdfsd";
|
return "DONT-NEED-IT";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
@ -93,24 +94,7 @@ public class HabiticaApplication extends Application {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PurchaseVerifier getPurchaseVerifier() {
|
public PurchaseVerifier getPurchaseVerifier() {
|
||||||
return new PurchaseVerifier() {
|
return new HabiticaPurchaseVerifier();
|
||||||
@Override
|
|
||||||
public void verify(List<Purchase> purchases, RequestListener<List<Purchase>> requestListener) {
|
|
||||||
final List<Purchase> verifiedPurchases = new ArrayList<Purchase>(purchases.size());
|
|
||||||
/* for (Purchase purchase : purchases) {
|
|
||||||
if (Security.verifyPurchase(publicKey, purchase.data, purchase.signature)) {
|
|
||||||
verifiedPurchases.add(purchase);
|
|
||||||
} else {
|
|
||||||
if (isEmpty(purchase.signature)) {
|
|
||||||
Billing.error("Cannot verify purchase: " + purchase + ". Signature is empty");
|
|
||||||
} else {
|
|
||||||
Billing.error("Cannot verify purchase: " + purchase + ". Wrong signature");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
//requestListener.onSuccess(verifiedPurchases);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -139,4 +123,5 @@ public class HabiticaApplication extends Application {
|
||||||
return checkout;
|
return checkout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.habitrpg.android.habitica;
|
||||||
|
|
||||||
|
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest;
|
||||||
|
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult;
|
||||||
|
import com.magicmicky.habitrpgwrapper.lib.models.Transaction;
|
||||||
|
|
||||||
|
import org.solovyev.android.checkout.BasePurchaseVerifier;
|
||||||
|
import org.solovyev.android.checkout.Purchase;
|
||||||
|
import org.solovyev.android.checkout.RequestListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Negue on 26.11.2015.
|
||||||
|
*/
|
||||||
|
public class HabiticaPurchaseVerifier extends BasePurchaseVerifier {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doVerify(final List<Purchase> purchases, final RequestListener<List<Purchase>> requestListener) {
|
||||||
|
final List<Purchase> verifiedPurchases = new ArrayList<Purchase>(purchases.size());
|
||||||
|
|
||||||
|
for(final Purchase purchase : purchases)
|
||||||
|
{
|
||||||
|
PurchaseValidationRequest validationRequest = new PurchaseValidationRequest();
|
||||||
|
validationRequest.transaction = new Transaction();
|
||||||
|
validationRequest.transaction.receipt = purchase.data;
|
||||||
|
validationRequest.transaction.signature = purchase.signature;
|
||||||
|
|
||||||
|
PurchaseValidationResult purchaseValidationResult = HabiticaApplication.ApiHelper.validatePurchase(validationRequest);
|
||||||
|
|
||||||
|
if (purchaseValidationResult.ok) {
|
||||||
|
verifiedPurchases.add(purchase);
|
||||||
|
|
||||||
|
requestListener.onSuccess(verifiedPurchases);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
requestListener.onError(purchases.indexOf(purchase), new Exception(purchaseValidationResult.data.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -58,6 +58,9 @@ public class LoginActivity extends AppCompatActivity
|
||||||
public Boolean isRegistering;
|
public Boolean isRegistering;
|
||||||
private Menu menu;
|
private Menu menu;
|
||||||
|
|
||||||
|
private String apiAddress = getString(R.string.SP_address_default);
|
||||||
|
//private String apiAddress = "http://192.168.2.155:8080/"; // local testing
|
||||||
|
|
||||||
private CallbackManager callbackManager;
|
private CallbackManager callbackManager;
|
||||||
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
@ -107,7 +110,7 @@ public class LoginActivity extends AppCompatActivity
|
||||||
|
|
||||||
HostConfig hc= PrefsActivity.fromContext(this);
|
HostConfig hc= PrefsActivity.fromContext(this);
|
||||||
if(hc ==null) {
|
if(hc ==null) {
|
||||||
hc = new HostConfig(getString(R.string.SP_address_default), "80", "", "");
|
hc = new HostConfig(apiAddress, "80", "", "");
|
||||||
}
|
}
|
||||||
mApiHelper = new APIHelper(this,hc);
|
mApiHelper = new APIHelper(this,hc);
|
||||||
|
|
||||||
|
|
@ -165,7 +168,6 @@ public class LoginActivity extends AppCompatActivity
|
||||||
public static void expand(final View v) {
|
public static void expand(final View v) {
|
||||||
v.setVisibility(View.VISIBLE);
|
v.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
//
|
|
||||||
|
|
||||||
public static void collapse(final View v) {
|
public static void collapse(final View v) {
|
||||||
v.setVisibility(View.GONE);
|
v.setVisibility(View.GONE);
|
||||||
|
|
@ -180,7 +182,7 @@ public class LoginActivity extends AppCompatActivity
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
boolean ans = editor.putString(getString(R.string.SP_APIToken), api)
|
boolean ans = editor.putString(getString(R.string.SP_APIToken), api)
|
||||||
.putString(getString(R.string.SP_userID), user)
|
.putString(getString(R.string.SP_userID), user)
|
||||||
.putString(getString(R.string.SP_address),getString(R.string.SP_address_default))
|
.putString(getString(R.string.SP_address), apiAddress)
|
||||||
.commit();
|
.commit();
|
||||||
if(!ans) {
|
if(!ans) {
|
||||||
throw new Exception("PB_string_commit");
|
throw new Exception("PB_string_commit");
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import android.view.View;
|
||||||
import com.crashlytics.android.Crashlytics;
|
import com.crashlytics.android.Crashlytics;
|
||||||
import com.crashlytics.android.core.CrashlyticsCore;
|
import com.crashlytics.android.core.CrashlyticsCore;
|
||||||
import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback;
|
import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback;
|
||||||
|
import com.habitrpg.android.habitica.events.commands.OpenGemPurchaseFragmentCommand;
|
||||||
import com.habitrpg.android.habitica.prefs.PrefsActivity;
|
import com.habitrpg.android.habitica.prefs.PrefsActivity;
|
||||||
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel;
|
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel;
|
||||||
import com.habitrpg.android.habitica.ui.MainDrawerBuilder;
|
import com.habitrpg.android.habitica.ui.MainDrawerBuilder;
|
||||||
|
|
@ -22,23 +23,20 @@ import com.habitrpg.android.habitica.userpicture.UserPictureRunnable;
|
||||||
import com.instabug.wrapper.support.activity.InstabugAppCompatActivity;
|
import com.instabug.wrapper.support.activity.InstabugAppCompatActivity;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.models.ContentResult;
|
import com.magicmicky.habitrpgwrapper.lib.models.ContentResult;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
|
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.models.QuestContent;
|
|
||||||
import com.magicmicky.habitrpgwrapper.lib.models.tasks.ItemData;
|
|
||||||
import com.mikepenz.materialdrawer.AccountHeader;
|
import com.mikepenz.materialdrawer.AccountHeader;
|
||||||
import com.mikepenz.materialdrawer.Drawer;
|
import com.mikepenz.materialdrawer.Drawer;
|
||||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||||
import com.raizlabs.android.dbflow.runtime.FlowContentObserver;
|
|
||||||
import com.raizlabs.android.dbflow.runtime.transaction.BaseTransaction;
|
import com.raizlabs.android.dbflow.runtime.transaction.BaseTransaction;
|
||||||
import com.raizlabs.android.dbflow.runtime.transaction.TransactionListener;
|
import com.raizlabs.android.dbflow.runtime.transaction.TransactionListener;
|
||||||
import com.raizlabs.android.dbflow.sql.builder.Condition;
|
import com.raizlabs.android.dbflow.sql.builder.Condition;
|
||||||
import com.raizlabs.android.dbflow.sql.language.Select;
|
import com.raizlabs.android.dbflow.sql.language.Select;
|
||||||
import com.raizlabs.android.dbflow.structure.BaseModel;
|
|
||||||
import com.raizlabs.android.dbflow.structure.Model;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import org.solovyev.android.checkout.ActivityCheckout;
|
||||||
|
import org.solovyev.android.checkout.Checkout;
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.InjectView;
|
import butterknife.InjectView;
|
||||||
|
import de.greenrobot.event.EventBus;
|
||||||
import io.fabric.sdk.android.Fabric;
|
import io.fabric.sdk.android.Fabric;
|
||||||
import retrofit.Callback;
|
import retrofit.Callback;
|
||||||
import retrofit.RetrofitError;
|
import retrofit.RetrofitError;
|
||||||
|
|
@ -73,6 +71,9 @@ public class MainActivity extends InstabugAppCompatActivity implements HabitRPGU
|
||||||
|
|
||||||
APIHelper mAPIHelper;
|
APIHelper mAPIHelper;
|
||||||
|
|
||||||
|
// Checkout needs to be in the Activity..
|
||||||
|
public static ActivityCheckout checkout = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
@ -93,7 +94,7 @@ public class MainActivity extends InstabugAppCompatActivity implements HabitRPGU
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.mAPIHelper = new APIHelper(this, hostConfig);
|
HabiticaApplication.ApiHelper = this.mAPIHelper = new APIHelper(this, hostConfig);
|
||||||
|
|
||||||
new Select().from(HabitRPGUser.class).where(Condition.column("id").eq(hostConfig.getUser())).async().querySingle(userTransactionListener);
|
new Select().from(HabitRPGUser.class).where(Condition.column("id").eq(hostConfig.getUser())).async().querySingle(userTransactionListener);
|
||||||
|
|
||||||
|
|
@ -132,6 +133,18 @@ public class MainActivity extends InstabugAppCompatActivity implements HabitRPGU
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Create Checkout
|
||||||
|
|
||||||
|
checkout = Checkout.forActivity(this, HabiticaApplication.Instance.getCheckout());
|
||||||
|
|
||||||
|
checkout.start();
|
||||||
|
|
||||||
|
EventBus.getDefault().register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEvent(OpenGemPurchaseFragmentCommand cmd){
|
||||||
|
drawer.setSelection(MainDrawerBuilder.SIDEBAR_PURCHASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -248,4 +261,19 @@ public class MainActivity extends InstabugAppCompatActivity implements HabitRPGU
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
checkout.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
if(checkout != null)
|
||||||
|
checkout.stop();
|
||||||
|
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.habitrpg.android.habitica.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Negue on 29.11.2015.
|
||||||
|
*/
|
||||||
|
public class BoughtGemsEvent {
|
||||||
|
public int NewGemsToAdd;
|
||||||
|
|
||||||
|
public BoughtGemsEvent(int newGemsToAdd) {
|
||||||
|
NewGemsToAdd = newGemsToAdd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.habitrpg.android.habitica.events.commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Negue on 29.11.2015.
|
||||||
|
*/
|
||||||
|
public class OpenGemPurchaseFragmentCommand {
|
||||||
|
}
|
||||||
|
|
@ -13,14 +13,18 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import com.habitrpg.android.habitica.R;
|
import com.habitrpg.android.habitica.R;
|
||||||
import com.habitrpg.android.habitica.databinding.ValueBarBinding;
|
import com.habitrpg.android.habitica.databinding.ValueBarBinding;
|
||||||
|
import com.habitrpg.android.habitica.events.BoughtGemsEvent;
|
||||||
|
import com.habitrpg.android.habitica.events.commands.OpenGemPurchaseFragmentCommand;
|
||||||
import com.habitrpg.android.habitica.userpicture.UserPicture;
|
import com.habitrpg.android.habitica.userpicture.UserPicture;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
|
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
|
||||||
import com.magicmicky.habitrpgwrapper.lib.models.Stats;
|
import com.magicmicky.habitrpgwrapper.lib.models.Stats;
|
||||||
|
|
||||||
|
import de.greenrobot.event.EventBus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Negue on 14.06.2015.
|
* Created by Negue on 14.06.2015.
|
||||||
*/
|
*/
|
||||||
public class AvatarWithBarsViewModel {
|
public class AvatarWithBarsViewModel implements View.OnClickListener {
|
||||||
private ValueBarBinding hpBar;
|
private ValueBarBinding hpBar;
|
||||||
private ValueBarBinding xpBar;
|
private ValueBarBinding xpBar;
|
||||||
private ValueBarBinding mpBar;
|
private ValueBarBinding mpBar;
|
||||||
|
|
@ -32,6 +36,7 @@ public class AvatarWithBarsViewModel {
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
private TextView lvlText, goldText, silverText, gemsText;
|
private TextView lvlText, goldText, silverText, gemsText;
|
||||||
|
private HabitRPGUser userObject;
|
||||||
|
|
||||||
public AvatarWithBarsViewModel(Context context, View v) {
|
public AvatarWithBarsViewModel(Context context, View v) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
@ -58,10 +63,17 @@ public class AvatarWithBarsViewModel {
|
||||||
setValueBar(hpBar, 50, 50, context.getString(R.string.HP_default), R.color.hpColor, R.drawable.ic_header_heart);
|
setValueBar(hpBar, 50, 50, context.getString(R.string.HP_default), R.color.hpColor, R.drawable.ic_header_heart);
|
||||||
setValueBar(xpBar, 1, 1, context.getString(R.string.XP_default), R.color.xpColor, R.drawable.ic_header_exp);
|
setValueBar(xpBar, 1, 1, context.getString(R.string.XP_default), R.color.xpColor, R.drawable.ic_header_exp);
|
||||||
setValueBar(mpBar, 100, 100, context.getString(R.string.MP_default), R.color.mpColor, R.drawable.ic_header_magic);
|
setValueBar(mpBar, 100, 100, context.getString(R.string.MP_default), R.color.mpColor, R.drawable.ic_header_magic);
|
||||||
|
|
||||||
|
EventBus.getDefault().register(this);
|
||||||
|
|
||||||
|
gemsText.setClickable(true);
|
||||||
|
gemsText.setOnClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||||
public void updateData(HabitRPGUser user) {
|
public void updateData(HabitRPGUser user) {
|
||||||
|
userObject = user;
|
||||||
|
|
||||||
Stats stats = user.getStats();
|
Stats stats = user.getStats();
|
||||||
char classShort;
|
char classShort;
|
||||||
String userClass = "";
|
String userClass = "";
|
||||||
|
|
@ -138,4 +150,17 @@ public class AvatarWithBarsViewModel {
|
||||||
valueBar.setBarForegroundColor(color);
|
valueBar.setBarForegroundColor(color);
|
||||||
valueBar.icHeader.setImageResource(icon);
|
valueBar.icHeader.setImageResource(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onEvent(BoughtGemsEvent gemsEvent){
|
||||||
|
Double gems = new Double(userObject.getBalance() * 4);
|
||||||
|
gems += gemsEvent.NewGemsToAdd;
|
||||||
|
gemsText.setText(gems.intValue() + "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
// Gems Clicked
|
||||||
|
|
||||||
|
EventBus.getDefault().post(new OpenGemPurchaseFragmentCommand());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,13 @@ import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||||
public class MainDrawerBuilder {
|
public class MainDrawerBuilder {
|
||||||
|
|
||||||
// Change the identificationIDs to the position IDs so that its easier to set the selected entry
|
// Change the identificationIDs to the position IDs so that its easier to set the selected entry
|
||||||
static final int SIDEBAR_TASKS = 0;
|
public static final int SIDEBAR_TASKS = 0;
|
||||||
static final int SIDEBAR_SKILLS = 1;
|
public static final int SIDEBAR_SKILLS = 1;
|
||||||
static final int SIDEBAR_TAVERN = 3;
|
public static final int SIDEBAR_TAVERN = 3;
|
||||||
static final int SIDEBAR_PARTY = 4;
|
public static final int SIDEBAR_PARTY = 4;
|
||||||
static final int SIDEBAR_PURCHASE = 5;
|
public static final int SIDEBAR_PURCHASE = 5;
|
||||||
static final int SIDEBAR_SETTINGS = 7;
|
public static final int SIDEBAR_SETTINGS = 7;
|
||||||
static final int SIDEBAR_ABOUT = 8;
|
public static final int SIDEBAR_ABOUT = 8;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,30 +9,36 @@ import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
||||||
import com.habitrpg.android.habitica.HabiticaApplication;
|
import com.habitrpg.android.habitica.HabiticaApplication;
|
||||||
|
import com.habitrpg.android.habitica.MainActivity;
|
||||||
import com.habitrpg.android.habitica.R;
|
import com.habitrpg.android.habitica.R;
|
||||||
|
import com.habitrpg.android.habitica.events.BoughtGemsEvent;
|
||||||
|
import com.habitrpg.android.habitica.ui.helpers.ViewHelper;
|
||||||
|
|
||||||
import org.solovyev.android.checkout.ActivityCheckout;
|
import org.solovyev.android.checkout.ActivityCheckout;
|
||||||
import org.solovyev.android.checkout.BillingRequests;
|
import org.solovyev.android.checkout.BillingRequests;
|
||||||
import org.solovyev.android.checkout.Checkout;
|
import org.solovyev.android.checkout.Checkout;
|
||||||
import org.solovyev.android.checkout.ProductTypes;
|
import org.solovyev.android.checkout.ProductTypes;
|
||||||
import org.solovyev.android.checkout.Purchase;
|
import org.solovyev.android.checkout.Purchase;
|
||||||
|
import org.solovyev.android.checkout.Purchases;
|
||||||
import org.solovyev.android.checkout.RequestListener;
|
import org.solovyev.android.checkout.RequestListener;
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.InjectView;
|
import butterknife.InjectView;
|
||||||
|
import butterknife.OnClick;
|
||||||
|
import de.greenrobot.event.EventBus;
|
||||||
|
import io.fabric.sdk.android.Fabric;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Negue on 24.11.2015.
|
* Created by Negue on 24.11.2015.
|
||||||
*/
|
*/
|
||||||
public class GemsPurchaseFragment extends BaseFragment {
|
public class GemsPurchaseFragment extends BaseFragment {
|
||||||
|
|
||||||
|
private BillingRequests billingRequests;
|
||||||
|
|
||||||
@InjectView(R.id.btn_purchase_gems)
|
@InjectView(R.id.btn_purchase_gems)
|
||||||
Button btnPurchaseGems;
|
Button btnPurchaseGems;
|
||||||
|
|
||||||
|
|
||||||
private ActivityCheckout checkout = null;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
@ -43,29 +49,44 @@ public class GemsPurchaseFragment extends BaseFragment {
|
||||||
|
|
||||||
ButterKnife.inject(this, v);
|
ButterKnife.inject(this, v);
|
||||||
|
|
||||||
checkout = Checkout.forActivity(this.activity, HabiticaApplication.Instance.getCheckout());
|
btnPurchaseGems.setEnabled(false);
|
||||||
|
ViewHelper.SetBackgroundTint(btnPurchaseGems, container.getResources().getColor(R.color.brand));
|
||||||
|
|
||||||
checkout.start();
|
MainActivity.checkout.destroyPurchaseFlow();
|
||||||
// you only need this if this activity starts purchase process
|
|
||||||
checkout.createPurchaseFlow(new RequestListener<Purchase>() {
|
MainActivity.checkout.createPurchaseFlow(new RequestListener<Purchase>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Purchase purchase) {
|
public void onSuccess(Purchase purchase) {
|
||||||
|
if(purchase.sku.equals(HabiticaApplication.Purchase20Gems)){
|
||||||
|
billingRequests.consume(purchase.token, new RequestListener<Object>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Object o) {
|
||||||
|
EventBus.getDefault().post(new BoughtGemsEvent(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int i, Exception e) {
|
||||||
|
Fabric.getLogger().e("Purchase", "Consume", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(int i, Exception e) {
|
public void onError(int i, Exception e) {
|
||||||
|
Fabric.getLogger().e("Purchase", "Error", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
MainActivity.checkout.whenReady(new Checkout.Listener() {
|
||||||
|
|
||||||
checkout.whenReady(new Checkout.Listener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onReady(BillingRequests billingRequests) {
|
public void onReady(final BillingRequests billingRequests) {
|
||||||
billingRequests.purchase(ProductTypes.IN_APP, HabiticaApplication.Purchase20Gems, null, checkout.getPurchaseFlow());
|
GemsPurchaseFragment.this.billingRequests = billingRequests;
|
||||||
|
|
||||||
|
btnPurchaseGems.setEnabled(true);
|
||||||
|
|
||||||
|
checkIfPendingPurchases();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -77,16 +98,55 @@ public class GemsPurchaseFragment extends BaseFragment {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkIfPendingPurchases(){
|
||||||
|
billingRequests.getAllPurchases(ProductTypes.IN_APP, new RequestListener<Purchases>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Purchases purchases) {
|
||||||
|
for(Purchase purchase : purchases.list){
|
||||||
|
if(purchase.sku.equals(HabiticaApplication.Purchase20Gems)) {
|
||||||
|
billingRequests.consume(purchase.token, new RequestListener<Object>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Object o) {
|
||||||
|
EventBus.getDefault().post(new BoughtGemsEvent(20));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onError(int i, Exception e) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
Fabric.getLogger().e("Purchase", "Consume", e);
|
||||||
checkout.onActivityResult(requestCode, resultCode, data);
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int i, Exception e) {
|
||||||
|
Fabric.getLogger().e("Purchase","getAllPurchases", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@OnClick(R.id.btn_purchase_gems)
|
||||||
public void onDestroy() {
|
public void doPurchaseGems(Button button) {
|
||||||
checkout.stop();
|
// check if the user already bought and if it hasn't validated yet
|
||||||
super.onDestroy();
|
billingRequests.isPurchased(ProductTypes.IN_APP, HabiticaApplication.Purchase20Gems, new RequestListener<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Boolean aBoolean) {
|
||||||
|
if (!aBoolean) {
|
||||||
|
// no current product exist
|
||||||
|
billingRequests.purchase(ProductTypes.IN_APP, HabiticaApplication.Purchase20Gems, null, MainActivity.checkout.getPurchaseFlow());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
checkIfPendingPurchases();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int i, Exception e) {
|
||||||
|
Fabric.getLogger().e("Purchase", "Error", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.magicmicky.habitrpgwrapper.lib.api;
|
||||||
|
|
||||||
|
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest;
|
||||||
|
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult;
|
||||||
|
|
||||||
|
import retrofit.Callback;
|
||||||
|
import retrofit.http.Body;
|
||||||
|
import retrofit.http.POST;
|
||||||
|
import retrofit.http.Query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Negue on 27.11.2015.
|
||||||
|
*/
|
||||||
|
public interface InAppPurchasesApiService {
|
||||||
|
@POST("/iap/android/verify")
|
||||||
|
PurchaseValidationResult validatePurchase(@Query("_id") String id, @Query("apiToken") String apiToken, @Body PurchaseValidationRequest request);
|
||||||
|
}
|
||||||
|
|
@ -4,19 +4,29 @@ package com.magicmicky.habitrpgwrapper.lib.api;
|
||||||
* Created by MagicMicky on 15/06/2014.
|
* Created by MagicMicky on 15/06/2014.
|
||||||
*/
|
*/
|
||||||
public class Server {
|
public class Server {
|
||||||
public final static Server NORMAL = new Server("https://habitrpg.com");
|
|
||||||
public final static Server BETA = new Server("https://beta.habitrpg.com");
|
|
||||||
|
|
||||||
private String addr;
|
private String addr;
|
||||||
|
|
||||||
public Server(String addr) {
|
public Server(String addr)
|
||||||
if(addr.endsWith("/api/v2") || addr.endsWith("/api/v2/"))
|
{
|
||||||
this.addr=addr;
|
this(addr, true);
|
||||||
else if(addr.endsWith("/"))
|
|
||||||
this.addr=addr + "api/v2";
|
|
||||||
else
|
|
||||||
this.addr = addr + "/api/v2";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Server(String addr, boolean attachPrefix)
|
||||||
|
{
|
||||||
|
if(attachPrefix){
|
||||||
|
if(addr.endsWith("/api/v2") || addr.endsWith("/api/v2/"))
|
||||||
|
this.addr=addr;
|
||||||
|
else if(addr.endsWith("/"))
|
||||||
|
this.addr=addr + "api/v2";
|
||||||
|
else
|
||||||
|
this.addr = addr + "/api/v2";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.addr = addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Server(Server s) {
|
public Server(Server s) {
|
||||||
this.addr = s.toString();
|
this.addr = s.toString();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.magicmicky.habitrpgwrapper.lib.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Negue on 26.11.2015.
|
||||||
|
*/
|
||||||
|
public class PurchaseValidationRequest {
|
||||||
|
public Transaction transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.magicmicky.habitrpgwrapper.lib.models;
|
||||||
|
|
||||||
|
public class PurchaseValidationResult{
|
||||||
|
public boolean ok;
|
||||||
|
public Object data;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.magicmicky.habitrpgwrapper.lib.models;
|
||||||
|
|
||||||
|
public class Transaction
|
||||||
|
{
|
||||||
|
public String receipt;
|
||||||
|
|
||||||
|
public String signature;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue