diff --git a/IAP6Helper/build.gradle b/IAP6Helper/build.gradle new file mode 100644 index 000000000..d8fc4749a --- /dev/null +++ b/IAP6Helper/build.gradle @@ -0,0 +1,24 @@ +apply plugin: 'com.android.library' +android { + compileSdkVersion rootProject.ext.android.compileSdkVersion + buildToolsVersion rootProject.ext.android.buildToolsVersion + defaultConfig { + minSdkVersion minSdkVersion + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + versionCode versionCode + versionName versionName + targetSdkVersion targetSdkVersion + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } +} + +dependencies { +} \ No newline at end of file diff --git a/IAP6Helper/proguard-rules.pro b/IAP6Helper/proguard-rules.pro new file mode 100644 index 000000000..7e9e287fb --- /dev/null +++ b/IAP6Helper/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\Users\sbkim\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/IAP6Helper/src/main/AndroidManifest.xml b/IAP6Helper/src/main/AndroidManifest.xml new file mode 100644 index 000000000..b5f9f1046 --- /dev/null +++ b/IAP6Helper/src/main/AndroidManifest.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/IAP6Helper/src/main/aidl/com/samsung/android/iap/IAPConnector.aidl b/IAP6Helper/src/main/aidl/com/samsung/android/iap/IAPConnector.aidl new file mode 100644 index 000000000..89f375057 --- /dev/null +++ b/IAP6Helper/src/main/aidl/com/samsung/android/iap/IAPConnector.aidl @@ -0,0 +1,19 @@ +package com.samsung.android.iap; + +import com.samsung.android.iap.IAPServiceCallback; + +interface IAPConnector { + + boolean requestCmd(IAPServiceCallback callback, in Bundle bundle); + + boolean unregisterCallback(IAPServiceCallback callback); + + ///////////////////////////// IAP 5.0 + Bundle getProductsDetails(String packageName, String itemIds, int pagingIndex, int mode); + + Bundle getOwnedList(String packageName, String itemType, int pagingIndex, int mode); + + Bundle consumePurchasedItems(String packageName, String purchaseIds, int mode); + + Bundle requestServiceAPI(String packageName, String requestId, String extraData); +} diff --git a/IAP6Helper/src/main/aidl/com/samsung/android/iap/IAPServiceCallback.aidl b/IAP6Helper/src/main/aidl/com/samsung/android/iap/IAPServiceCallback.aidl new file mode 100644 index 000000000..c37123350 --- /dev/null +++ b/IAP6Helper/src/main/aidl/com/samsung/android/iap/IAPServiceCallback.aidl @@ -0,0 +1,7 @@ +package com.samsung.android.iap; + +import android.os.Bundle; + +interface IAPServiceCallback { + oneway void responseCallback(in Bundle bundle); +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/AccountActivity.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/AccountActivity.java new file mode 100644 index 000000000..4ce2f87a2 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/AccountActivity.java @@ -0,0 +1,85 @@ +package com.samsung.android.sdk.iap.lib.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.helper.HelperUtil; +import com.samsung.android.sdk.iap.lib.helper.IapHelper; + +/** + * Created by sangbum7.kim on 2018-03-06. + */ + +public class AccountActivity extends Activity { + private static final String TAG = AccountActivity.class.getSimpleName(); + + IapHelper mIapHelper = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mIapHelper = IapHelper.getInstance(this); + // ==================================================================== + // 1. If IAP package is installed and valid, start SamsungAccount + // authentication activity to start purchase. + // ==================================================================== + Log.i(TAG, "Samsung Account Login..."); + HelperUtil.startAccountActivity(this); + // ==================================================================== + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + @Override + protected void onActivityResult(int _requestCode, int _resultCode, Intent intent) { + Log.i(TAG, "onActivityResult>> requestCode : " + _requestCode + ", resultCode : " + _resultCode); + switch (_requestCode) { + case HelperDefine.REQUEST_CODE_IS_ACCOUNT_CERTIFICATION: + Log.i(TAG, "REQUEST_CODE_IS_ACCOUNT_CERTIFICATION Result : " + _resultCode); + // 1) If SamsungAccount authentication is succeed + // ------------------------------------------------------------ + if (RESULT_OK == _resultCode) { + // bind to IAPService + // -------------------------------------------------------- + Runnable runProcess = new Runnable() { + @Override + public void run() { + mIapHelper.bindIapService(); + } + }; + runProcess.run(); + + finish(); + overridePendingTransition(0, 0); + // -------------------------------------------------------- + } + // ------------------------------------------------------------ + // 2) If SamsungAccount authentication is cancelled + // ------------------------------------------------------------ + else { +// Runnable runProcess = new Runnable() { +// @Override +// public void run() { +// if(mIapHelper.getServiceProcess() != null) +// mIapHelper.getServiceProcess().onEndProcess(); +// else +// mIapHelper.dispose(); +// } +// }; +// if(runProcess!=null) +// runProcess.run(); +// else + mIapHelper.dispose(); + finish(); + } + break; + } + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/BaseActivity.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/BaseActivity.java new file mode 100644 index 000000000..10e581604 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/BaseActivity.java @@ -0,0 +1,233 @@ +package com.samsung.android.sdk.iap.lib.activity; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.widget.Toast; + +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.dialog.BaseDialogFragment; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.helper.HelperUtil; +import com.samsung.android.sdk.iap.lib.helper.IapHelper; +import com.samsung.android.sdk.iap.lib.vo.ErrorVo; +import com.samsung.android.sdk.iap.lib.vo.PurchaseVo; + + +public abstract class BaseActivity extends Activity { + private static final String TAG = BaseActivity.class.getSimpleName(); + + protected ErrorVo mErrorVo = new ErrorVo(); + private Dialog mProgressDialog = null; + protected PurchaseVo mPurchaseVo = null; + + /** + * Helper Class between IAPService and 3rd Party Application + */ + IapHelper mIapHelper = null; + + /** + * Flag value to show successful pop-up. Error pop-up appears whenever it fails or not. + */ + protected boolean mShowErrorDialog = true; + + @Override + protected void onCreate(Bundle savedInstanceState) { + // 1. IapHelper Instance creation + // To test on development, set mode to test mode using + // use HelperDefine.OperationMode.OPERATION_MODE_TEST or + // HelperDefine.OperationMode.OPERATION_MODE_TEST_FAILURE constants. + // ==================================================================== + mIapHelper = IapHelper.getInstance(this); + // ==================================================================== + + // 2. This activity is invisible excepting progress bar as default. + // ==================================================================== + try { + Toast.makeText(this, + R.string.dream_sapps_body_authenticating_ing, + Toast.LENGTH_LONG).show(); + } catch (Exception e) { + e.printStackTrace(); + } + // ==================================================================== + + super.onCreate(savedInstanceState); + } + + public void setErrorVo(ErrorVo _errorVo) { + mErrorVo = _errorVo; + } + + public boolean checkAppsPackage(Activity _activity) { + // 1. If Galaxy Store is installed + // ==================================================================== + if (HelperUtil.isInstalledAppsPackage(this)) { + // 1) If Galaxy Store is enabled + // ================================================================ + if (!HelperUtil.isEnabledAppsPackage(this)) { + HelperUtil.showEnableGalaxyStoreDialog(_activity); + // ================================================================ + // 2) If Galaxy Store is valid + // ================================================================ + } else if (HelperUtil.isValidAppsPackage(this)) { + return true; + } else { + // Set error to notify result to third-party application + // ------------------------------------------------------------ + final String ERROR_ISSUER_IAP_CLIENT = "IC"; + final int ERROR_CODE_INVALID_GALAXY_STORE = 10002; + String errorString = String.format( + getString( + R.string.dream_ph_body_contact_p1sscustomer_servicep2ss_for_more_information_n_nerror_code_c_p3ss), + "", "", ERROR_ISSUER_IAP_CLIENT + ERROR_CODE_INVALID_GALAXY_STORE); + mErrorVo.setError(HelperDefine.IAP_PAYMENT_IS_CANCELED, errorString); + HelperUtil.showInvalidGalaxyStoreDialog(this); + } + // ================================================================ + + // ==================================================================== + // 2. If Galaxy Store is not installed + // ==================================================================== + } else { + HelperUtil.installAppsPackage(this); + } + // ==================================================================== + return false; + } + + /** + * dispose IapHelper {@link PaymentActivity} To do that, preDestory must be invoked at first in onDestory of each child activity + */ + protected void preDestory() { + // 1. Invoke dispose Method to unbind service and release inprogress flag + // ==================================================================== + if (mIapHelper != null) { + mIapHelper.dispose(); + mIapHelper = null; + } + } + + @Override + protected void onDestroy() { + // 1. dismiss ProgressDialog + // ==================================================================== + try { + if (mProgressDialog != null) { + mProgressDialog.dismiss(); + mProgressDialog = null; + } + } catch (Exception e) { + e.printStackTrace(); + } + // ==================================================================== + + super.onDestroy(); + } + + @Override + public void finish() { + super.finish(); + overridePendingTransition(0, 0); + } + + protected void finishPurchase(Intent _intent) { + // 1. If there is bundle passed from IAP + // ==================================================================== + if (_intent != null && _intent.getExtras() != null) { + Bundle extras = _intent.getExtras(); + mErrorVo.setError( + extras.getInt(HelperDefine.KEY_NAME_STATUS_CODE), + extras.getString(HelperDefine.KEY_NAME_ERROR_STRING), + extras.getString(HelperDefine.KEY_NAME_ERROR_DETAILS, "")); + + // 1) If the purchase is successful, + // ---------------------------------------------------------------- + if (mErrorVo.getErrorCode() == HelperDefine.IAP_ERROR_NONE) { + mPurchaseVo = new PurchaseVo(extras.getString( + HelperDefine.KEY_NAME_RESULT_OBJECT)); + + mErrorVo.setError( + HelperDefine.IAP_ERROR_NONE, + getString(R.string.dream_sapps_body_your_purchase_is_complete)); + + finish(); + } + // ---------------------------------------------------------------- + // 2) If the purchase is failed + // ---------------------------------------------------------------- + else { + Log.e(TAG, "finishPurchase: " + mErrorVo.dump()); + if (mShowErrorDialog) { + HelperUtil.showIapErrorDialog( + this, + getString(R.string.dream_ph_pheader_couldnt_complete_purchase), + mErrorVo.getErrorString(), + mErrorVo.getErrorDetailsString(), + new BaseDialogFragment.OnClickListener() { + @Override + public void onClick() { + finish(); + } + }, + null); + } else { + finish(); + } + } + // ---------------------------------------------------------------- + } + // ==================================================================== + // 2. If there is no bundle passed from IAP + // ==================================================================== + else { + mErrorVo.setError( + HelperDefine.IAP_ERROR_COMMON, + getString(R.string.mids_sapps_pop_unknown_error_occurred)); + + if (mShowErrorDialog) { + HelperUtil.showIapErrorDialog( + this, + getString(R.string.dream_ph_pheader_couldnt_complete_purchase), + getString(R.string.mids_sapps_pop_unknown_error_occurred), + new BaseDialogFragment.OnClickListener() { + @Override + public void onClick() { + finish(); + } + }, + null); + } else { + finish(); + } + + return; + } + // ==================================================================== + } + + protected void cancelPurchase(Intent intent) { + if (intent != null) { + Bundle extras = intent.getExtras(); + if (extras != null) { + mErrorVo.setError( + extras.getInt( + HelperDefine.KEY_NAME_STATUS_CODE, + HelperDefine.IAP_PAYMENT_IS_CANCELED), + extras.getString( + HelperDefine.KEY_NAME_ERROR_STRING, + getString(R.string.mids_sapps_pop_payment_canceled)), + extras.getString(HelperDefine.KEY_NAME_ERROR_DETAILS, "")); + finish(); + return; + } + } + + mErrorVo.setError( + HelperDefine.IAP_PAYMENT_IS_CANCELED, + getString(R.string.mids_sapps_pop_payment_canceled)); + finish(); + } +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/CheckPackageActivity.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/CheckPackageActivity.java new file mode 100644 index 000000000..e790a63d0 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/CheckPackageActivity.java @@ -0,0 +1,57 @@ +package com.samsung.android.sdk.iap.lib.activity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.helper.HelperUtil; +import com.samsung.android.sdk.iap.lib.helper.IapHelper; + +/** + * Created by sangbum7.kim on 2018-03-07. + */ + +public class CheckPackageActivity extends Activity { + private static final String TAG = CheckPackageActivity.class.getSimpleName(); + private boolean mFinishFlag = true; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mFinishFlag = true; + Intent intent = getIntent(); + if (intent != null) { + Bundle extras = intent.getExtras(); + if (extras != null) { + int DialogType = extras.getInt("DialogType"); + switch (DialogType) { + case HelperDefine.DIALOG_TYPE_INVALID_PACKAGE: { + HelperUtil.showInvalidGalaxyStoreDialog(this); + mFinishFlag = false; + } + break; + case HelperDefine.DIALOG_TYPE_DISABLE_APPLICATION: { + HelperUtil.showEnableGalaxyStoreDialog(this); + mFinishFlag = false; + } + break; + case HelperDefine.DIALOG_TYPE_APPS_DETAIL: { + HelperUtil.showUpdateGalaxyStoreDialog(this); + mFinishFlag = false; + } + break; + } + } + } + if (mFinishFlag) { + finish(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + IapHelper.getInstance(getApplicationContext()).dispose(); + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/DialogActivity.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/DialogActivity.java new file mode 100644 index 000000000..8e77cfa79 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/DialogActivity.java @@ -0,0 +1,53 @@ +package com.samsung.android.sdk.iap.lib.activity; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.text.TextUtils; + +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.dialog.BaseDialogFragment; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.helper.HelperUtil; + +/** + * Created by sangbum7.kim on 2018-03-05. + */ + +public class DialogActivity extends Activity { + private static final String TAG = DialogActivity.class.getSimpleName(); + private String mExtraString = ""; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Intent intent = getIntent(); + if (intent != null) { + Bundle extras = intent.getExtras(); + if (extras != null) { + if (HelperDefine.DIALOG_TYPE_NOTIFICATION == extras.getInt("DialogType")) { + String title = extras.getString("Title"); + String message = extras.getString("Message"); + HelperUtil.showIapErrorDialog( + this, + title, + message, + new BaseDialogFragment.OnClickListener() { + @Override + public void onClick() { + finish(); + } + }, + null); + } + } + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/PaymentActivity.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/PaymentActivity.java new file mode 100644 index 000000000..e309aa00c --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/activity/PaymentActivity.java @@ -0,0 +1,127 @@ +package com.samsung.android.sdk.iap.lib.activity; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Bundle; +import android.util.Log; +import android.widget.Toast; + +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.helper.HelperListenerManager; +import com.samsung.android.sdk.iap.lib.listener.OnPaymentListener; + +public class PaymentActivity extends BaseActivity { + private static final String TAG = PaymentActivity.class.getSimpleName(); + + private String mItemId = null; + private String mPassThroughParam = ""; + private int mMode; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + if (intent != null && intent.getExtras() != null + && intent.getExtras().containsKey("ItemId")) { + Bundle extras = intent.getExtras(); + mItemId = extras.getString("ItemId"); + mPassThroughParam = extras.getString("PassThroughParam"); + mShowErrorDialog = extras.getBoolean("ShowErrorDialog", true); + mMode = extras.getInt("OperationMode", HelperDefine.OperationMode.OPERATION_MODE_PRODUCTION.getValue()); + } else { + Toast.makeText(this, + R.string.mids_sapps_pop_an_invalid_value_has_been_provided_for_samsung_in_app_purchase, + Toast.LENGTH_LONG).show(); + + // Set error to pass result to third-party application + // ---------------------------------------------------------------- + mErrorVo.setError(HelperDefine.IAP_ERROR_COMMON, + getString(R.string.mids_sapps_pop_an_invalid_value_has_been_provided_for_samsung_in_app_purchase)); + // ---------------------------------------------------------------- + + finish(); + } + + if (checkAppsPackage(this)) { + startPaymentActivity(); + } + } + + @Override + protected void onDestroy() { + super.preDestory(); + if (isFinishing()) { + OnPaymentListener onPaymentListener = + HelperListenerManager.getInstance().getOnPaymentListener(); + HelperListenerManager.getInstance().setOnPaymentListener(null); + if (null != onPaymentListener) { + onPaymentListener.onPayment(mErrorVo, mPurchaseVo); + } + } + super.onDestroy(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + } + + @Override + protected void onActivityResult(int _requestCode, int _resultCode, Intent _intent) { + switch (_requestCode) { + case HelperDefine.REQUEST_CODE_IS_IAP_PAYMENT: { + if (_resultCode == RESULT_OK) { + finishPurchase(_intent); + } + else if (_resultCode == RESULT_CANCELED) { + Log.e(TAG, "Payment is canceled."); + cancelPurchase(_intent); + } + break; + } + case HelperDefine.REQUEST_CODE_IS_ENABLE_APPS: { + if (checkAppsPackage(this)) { + startPaymentActivity(); + } + break; + } + } + } + + private void startPaymentActivity() { + if (mIapHelper == null) { + Log.e(TAG, "Fail to get IAP Helper instance"); + return; + } + try { + Context context = this.getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString(HelperDefine.KEY_NAME_THIRD_PARTY_NAME, context.getPackageName()); + bundle.putString(HelperDefine.KEY_NAME_ITEM_ID, mItemId); + if (mPassThroughParam != null) { + bundle.putString(HelperDefine.KEY_NAME_PASSTHROUGH_ID, mPassThroughParam); + } + bundle.putInt(HelperDefine.KEY_NAME_OPERATION_MODE, mMode); + bundle.putString(HelperDefine.KEY_NAME_VERSION_CODE, HelperDefine.HELPER_VERSION); + + ComponentName com = new ComponentName(HelperDefine.GALAXY_PACKAGE_NAME, + HelperDefine.IAP_PACKAGE_NAME + ".activity.PaymentMethodListActivity"); + + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + intent.setComponent(com); + + intent.putExtras(bundle); + + if (intent.resolveActivity(context.getPackageManager()) != null) { + startActivityForResult(intent, HelperDefine.REQUEST_CODE_IS_IAP_PAYMENT); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/dialog/BaseDialogFragment.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/dialog/BaseDialogFragment.java new file mode 100644 index 000000000..8f2977cd3 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/dialog/BaseDialogFragment.java @@ -0,0 +1,213 @@ +package com.samsung.android.sdk.iap.lib.dialog; + +import android.app.ActionBar; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.text.TextUtils; +import android.text.method.LinkMovementMethod; +import android.util.Log; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.TextView; + +import com.samsung.android.sdk.iap.lib.R; + +public class BaseDialogFragment extends DialogFragment implements View.OnClickListener { + private static final String TAG = BaseDialogFragment.class.getSimpleName(); + + private int dialogWidth; + private String title; + private CharSequence message; + private String messageExtra = ""; + private String positiveBtnText; + private String negativeBtnText; + private OnClickListener positiveButtonListener = null; + private OnClickListener negativeButtonListener = null; + + public static final String IAP_DIALOG_TAG = "IAP_dialog"; + + public interface OnClickListener { + void onClick(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public void onResume() { + super.onResume(); + dialogWidth = getDialogWidth(); + getDialog().getWindow().setLayout(dialogWidth, ActionBar.LayoutParams.WRAP_CONTENT); + } + + @Override + public void onDestroyView() { + if (getDialog() != null && getRetainInstance()) { + getDialog().setDismissMessage(null); + } + super.onDestroyView(); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + View view; + if (isDarkMode()) { + view = getActivity().getLayoutInflater().inflate(R.layout.dialog_dark, null); + } else { + view = getActivity().getLayoutInflater().inflate(R.layout.dialog_light, null); + } + + ((TextView) view.findViewById(R.id.dialog_title)).setText(title); + ((TextView) view.findViewById(R.id.dialog_message)).setText(message); + ((TextView) view.findViewById(R.id.dialog_message)).setLinksClickable(true); + ((TextView) view.findViewById(R.id.dialog_message)).setMovementMethod(LinkMovementMethod.getInstance()); + + if (messageExtra == null || messageExtra.isEmpty()) { + view.findViewById(R.id.dialog_message_extra).setVisibility(View.GONE); + } else { + ((TextView) view.findViewById(R.id.dialog_message_extra)) + .setText(getString(R.string.ids_com_body_error_code_c) + " " + messageExtra); + view.findViewById(R.id.dialog_message_extra).setVisibility(View.VISIBLE); + } + + ((Button) view.findViewById(R.id.dialog_ok_btn)).setText(positiveBtnText); + view.findViewById(R.id.dialog_ok_btn).setOnClickListener(this); + + if (negativeButtonListener == null) { + view.findViewById(R.id.dialog_cancel_btn).setVisibility(View.GONE); + view.findViewById(R.id.dialog_btn_padding).setVisibility(View.GONE); + } else { + ((Button) view.findViewById(R.id.dialog_cancel_btn)).setText(negativeBtnText); + view.findViewById(R.id.dialog_cancel_btn).setVisibility(View.VISIBLE); + view.findViewById(R.id.dialog_cancel_btn).setOnClickListener(this); + view.findViewById(R.id.dialog_btn_padding).setVisibility(View.VISIBLE); + } + + Dialog dialog = new Dialog(getActivity(), R.style.Theme_DialogTransparent); + dialog.setContentView(view); + dialog.setCancelable(false); + dialog.setCanceledOnTouchOutside(false); + + dialog.getWindow().setGravity(Gravity.BOTTOM); + dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + TypedValue dimValue = new TypedValue(); + if (isDarkMode()) { + getResources().getValue(R.integer.dim_dark, dimValue, true); + } else { + getResources().getValue(R.integer.dim_light, dimValue, true); + } + dialog.getWindow().setDimAmount(dimValue.getFloat()); + + return dialog; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + dialogWidth = getDialogWidth(); + getDialog().getWindow().setLayout(dialogWidth, ActionBar.LayoutParams.WRAP_CONTENT); + } + + public BaseDialogFragment setDialogTitle(String _title) { + if (!TextUtils.isEmpty(_title)) { + this.title = _title; + } + return this; + } + + public BaseDialogFragment setDialogMessageText(CharSequence _message) { + if (!TextUtils.isEmpty(_message)) { + this.message = _message; + } + return this; + } + + public BaseDialogFragment setDialogMessageExtra(String _extra) { + if (!TextUtils.isEmpty(_extra)) { + this.messageExtra = _extra; + } + return this; + } + + public BaseDialogFragment setDialogPositiveButton(String _positiveBtnText, final OnClickListener listener) { + if (!TextUtils.isEmpty(_positiveBtnText)) { + positiveBtnText = _positiveBtnText; + } else { + positiveBtnText = (String) getText(android.R.string.ok); + } + if (listener != null) { + positiveButtonListener = listener; + } + return this; + } + + public BaseDialogFragment setDialogNegativeButton(String _negativeBtnText, final OnClickListener listener) { + if (!TextUtils.isEmpty(_negativeBtnText)) { + negativeBtnText = _negativeBtnText; + } + if (listener != null) { + negativeButtonListener = listener; + } + return this; + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.dialog_ok_btn) { + Runnable OkBtnRunnable = new Runnable() { + @Override + public void run() { + positiveButtonListener.onClick(); + } + }; + OkBtnRunnable.run(); + } else if (v.getId() == R.id.dialog_cancel_btn) { + Runnable CancelBtnRunnable = new Runnable() { + @Override + public void run() { + negativeButtonListener.onClick(); + } + }; + CancelBtnRunnable.run(); + } + dismiss(); + } + + private int getDialogWidth() { + TypedValue outValue = new TypedValue(); + getResources().getValue(R.integer.dialog_width_percentage, outValue, true); + float ratio = outValue.getFloat(); + int width = (int) (getResources().getDisplayMetrics().widthPixels * ratio); + return width; + } + + private boolean isDarkMode() { + try { + // getContext() requires M OS or higher version + int nightModeFlags = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + nightModeFlags = getContext().getResources().getConfiguration().uiMode & + Configuration.UI_MODE_NIGHT_MASK; + } + switch (nightModeFlags) { + case Configuration.UI_MODE_NIGHT_YES: + return true; + case Configuration.UI_MODE_NIGHT_NO: + case Configuration.UI_MODE_NIGHT_UNDEFINED: + default: + return false; + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/HelperDefine.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/HelperDefine.java new file mode 100644 index 000000000..15a86549d --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/HelperDefine.java @@ -0,0 +1,192 @@ +package com.samsung.android.sdk.iap.lib.helper; + +/** + * Created by sangbum7.kim on 2017-07-17. + */ + +public class HelperDefine { + public static final String HELPER_VERSION = "6.1.0.004"; + // IAP Signature HashCode - Used to validate IAP package + // ======================================================================== + public static final int APPS_SIGNATURE_HASHCODE = 0x79998D13; + public static final int APPS_PACKAGE_VERSION = 450301000; + public static final int APPS_PACKAGE_VERSION_GO = 510130000; + public static final int APPS_PACKAGE_VERSION_INDIA = 660107000; + + // ======================================================================== + + // Name of IAP Package and Service + // ======================================================================== + public static final String GALAXY_PACKAGE_NAME = "com.sec.android.app.samsungapps"; + public static final String IAP_PACKAGE_NAME = "com.samsung.android.iap"; + public static final String IAP_SERVICE_NAME = + "com.samsung.android.iap.service.IAPService"; + // ======================================================================== + + // result code for binding to IAPService + // ======================================================================== + public static final int IAP_RESPONSE_RESULT_OK = 0; + public static final int IAP_RESPONSE_RESULT_UNAVAILABLE = 2; + // ======================================================================== + + // BUNDLE KEY + // ======================================================================== + public static final String KEY_NAME_THIRD_PARTY_NAME = "THIRD_PARTY_NAME"; + public static final String KEY_NAME_STATUS_CODE = "STATUS_CODE"; + public static final String KEY_NAME_ERROR_STRING = "ERROR_STRING"; + public static final String KEY_NAME_ERROR_DETAILS = "ERROR_DETAILS"; + public static final String KEY_NAME_ITEM_ID = "ITEM_ID"; + public static final String KEY_NAME_PASSTHROUGH_ID = "PASSTHROUGH_ID"; + public static final String KEY_NAME_RESULT_LIST = "RESULT_LIST"; + public static final String KEY_NAME_OPERATION_MODE = "OPERATION_MODE"; + public static final String KEY_NAME_RESULT_OBJECT = "RESULT_OBJECT"; + public static final String KEY_NAME_VERSION_CODE = "VERSION_CODE"; + public static final String NEXT_PAGING_INDEX = "NEXT_PAGING_INDEX"; + // ======================================================================== + + // Item Type + // ======================================================================== + public static final String PRODUCT_TYPE_ITEM = "item"; + public static final String PRODUCT_TYPE_SUBSCRIPTION = "subscription"; + public static final String PRODUCT_TYPE_ALL = "all"; + + // Define request code to IAPService. + // ======================================================================== + public static final int REQUEST_CODE_IS_IAP_PAYMENT = 1; + public static final int REQUEST_CODE_IS_ACCOUNT_CERTIFICATION = 2; + public static final int REQUEST_CODE_IS_ENABLE_APPS = 3; + // ======================================================================== + + // Define dialog type to DialogActivity + public static final int DIALOG_TYPE_NONE = 0; + public static final int DIALOG_TYPE_NOTIFICATION = 1; + public static final int DIALOG_TYPE_INVALID_PACKAGE = 2; + public static final int DIALOG_TYPE_DISABLE_APPLICATION = 3; + public static final int DIALOG_TYPE_APPS_DETAIL = 4; + + // Define request parameter to IAPService + // ======================================================================== + public static final int PASSTHROGUH_MAX_LENGTH = 255; + // ======================================================================== + + // Define status code notify to 3rd-party application + // ======================================================================== + /** + * Success + */ + final public static int IAP_ERROR_NONE = 0; + + /** + * Payment is cancelled + */ + final public static int IAP_PAYMENT_IS_CANCELED = 1; + + /** + * IAP initialization error + */ + final public static int IAP_ERROR_INITIALIZATION = -1000; + + /** + * IAP need to be upgraded + */ + final public static int IAP_ERROR_NEED_APP_UPGRADE = -1001; + + /** + * Common error + */ + final public static int IAP_ERROR_COMMON = -1002; + + /** + * Repurchase NON-CONSUMABLE item + */ + final public static int IAP_ERROR_ALREADY_PURCHASED = -1003; + + /** + * When PaymentMethodList Activity is called without Bundle data + */ + final public static int IAP_ERROR_WHILE_RUNNING = -1004; + + /** + * does not exist item or item group id + */ + final public static int IAP_ERROR_PRODUCT_DOES_NOT_EXIST = -1005; + + /** + * After purchase request not received the results can not be determined whether to buy. So, the confirmation of purchase list is needed. + */ + final public static int IAP_ERROR_CONFIRM_INBOX = -1006; + + /** + * Error when item group id does not exist + */ + public static final int IAP_ERROR_ITEM_GROUP_DOES_NOT_EXIST = -1007; + + /** + * Error when network is not available + */ + public static final int IAP_ERROR_NETWORK_NOT_AVAILABLE = -1008; + + /** + * IOException + */ + public static final int IAP_ERROR_IOEXCEPTION_ERROR = -1009; + + /** + * SocketTimeoutException + */ + public static final int IAP_ERROR_SOCKET_TIMEOUT = -1010; + + /** + * ConnectTimeoutException + */ + public static final int IAP_ERROR_CONNECT_TIMEOUT = -1011; + + /** + * The Item is not for sale in the country + */ + public static final int IAP_ERROR_NOT_EXIST_LOCAL_PRICE = -1012; + + /** + * IAP is not serviced in the country + */ + public static final int IAP_ERROR_NOT_AVAILABLE_SHOP = -1013; + + /** + * SA not logged in + */ + public static final int IAP_ERROR_NEED_SA_LOGIN = -1014; + // ======================================================================== + + /** + * initial state + */ + protected static final int STATE_TERM = 0; + + /** + * state of bound to IAPService successfully + */ + protected static final int STATE_BINDING = 1; + + /** + * state of InitIapTask successfully finished + */ + protected static final int STATE_READY = 2; + // ======================================================================== + + // IAP Operation Mode + // ======================================================================== + public enum OperationMode { + OPERATION_MODE_TEST_FAILURE(-1), + OPERATION_MODE_PRODUCTION(0), + OPERATION_MODE_TEST(1); + + final private int value; + OperationMode(int value) { + this.value = value; + } + public int getValue() { + return value; + } + } + // ======================================================================== +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/HelperListenerManager.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/HelperListenerManager.java new file mode 100644 index 000000000..f4a827f65 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/HelperListenerManager.java @@ -0,0 +1,102 @@ +package com.samsung.android.sdk.iap.lib.helper; + +import com.samsung.android.sdk.iap.lib.helper.task.ConsumePurchasedItemsTask; +import com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask; +import com.samsung.android.sdk.iap.lib.helper.task.GetProductsDetailsTask; +import com.samsung.android.sdk.iap.lib.listener.OnConsumePurchasedItemsListener; +import com.samsung.android.sdk.iap.lib.listener.OnGetOwnedListListener; +import com.samsung.android.sdk.iap.lib.listener.OnGetProductsDetailsListener; +import com.samsung.android.sdk.iap.lib.listener.OnPaymentListener; + +/** + * Created by sangbum7.kim on 2017-08-29. + */ + +public class HelperListenerManager { + private static HelperListenerManager mInstance = null; + + private OnGetProductsDetailsListener mOnGetProductsDetailsListener = null; + private OnGetOwnedListListener mOnGetOwnedListListener = null; + private OnConsumePurchasedItemsListener mOnConsumePurchasedItemsListener = null; + private OnPaymentListener mOnPaymentListener = null; + + /** + * HelperListenerManager singleton reference method + */ + public static HelperListenerManager getInstance() { + if (mInstance == null) { + mInstance = new HelperListenerManager(); + } + return mInstance; + } + + public static void destroy() { + mInstance = null; + } + + /** + * HelperListenerManager constructor + */ + private HelperListenerManager() { + mOnGetProductsDetailsListener = null; + mOnGetOwnedListListener = null; + mOnConsumePurchasedItemsListener = null; + mOnPaymentListener = null; + } + + /** + * Register {@link OnGetProductsDetailsListener} callback interface to be invoked when {@link GetProductsDetailsTask} has been finished. + * + * @param _onGetProductsDetailsListener + */ + public void setOnGetProductsDetailsListener(OnGetProductsDetailsListener _onGetProductsDetailsListener) { + mOnGetProductsDetailsListener = _onGetProductsDetailsListener; + } + + public OnGetProductsDetailsListener getOnGetProductsDetailsListener() { + return mOnGetProductsDetailsListener; + } + + + /** + * Register {@link OnGetOwnedListListener} callback interface to be invoked when {@link GetOwnedListTask} has been finished. + * + * @param _onGetOwnedListListener + */ + public void setOnGetOwnedListListener(OnGetOwnedListListener _onGetOwnedListListener) { + mOnGetOwnedListListener = _onGetOwnedListListener; + } + + public OnGetOwnedListListener getOnGetOwnedListListener() { + return mOnGetOwnedListListener; + } + + + /** + * Register {@link OnConsumePurchasedItemsListener} callback interface to be invoked when {@link ConsumePurchasedItemsTask} has been finished. + * + * @param _onConsumePurchasedItemsListener + */ + public void setOnConsumePurchasedItemsListener(OnConsumePurchasedItemsListener _onConsumePurchasedItemsListener) { + mOnConsumePurchasedItemsListener = _onConsumePurchasedItemsListener; + } + + public OnConsumePurchasedItemsListener getOnConsumePurchasedItemsListener() { + return mOnConsumePurchasedItemsListener; + } + + + /** + * Register a callback interface to be invoked when Purchase Process has been finished. + * + * @param _onPaymentListener + */ + public void setOnPaymentListener(OnPaymentListener _onPaymentListener) { + mOnPaymentListener = _onPaymentListener; + } + + + public OnPaymentListener getOnPaymentListener() { + return mOnPaymentListener; + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/HelperUtil.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/HelperUtil.java new file mode 100644 index 000000000..265ff6f50 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/HelperUtil.java @@ -0,0 +1,335 @@ +package com.samsung.android.sdk.iap.lib.helper; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.Signature; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; +import android.text.Html; +import android.util.Log; + +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.activity.BaseActivity; +import com.samsung.android.sdk.iap.lib.dialog.BaseDialogFragment; +import com.samsung.android.sdk.iap.lib.vo.ErrorVo; + +/** + * Created by sangbum7.kim on 2017-08-17. + */ + +public class HelperUtil { + private static final String TAG = HelperUtil.class.getSimpleName(); + + /** + * show a dialog + * + * @param activity The activity adding the fragment that displays a dialog + * @param title The title to display + * @param message The message to display + * @param positiveListener The listener to be invoked when the positive button of the dialog is pressed + * @param negativeListener The listener to be invoked when the negative button of the dialog is pressed + */ + public static void showIapErrorDialog( + final Activity activity, + String title, + String message, + final BaseDialogFragment.OnClickListener positiveListener, + final BaseDialogFragment.OnClickListener negativeListener) { + showIapErrorDialog(activity, title, message, "", positiveListener, negativeListener); + } + + /** + * show a dialog + * + * @param activity The activity adding the fragment that displays a dialog + * @param title The title to display + * @param message The message to display + * @param messageExtra The extra message to display + * @param positiveListener The listener to be invoked when the positive button of the dialog is pressed + * @param negativeListener The listener to be invoked when the negative button of the dialog is pressed + */ + public static void showIapErrorDialog( + final Activity activity, + String title, + String message, + String messageExtra, + final BaseDialogFragment.OnClickListener positiveListener, + final BaseDialogFragment.OnClickListener negativeListener) { + new BaseDialogFragment() + .setDialogTitle(title) + .setDialogMessageText(message) + .setDialogMessageExtra(messageExtra) + .setDialogPositiveButton(activity.getString(android.R.string.ok), positiveListener) + .setDialogNegativeButton(activity.getString(android.R.string.cancel), negativeListener) + .show(activity.getFragmentManager(), BaseDialogFragment.IAP_DIALOG_TAG); + } + + /** + * show a dialog to update the Galaxy Store + * + * @param activity The activity adding the fragment that displays a dialog + */ + public static void showUpdateGalaxyStoreDialog(final Activity activity) { + // TODO: both title and message will be changed as UX Guide + new BaseDialogFragment() + .setDialogTitle(activity.getString(R.string.dream_ph_pheader_couldnt_complete_purchase)) + .setDialogMessageText(activity.getString( + R.string.dream_ph_body_to_complete_this_purchase_you_need_to_update_the_galaxy_store)) + .setDialogPositiveButton( + activity.getString(android.R.string.ok), + new BaseDialogFragment.OnClickListener() { + @Override + public void onClick() { + goGalaxyStoreDetailPage(activity.getApplicationContext()); + activity.finish(); + } + }) + .setDialogNegativeButton( + activity.getString(android.R.string.cancel), + new BaseDialogFragment.OnClickListener() { + @Override + public void onClick() { + activity.finish(); + } + }) + .show(activity.getFragmentManager(), BaseDialogFragment.IAP_DIALOG_TAG); + } + + /** + * show a dialog to enable the Galaxy Store + * + * @param activity The activity adding the fragment that displays a dialog + */ + public static void showEnableGalaxyStoreDialog(final Activity activity) { + // TODO: both title and message will be changed as UX Guide + new BaseDialogFragment() + .setDialogTitle(activity.getString(R.string.dream_ph_pheader_couldnt_complete_purchase)) + .setDialogMessageText( + activity.getString(R.string.dream_ph_body_to_complete_this_purchase_you_need_to_enable_the_galaxy_store_in_settings)) + .setDialogPositiveButton( + activity.getString(android.R.string.ok), + new BaseDialogFragment.OnClickListener() { + @Override + public void onClick() { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + HelperDefine.GALAXY_PACKAGE_NAME)); + activity.startActivityForResult(intent, HelperDefine.REQUEST_CODE_IS_ENABLE_APPS); + + activity.finish(); + } + }) + .setDialogNegativeButton( + activity.getString(android.R.string.cancel), + new BaseDialogFragment.OnClickListener() { + @Override + public void onClick() { + activity.finish(); + } + }) + .show(activity.getFragmentManager(), BaseDialogFragment.IAP_DIALOG_TAG); + } + + /** + * show a dialog to notice that the Galaxy Store is invalid + * + * @param activity The activity adding the fragment that displays a dialog + */ + public static void showInvalidGalaxyStoreDialog(final Activity activity) { + final String ERROR_ISSUER_IAP_CLIENT = "IC"; + final int ERROR_CODE_INVALID_GALAXY_STORE = 10002; + + String source = String.format( + activity.getString( + R.string.dream_ph_body_contact_p1sscustomer_servicep2ss_for_more_information_n_nerror_code_c_p3ss), + "", "", + ERROR_ISSUER_IAP_CLIENT + ERROR_CODE_INVALID_GALAXY_STORE); + + CharSequence errorMessage; + // fromHtml(String) was deprecated in N OS + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + errorMessage = Html.fromHtml(source); + } else { + errorMessage = Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY); + } + new BaseDialogFragment() + .setDialogTitle(activity.getString(R.string.dream_ph_pheader_couldnt_complete_purchase)) + .setDialogMessageText(errorMessage) + .setDialogMessageExtra(ERROR_ISSUER_IAP_CLIENT + ERROR_CODE_INVALID_GALAXY_STORE) + .setDialogPositiveButton( + activity.getString(android.R.string.ok), + new BaseDialogFragment.OnClickListener() { + @Override + public void onClick() { + activity.finish(); + } + }) + .show(activity.getFragmentManager(), BaseDialogFragment.IAP_DIALOG_TAG); + } + + private static void goGalaxyStoreDetailPage(Context context) { + // Link of Galaxy Store for IAP install + // ------------------------------------------------------------ + Uri appsDeepLink = Uri.parse("samsungapps://StoreVersionInfo/"); + // ------------------------------------------------------------ + + Intent intent = new Intent(); + intent.setData(appsDeepLink); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | + Intent.FLAG_ACTIVITY_CLEAR_TOP | + Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + } else { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | + Intent.FLAG_ACTIVITY_CLEAR_TOP); + } + + if (intent.resolveActivity(context.getPackageManager()) != null) { + context.startActivity(intent); + } + } + + /** + * Check that Galaxy Store is installed + * + * @param _context Context + * @return If it is true Galaxy Store is installed. otherwise, not installed. + */ + static public boolean isInstalledAppsPackage(Context _context) { + PackageManager pm = _context.getPackageManager(); + try { + PackageInfo packageInfo = pm.getPackageInfo(HelperDefine.GALAXY_PACKAGE_NAME, PackageManager.GET_META_DATA); + int versionType = packageInfo.versionCode / 100000000; + Log.i(TAG, "isInstalledAppsPackage : " + packageInfo.versionCode + ", " + versionType); + switch (versionType) { + case 4: { + return packageInfo.versionCode >= HelperDefine.APPS_PACKAGE_VERSION; + } + case 5: { + return true; +// return packageInfo.versionCode >= HelperDefine.APPS_PACKAGE_VERSION_GO; + } + case 6: { + return packageInfo.versionCode >= HelperDefine.APPS_PACKAGE_VERSION_INDIA; + } + // Unverified version + default: + return true; + } + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + return false; + } + } + + static public boolean isEnabledAppsPackage(Context context) { + //// TODO: 2017-08-16 Make sure the status is normal + int status = context.getPackageManager().getApplicationEnabledSetting(HelperDefine.GALAXY_PACKAGE_NAME); + Log.i(TAG, "isEnabledAppsPackage: status " + status); + return !((status == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) || (status == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)); + } + + + /** + * check validation of installed Galaxy Store in your device + * + * @param _context + * @return If it is true Galaxy Store is valid. otherwise, is not valid. + */ + static public boolean isValidAppsPackage(Context _context) { + boolean result = true; + try { + Signature[] sigs = _context.getPackageManager().getPackageInfo( + HelperDefine.GALAXY_PACKAGE_NAME, + PackageManager.GET_SIGNATURES).signatures; + if (sigs[0].hashCode() != HelperDefine.APPS_SIGNATURE_HASHCODE) { + result = false; + } + } catch (Exception e) { + e.printStackTrace(); + result = false; + } + + return result; + } + + /** + * SamsungAccount authentication + * + * @param _activity + */ + static public boolean startAccountActivity(final Activity _activity) { + ComponentName com = new ComponentName(HelperDefine.GALAXY_PACKAGE_NAME, + HelperDefine.IAP_PACKAGE_NAME + ".activity.AccountActivity"); + Context context = _activity.getApplicationContext(); + + Intent intent = new Intent(); + intent.setComponent(com); + + if (intent.resolveActivity(context.getPackageManager()) != null) { + _activity.startActivityForResult(intent, + HelperDefine.REQUEST_CODE_IS_ACCOUNT_CERTIFICATION); + return true; + } + return false; + } + + /** + * go to about page of Galaxy Store in order to install IAP package. + */ + static public void installAppsPackage(final BaseActivity _activity) { + // Set error in order to notify result to third-party application. + // ==================================================================== + ErrorVo errorVo = new ErrorVo(); + _activity.setErrorVo(errorVo); + + errorVo.setError( + HelperDefine.IAP_PAYMENT_IS_CANCELED, + _activity.getString(R.string.mids_sapps_pop_payment_canceled)); + // ==================================================================== + + // Show information dialog + // ==================================================================== + showUpdateGalaxyStoreDialog(_activity); + // ==================================================================== + } + + static public int checkAppsPackage(Context _context) { + // 1. If Galaxy Store is installed + // ==================================================================== + if (HelperUtil.isInstalledAppsPackage(_context)) { + // 1) If Galaxy Store is enabled + // ================================================================ + if (!HelperUtil.isEnabledAppsPackage(_context)) { + return HelperDefine.DIALOG_TYPE_DISABLE_APPLICATION; + // ================================================================ + // 2) If Galaxy Store is valid + // ================================================================ + } else if (HelperUtil.isValidAppsPackage(_context)) { + return HelperDefine.DIALOG_TYPE_NONE; + } else { + // ------------------------------------------------------------ + // show alert dialog if Galaxy Store is invalid + // ------------------------------------------------------------ + return HelperDefine.DIALOG_TYPE_INVALID_PACKAGE; + // ------------------------------------------------------------ + } + // ================================================================ + + // ==================================================================== + // 2. If Galaxy Store is not installed + // ==================================================================== + } else { + // When user click the OK button on the dialog, + // go to Galaxy Store Detail page + // ==================================================================== + return HelperDefine.DIALOG_TYPE_APPS_DETAIL; + } + // ==================================================================== + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/IapHelper.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/IapHelper.java new file mode 100644 index 000000000..7e5ad8a55 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/IapHelper.java @@ -0,0 +1,642 @@ +package com.samsung.android.sdk.iap.lib.helper; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.AsyncTask.Status; +import android.os.IBinder; +import android.text.TextUtils; +import android.util.Base64; +import android.util.Log; + +import com.samsung.android.iap.IAPConnector; +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.activity.CheckPackageActivity; +import com.samsung.android.sdk.iap.lib.activity.PaymentActivity; +import com.samsung.android.sdk.iap.lib.helper.task.ConsumePurchasedItemsTask; +import com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask; +import com.samsung.android.sdk.iap.lib.helper.task.GetProductsDetailsTask; +import com.samsung.android.sdk.iap.lib.listener.OnConsumePurchasedItemsListener; +import com.samsung.android.sdk.iap.lib.listener.OnGetOwnedListListener; +import com.samsung.android.sdk.iap.lib.listener.OnGetProductsDetailsListener; +import com.samsung.android.sdk.iap.lib.listener.OnPaymentListener; +import com.samsung.android.sdk.iap.lib.service.BaseService; +import com.samsung.android.sdk.iap.lib.service.ConsumePurchasedItems; +import com.samsung.android.sdk.iap.lib.service.OwnedProduct; +import com.samsung.android.sdk.iap.lib.service.ProductsDetails; +import com.samsung.android.sdk.iap.lib.vo.ErrorVo; + +import java.util.ArrayList; + +public class IapHelper extends HelperDefine { + private static final String TAG = IapHelper.class.getSimpleName(); + + /** + * When you release a application, this Mode must be set to {@link HelperDefine.OperationMode.OPERATION_MODE_PRODUCTION} + * Please double-check this mode before release. + */ + private int mMode = HelperDefine.OperationMode.OPERATION_MODE_PRODUCTION.getValue(); + // ======================================================================== + + private Context mContext = null; + + private IAPConnector mIapConnector = null; + private ServiceConnection mServiceConn = null; + + // AsyncTask for API + // ======================================================================== + private GetProductsDetailsTask mGetProductsDetailsTask = null; + private GetOwnedListTask mGetOwnedListTask = null; + private ConsumePurchasedItemsTask mConsumePurchasedItemsTask = null; + // ======================================================================== + + private ArrayList mServiceQueue = new ArrayList(); + private BaseService mCurrentService = null; + + // API listener + private HelperListenerManager mListenerInstance = null; + + private static IapHelper mInstance = null; + + // State of IAP Service + // ======================================================================== + private int mState = HelperDefine.STATE_TERM; + private final static Object mOperationLock = new Object(); + static boolean mOperationRunningFlag = false; + private boolean mShowErrorDialog = true; + + // ######################################################################## + // ######################################################################## + // 1. SamsungIAPHeler object create and reference + // ######################################################################## + // ######################################################################## + + /** + * IapHelper constructor + * + * @param _context + */ + private IapHelper(Context _context) { + _setContextAndMode(_context); + _setListenerInstance(); + } + + /** + * IapHelper singleton reference method + * + * @param _context Context + */ + public static IapHelper getInstance(Context _context) { + Log.i(TAG, "IAP Helper version : " + HelperDefine.HELPER_VERSION); + if (null == mInstance) { + mInstance = new IapHelper(_context); + } else { + mInstance._setContextAndMode(_context); + } + + return mInstance; + } + + public void setOperationMode(OperationMode _mode) { + mMode = _mode.getValue(); + } + + private void _setContextAndMode(Context _context) { + mContext = _context.getApplicationContext(); + } + + private void _setListenerInstance() { + if (mListenerInstance != null) { + mListenerInstance.destroy(); + mListenerInstance = null; + } + mListenerInstance = HelperListenerManager.getInstance(); + } + + + // ######################################################################## + // ######################################################################## + // 2. Binding for IAPService + // ######################################################################## + // ######################################################################## + + /** + * bind to IAPService + */ + public void bindIapService() { + Log.i(TAG, "bindIapService()"); + // exit If already bound + // ==================================================================== + if (mState >= HelperDefine.STATE_BINDING) { + onBindIapFinished(HelperDefine.IAP_RESPONSE_RESULT_OK); + return; + } + // ==================================================================== + + // Connection to IAP service + // ==================================================================== + mServiceConn = new ServiceConnection() { + @Override + public void onServiceDisconnected(ComponentName _name) { + Log.i(TAG, "IAP Service Disconnected..."); + + mState = HelperDefine.STATE_TERM; + mIapConnector = null; + mServiceConn = null; + } + + @Override + public void onServiceConnected + ( + ComponentName _name, + IBinder _service + ) { + Log.i(TAG, "IAP Service Connected..."); + mIapConnector = IAPConnector.Stub.asInterface(_service); + + if (mIapConnector != null) { + mState = HelperDefine.STATE_BINDING; + onBindIapFinished(HelperDefine.IAP_RESPONSE_RESULT_OK); + } else { + mState = HelperDefine.STATE_TERM; + onBindIapFinished(HelperDefine.IAP_RESPONSE_RESULT_UNAVAILABLE); + } + } + }; + // ==================================================================== + Intent serviceIntent = new Intent(); + serviceIntent.setComponent(new ComponentName(HelperDefine.GALAXY_PACKAGE_NAME, HelperDefine.IAP_SERVICE_NAME)); + + // bind to IAPService + // ==================================================================== + try { + if (mContext == null || mContext.bindService(serviceIntent, + mServiceConn, + Context.BIND_AUTO_CREATE) == false) { + mState = HelperDefine.STATE_TERM; + onBindIapFinished(HelperDefine.IAP_RESPONSE_RESULT_UNAVAILABLE); + } + } catch (SecurityException e) { + Log.e(TAG, "SecurityException : " + e); + onBindIapFinished(HelperDefine.IAP_RESPONSE_RESULT_UNAVAILABLE); + } + // ==================================================================== + } + + + protected void onBindIapFinished(int _result) { + Log.i(TAG, "onBindIapFinished"); + if (_result == HelperDefine.IAP_RESPONSE_RESULT_OK) { + if (getServiceProcess() != null) { + getServiceProcess().runServiceProcess(); + } + } + // ============================================================ + // 2) If IAPService is not bound. + // ============================================================ + else { + if (getServiceProcess() != null) { + ErrorVo errorVo = new ErrorVo(); + errorVo.setError(HelperDefine.IAP_ERROR_INITIALIZATION, + mContext.getString(R.string.mids_sapps_pop_unknown_error_occurred) + "[Lib_Bind]"); + errorVo.setShowDialog(mShowErrorDialog); + getServiceProcess().setErrorVo(errorVo); + getServiceProcess().onEndProcess(); + } + } + } + + + /* ######################################################################## + * ######################################################################## + * 3. IAP APIs. + * ######################################################################## + * ##################################################################### */ + /////////////////////////////////////////////////////////////////////////// + // 3.1) getProductsDetails /////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + /** + *
+     * This load item list by starting productActivity in this library, and the result will be sent to {@link OnGetProductsDetailsListener} Callback
+     * interface.
+     *
+     * 
+ * + * @param _productIds + * @param _onGetProductsDetailsListener + */ + public void getProductsDetails + ( + String _productIds, + OnGetProductsDetailsListener _onGetProductsDetailsListener + ) { + try { + if (_onGetProductsDetailsListener == null) { + throw new Exception("_onGetProductsDetailsListener is null"); + } + + ProductsDetails productsDetails = new ProductsDetails(mInstance, mContext, _onGetProductsDetailsListener); + productsDetails.setProductId(_productIds); + setServiceProcess(productsDetails); + + IapStartInProgressFlag(); + checkAppsPackage(); + } catch (IapInProgressException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * execute GetProductsDetailsTask + */ + public boolean safeGetProductsDetails + ( + ProductsDetails _baseService, + String _productIDs, + boolean _showErrorDialog + ) { + try { + if (mGetProductsDetailsTask != null && + mGetProductsDetailsTask.getStatus() != Status.FINISHED) { + mGetProductsDetailsTask.cancel(true); + } + if (mIapConnector == null || mContext == null) { + return false; + } else { + mGetProductsDetailsTask = new GetProductsDetailsTask(_baseService, + mIapConnector, + mContext, + _productIDs, + _showErrorDialog, + mMode); + mGetProductsDetailsTask.execute(); + return true; + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + + /////////////////////////////////////////////////////////////////////////// + // 3.2) getOwnedList ////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + /** + *
+     * This load owned product list by starting OwnedListActivity in this library, and the result will be sent to {@link OnGetOwnedListListener}
+     * Callback interface.
+     *
+     * 
+ * + * @param _productType + * @param _onGetOwnedListListener + */ + public boolean getOwnedList + ( + String _productType, + OnGetOwnedListListener _onGetOwnedListListener + ) { + Log.i(TAG, "getOwnedList"); + try { + if (_onGetOwnedListListener == null) { + throw new Exception("_onGetOwnedListListener is null"); + } + if (TextUtils.isEmpty(_productType)) { + throw new Exception("_productType is null or empty"); + } + + OwnedProduct ownedProduct = new OwnedProduct(mInstance, mContext, _onGetOwnedListListener); + ownedProduct.setProductType(_productType); + setServiceProcess(ownedProduct); + + IapStartInProgressFlag(); + checkAppsPackage(); + } catch (IapInProgressException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + /** + * execute GetOwnedListTask + */ + public boolean safeGetOwnedList + ( + OwnedProduct _baseService, + String _productType, + boolean _showErrorDialog + ) { + try { + if (mGetOwnedListTask != null && + mGetOwnedListTask.getStatus() != Status.FINISHED) { + mGetOwnedListTask.cancel(true); + } + + if (mIapConnector == null || mContext == null) { + return false; + } else { + mGetOwnedListTask = new GetOwnedListTask(_baseService, + mIapConnector, + mContext, + _productType, + _showErrorDialog, + mMode); + + mGetOwnedListTask.execute(); + return true; + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /////////////////////////////////////////////////////////////////////////// + // 3.3) consumePurchasedItems ///////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + /** + *
+     * This load item list by starting OwnedListActivity in this library, and the result will be sent to {@link OnConsumePurchasedItemsListener}
+     * Callback interface.
+     *
+     * 
+ * + * @param _purchaseIds + * @param _onConsumePurchasedItemsListener + */ + public boolean consumePurchasedItems + ( + String _purchaseIds, + OnConsumePurchasedItemsListener _onConsumePurchasedItemsListener + ) { + try { + if (_onConsumePurchasedItemsListener == null) { + throw new Exception("_onConsumePurchasedItemsListener is null"); + } + if (TextUtils.isEmpty(_purchaseIds)) { + throw new Exception("_purchaseIds is null or empty"); + } + + ConsumePurchasedItems consumePurchasedItems = new ConsumePurchasedItems(mInstance, mContext, _onConsumePurchasedItemsListener); + consumePurchasedItems.setPurchaseIds(_purchaseIds); + setServiceProcess(consumePurchasedItems); + + IapStartInProgressFlag(); + checkAppsPackage(); + } catch (IapInProgressException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + /** + * execute ConsumePurchasedItemsTask + */ + public boolean safeConsumePurchasedItems + ( + ConsumePurchasedItems _baseService, + String _purchaseIds, + boolean _showErrorDialog + ) { + try { + if (mConsumePurchasedItemsTask != null && + mConsumePurchasedItemsTask.getStatus() != Status.FINISHED) { + mConsumePurchasedItemsTask.cancel(true); + } + + mConsumePurchasedItemsTask = new ConsumePurchasedItemsTask(_baseService, + mIapConnector, + mContext, + _purchaseIds, + _showErrorDialog, + mMode); + mConsumePurchasedItemsTask.execute(); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /////////////////////////////////////////////////////////////////////////// + // 3.4) startPurchase / /////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + /** + *
+     * Start payment process by starting {@link PaymentActivity} in this library, and result will be sent to {@link OnPaymentListener} interface. To
+     * do that, PaymentActivity must be described in AndroidManifest.xml of third-party application as below.
+     * 

+ * <activity android:name="com.sec.android.iap.lib.activity.PaymentActivity" android:theme="@style/Theme.Empty" + * android:configChanges="orientation|screenSize"/> + *

+ * + * @param _itemId + * @param _passThroughParam + * @param _onPaymentListener + */ + public boolean startPayment + ( + String _itemId, + String _passThroughParam, + OnPaymentListener _onPaymentListener + ) { + try { + if (_onPaymentListener == null) { + throw new Exception("OnPaymentListener is null"); + } + if (TextUtils.isEmpty(_itemId)) { + throw new Exception("_itemId is null or empty"); + } + if (_passThroughParam != null && _passThroughParam.getBytes("UTF-8").length > HelperDefine.PASSTHROGUH_MAX_LENGTH) { + throw new Exception("PassThroughParam length exceeded (MAX " + HelperDefine.PASSTHROGUH_MAX_LENGTH + ")"); + } + + IapStartInProgressFlag(); + mListenerInstance.setOnPaymentListener(_onPaymentListener); + + Intent intent = new Intent(mContext, PaymentActivity.class); + intent.putExtra("ItemId", _itemId); + String encodedPassThroughParam = ""; + if (_passThroughParam != null) { + encodedPassThroughParam = Base64.encodeToString(_passThroughParam.getBytes("UTF-8"), 0); + } + intent.putExtra("PassThroughParam", encodedPassThroughParam); + intent.putExtra("ShowErrorDialog", mShowErrorDialog); + intent.putExtra("OperationMode", mMode); + Log.i(TAG, "startPayment: " + mMode); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + mContext.startActivity(intent); + } catch (IapInProgressException e) { + e.printStackTrace(); + return false; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + /** + *
+     * Start payment process by starting {@link PaymentActivity} in this library, and result will be sent to {@link OnPaymentListener} interface. To
+     * do that, PaymentActivity must be described in AndroidManifest.xml of third-party application as below.
+     * 

+ * <activity android:name="com.sec.android.iap.lib.activity.PaymentActivity" android:theme="@style/Theme.Empty" + * android:configChanges="orientation|screenSize"/> + *

+ * + * @param _itemId + * @param _passThroughParam + * @param _showSuccessDialog Unused parameter. + * @param _onPaymentListener + * @deprecated + */ + public boolean startPayment + ( + String _itemId, + String _passThroughParam, + boolean _showSuccessDialog, + OnPaymentListener _onPaymentListener + ) { + return startPayment(_itemId, _passThroughParam, _onPaymentListener); + } + + // ######################################################################## + // ######################################################################## + // 4. etc + // ######################################################################## + // ######################################################################## + + /** + * Stop running task, {@link GetProductsDetailsTask}, {@link ConsumePurchasedItemsTask} or {@link GetOwnedListTask} } before dispose(). + */ + private void stopTasksIfNotFinished() { + if (mGetProductsDetailsTask != null) { + if (mGetProductsDetailsTask.getStatus() != Status.FINISHED) { + Log.e(TAG, "stopTasksIfNotFinished: mGetProductsDetailsTask Status > " + mGetProductsDetailsTask.getStatus()); + mGetProductsDetailsTask.cancel(true); + } + } + + if (mGetOwnedListTask != null) { + if (mGetOwnedListTask.getStatus() != Status.FINISHED) { + Log.e(TAG, "stopTasksIfNotFinished: mGetOwnedListTask Status > " + mGetOwnedListTask.getStatus()); + mGetOwnedListTask.cancel(true); + } + } + + if (mConsumePurchasedItemsTask != null) { + if (mConsumePurchasedItemsTask.getStatus() != Status.FINISHED) { + Log.e(TAG, "stopTasksIfNotFinished: mConsumePurchasedItemsTask Status > " + mConsumePurchasedItemsTask.getStatus()); + mConsumePurchasedItemsTask.cancel(true); + } + } + } + + /** + * Unbind from IAPService and release used resources. + */ + public void dispose() { + stopTasksIfNotFinished(); + + if (mContext != null && mServiceConn != null) { + mContext.unbindService(mServiceConn); + } + + mState = HelperDefine.STATE_TERM; + mServiceConn = null; + mIapConnector = null; + clearServiceProcess(); + IapEndInProgressFlag(); + } + + void IapStartInProgressFlag() throws IapInProgressException { + Log.i(TAG, "IapStartInProgressFlag"); + synchronized (mOperationLock) { + if (mOperationRunningFlag) { + throw new IapInProgressException("another operation is running"); + } + mOperationRunningFlag = true; + } + } + + void IapEndInProgressFlag() { + Log.i(TAG, "IapEndInProgressFlag"); + synchronized (mOperationLock) { + mOperationRunningFlag = false; + } + } + + protected static class IapInProgressException extends Exception { + public IapInProgressException(String message) { + super(message); + } + } + + void checkAppsPackage() { + int checkResult = HelperUtil.checkAppsPackage(mContext); + if (checkResult == HelperDefine.DIALOG_TYPE_NONE) { + bindIapService(); + } else { + Intent intent = new Intent(mContext, CheckPackageActivity.class); + intent.putExtra("DialogType", checkResult); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } + } + + /** + * Sets whether error popup is displayed when payment is finished. + */ + public void setShowErrorDialog(boolean _showErrorDialog) { + this.mShowErrorDialog = _showErrorDialog; + } + + public boolean getShowErrorDialog() { + return this.mShowErrorDialog; + } + + public BaseService getServiceProcess() { + return getServiceProcess(false); + } + + public BaseService getServiceProcess(boolean _nextProcess) { + if (mCurrentService == null || _nextProcess) { + mCurrentService = null; + if (mServiceQueue.size() > 0) { + mCurrentService = mServiceQueue.get(0); + mServiceQueue.remove(0); + } + } + return mCurrentService; + } + + private void setServiceProcess(BaseService _baseService) { + mServiceQueue.add(_baseService); + } + + private void clearServiceProcess() { + do { + if (mCurrentService != null) { + mCurrentService.releaseProcess(); + } + mCurrentService = getServiceProcess(true); + } while (mCurrentService != null); + mServiceQueue.clear(); + } +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/BaseTask.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/BaseTask.java new file mode 100644 index 000000000..c284cef37 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/BaseTask.java @@ -0,0 +1,65 @@ +package com.samsung.android.sdk.iap.lib.helper.task; + +import android.content.Context; +import android.os.AsyncTask; +import android.util.Log; + +import com.samsung.android.iap.IAPConnector; +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.service.BaseService; +import com.samsung.android.sdk.iap.lib.vo.ErrorVo; + +/** + * Created by sangbum7.kim on 2017-09-01. + */ + +public class BaseTask extends AsyncTask { + private static final String TAG = BaseTask.class.getSimpleName(); + + protected BaseService mBaseService; + protected IAPConnector mIapConnector; + protected Context mContext; + protected int mMode; + protected String mPackageName = ""; + + protected ErrorVo mErrorVo = new ErrorVo(); + + public BaseTask(BaseService _baseService, + IAPConnector _iapConnector, + Context _context, + boolean _showErrorDialog, + int _mode) { + + mBaseService = _baseService; + mIapConnector = _iapConnector; + mContext = _context; + if (mContext != null) { + mPackageName = mContext.getPackageName(); + } + mMode = _mode; + mErrorVo.setShowDialog(_showErrorDialog); + mBaseService.setErrorVo(mErrorVo); + } + + @Override + protected Boolean doInBackground(String... params) { + return true; + } + + @Override + protected void onPostExecute(Boolean _result) { + // ================================================================ + if (!_result) { + mErrorVo.setError(mErrorVo.getErrorCode(), mContext.getString(R.string.mids_sapps_pop_unknown_error_occurred)); + } + // ================================================================ + + mBaseService.onEndProcess(); + } + + @Override + protected void onCancelled() { + Log.e(TAG, "onCancelled: task cancelled"); + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/ConsumePurchasedItemsTask.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/ConsumePurchasedItemsTask.java new file mode 100644 index 000000000..95b7776be --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/ConsumePurchasedItemsTask.java @@ -0,0 +1,105 @@ +package com.samsung.android.sdk.iap.lib.helper.task; + +import android.content.Context; +import android.os.Bundle; +import android.util.Log; + +import com.samsung.android.iap.IAPConnector; +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.service.ConsumePurchasedItems; +import com.samsung.android.sdk.iap.lib.vo.ConsumeVo; + +import java.util.ArrayList; + +/** + * Asynchronized Task to load a list of items + */ +public class ConsumePurchasedItemsTask extends BaseTask { + private static final String TAG = GetOwnedListTask.class.getSimpleName(); + private String mPurchaseIds = ""; + + ArrayList mConsumeList = new ArrayList(); + + public ConsumePurchasedItemsTask + ( + ConsumePurchasedItems _baseService, + IAPConnector _iapConnector, + Context _context, + String _purchaseIds, + boolean _showErrorDialog, + int _mode + ) { + super(_baseService, _iapConnector, _context, _showErrorDialog, _mode); + mPurchaseIds = _purchaseIds; + + _baseService.setConsumeList(mConsumeList); + } + + @Override + protected Boolean doInBackground(String... params) { + try { + // 1) call getItemList() method of IAPService + // ============================================================ + Bundle bundle = mIapConnector.consumePurchasedItems( + mPackageName, + mPurchaseIds, + mMode); + // ============================================================ + + // 2) save status code, error string and extra String. + // ============================================================ + if (bundle != null) { + mErrorVo.setError(bundle.getInt(HelperDefine.KEY_NAME_STATUS_CODE), + bundle.getString(HelperDefine.KEY_NAME_ERROR_STRING)); + } else { + mErrorVo.setError( + HelperDefine.IAP_ERROR_COMMON, + mContext.getString( + R.string.mids_sapps_pop_unknown_error_occurred)); + } + // ============================================================ + + // 3) If item list is loaded successfully, + // make item list by Bundle data + // ============================================================ + // ============================================================ + + // 3) If item list is loaded successfully, + // make item list by Bundle data + // ============================================================ + if (mErrorVo.getErrorCode() == HelperDefine.IAP_ERROR_NONE) { + if (bundle != null) { + ArrayList consumePurchasedItemsStringList = + bundle.getStringArrayList(HelperDefine.KEY_NAME_RESULT_LIST); + + if (consumePurchasedItemsStringList != null) { + for (String consumePurchasedItemString : consumePurchasedItemsStringList) { + ConsumeVo consumeVo = new ConsumeVo(consumePurchasedItemString); + mConsumeList.add(consumeVo); + } + } else { + Log.i(TAG, "Bundle Value 'RESULT_LIST' is null."); + } + } + } + // ============================================================ + // 4) If failed, print log. + // ============================================================ + else { + Log.e(TAG, mErrorVo.getErrorString()); + } + // ============================================================ + } catch (Exception e) { + mErrorVo.setError( + HelperDefine.IAP_ERROR_COMMON, + mContext.getString( + R.string.mids_sapps_pop_unknown_error_occurred)); + + e.printStackTrace(); + return false; + } + + return true; + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/GetOwnedListTask.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/GetOwnedListTask.java new file mode 100644 index 000000000..a52b7d21d --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/GetOwnedListTask.java @@ -0,0 +1,112 @@ +package com.samsung.android.sdk.iap.lib.helper.task; + +import android.content.Context; +import android.os.Bundle; +import android.util.Log; + +import com.samsung.android.iap.IAPConnector; +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.service.OwnedProduct; +import com.samsung.android.sdk.iap.lib.vo.OwnedProductVo; + +import java.util.ArrayList; + +/** + * Asynchronized Task to load a list of items + */ +public class GetOwnedListTask extends BaseTask { + private static final String TAG = GetOwnedListTask.class.getSimpleName(); + private String mProductType = ""; + ArrayList mOwnedList = new ArrayList(); + + public GetOwnedListTask + ( + OwnedProduct _baseService, + IAPConnector _iapConnector, + Context _context, + String _productType, + boolean _showErrorDialog, + int _mode + ) { + super(_baseService, _iapConnector, _context, _showErrorDialog, _mode); + mProductType = _productType; + _baseService.setOwnedList(mOwnedList); + } + + @Override + protected Boolean doInBackground(String... params) { + Log.i(TAG, "doInBackground: start"); + try { + int pagingIndex = 1; + do { + Log.i(TAG, "doInBackground: pagingIndex = " + pagingIndex); + // 1) call getItemList() method of IAPService + // ============================================================ + Bundle bundle = mIapConnector.getOwnedList( + mPackageName, + mProductType, + pagingIndex, + mMode); + // ============================================================ + + // 2) save status code, error string and extra String. + // ============================================================ + if (bundle != null) { + mErrorVo.setError(bundle.getInt(HelperDefine.KEY_NAME_STATUS_CODE), + bundle.getString(HelperDefine.KEY_NAME_ERROR_STRING)); + } else { + mErrorVo.setError( + HelperDefine.IAP_ERROR_COMMON, + mContext.getString( + R.string.mids_sapps_pop_unknown_error_occurred)); + } + // ============================================================ + + // 3) If item list is loaded successfully, + // make item list by Bundle data + // ============================================================ + if (mErrorVo.getErrorCode() == HelperDefine.IAP_ERROR_NONE) { + if (bundle != null) { + String nextPagingIndex = bundle.getString(HelperDefine.NEXT_PAGING_INDEX); + if (nextPagingIndex != null && nextPagingIndex.length() > 0) { + pagingIndex = Integer.parseInt(nextPagingIndex); + } else { + pagingIndex = -1; + } + + ArrayList ownedProductStringList = + bundle.getStringArrayList(HelperDefine.KEY_NAME_RESULT_LIST); + + if (ownedProductStringList != null) { + for (String ownedProductString : ownedProductStringList) { + OwnedProductVo ownedPrroductVo = new OwnedProductVo(ownedProductString); + mOwnedList.add(ownedPrroductVo); + } + } else { + Log.i(TAG, "Bundle Value 'RESULT_LIST' is null."); + } + } + } + // ============================================================ + // 4) If failed, print log. + // ============================================================ + else { + Log.e(TAG, mErrorVo.getErrorString()); + return true; + } + // ============================================================ + } while (pagingIndex > 0); + } catch (Exception e) { + mErrorVo.setError( + HelperDefine.IAP_ERROR_COMMON, + mContext.getString( + R.string.mids_sapps_pop_unknown_error_occurred)); + + e.printStackTrace(); + return false; + } + + return true; + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/GetProductsDetailsTask.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/GetProductsDetailsTask.java new file mode 100644 index 000000000..65002d7b0 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/helper/task/GetProductsDetailsTask.java @@ -0,0 +1,115 @@ +package com.samsung.android.sdk.iap.lib.helper.task; + +import android.content.Context; +import android.os.Bundle; +import android.util.Log; + +import com.samsung.android.iap.IAPConnector; +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.service.ProductsDetails; +import com.samsung.android.sdk.iap.lib.vo.ProductVo; + +import java.util.ArrayList; + +/** + * Asynchronized Task to load a list of items + */ +public class GetProductsDetailsTask extends BaseTask { + private static final String TAG = GetProductsDetailsTask.class.getSimpleName(); + private String mProductIds = ""; + ArrayList mProductsDetails = new ArrayList(); + + public GetProductsDetailsTask + ( + ProductsDetails _baseService, + IAPConnector _iapConnector, + Context _context, + String _productIDs, + boolean _showErrorDialog, + int _mode + ) { + super(_baseService, _iapConnector, _context, _showErrorDialog, _mode); + mProductIds = _productIDs; + + _baseService.setProductsDetails(mProductsDetails); + } + + @Override + protected Boolean doInBackground(String... params) { + try { + int pagingIndex = 1; + do { + // 1) call getProductsDetails() method of IAPService + // ---- Order Priority ---- + // 1. if productIds is not empty, the infomations abouts products included in the productIds are returned + // 2. if productIds is empty, the infomations about all products in this package are returned on a page by page + // ============================================================ + Bundle bundle = mIapConnector.getProductsDetails( + mPackageName, + mProductIds, + pagingIndex, + mMode); + // ============================================================ + + // 2) save status code, error string and extra String. + // ============================================================ + if (bundle != null) { + mErrorVo.setError(bundle.getInt(HelperDefine.KEY_NAME_STATUS_CODE), + bundle.getString(HelperDefine.KEY_NAME_ERROR_STRING)); + } else { + mErrorVo.setError( + HelperDefine.IAP_ERROR_COMMON, + mContext.getString( + R.string.mids_sapps_pop_unknown_error_occurred)); + } + // ============================================================ + + // 3) If item list is loaded successfully, + // make item list by Bundle data + // ============================================================ + if (mErrorVo.getErrorCode() == HelperDefine.IAP_ERROR_NONE) { + if (bundle != null) { + String nextPagingIndex = bundle.getString(HelperDefine.NEXT_PAGING_INDEX); + if (nextPagingIndex != null && nextPagingIndex.length() > 0) { + pagingIndex = Integer.parseInt(nextPagingIndex); + Log.i(TAG, "PagingIndex = " + nextPagingIndex); + } else { + pagingIndex = -1; + } + + ArrayList productStringList = + bundle.getStringArrayList(HelperDefine.KEY_NAME_RESULT_LIST); + + if (productStringList != null) { + for (String productString : productStringList) { + ProductVo productVo = new ProductVo(productString); + mProductsDetails.add(productVo); + } + } else { + Log.i(TAG, "Bundle Value 'RESULT_LIST' is null."); + } + } + } + // ============================================================ + // 4) If failed, print log. + // ============================================================ + else { + Log.e(TAG, mErrorVo.getErrorString()); + return true; + } + // ============================================================ + } while (pagingIndex > 0); + } catch (Exception e) { + mErrorVo.setError( + HelperDefine.IAP_ERROR_COMMON, + mContext.getString( + R.string.mids_sapps_pop_unknown_error_occurred)); + + e.printStackTrace(); + return false; + } + + return true; + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnConsumePurchasedItemsListener.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnConsumePurchasedItemsListener.java new file mode 100644 index 000000000..4311cde1b --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnConsumePurchasedItemsListener.java @@ -0,0 +1,20 @@ +package com.samsung.android.sdk.iap.lib.listener; + +import com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask; +import com.samsung.android.sdk.iap.lib.vo.ConsumeVo; +import com.samsung.android.sdk.iap.lib.vo.ErrorVo; + +import java.util.ArrayList; + +/** + * Callback Interface used with {@link GetOwnedListTask} + */ +public interface OnConsumePurchasedItemsListener { + /** + * Callback method to be invoked when {@link GetOwnedListTask} has been finished. + * + * @param _errorVO + * @param _consumeList + */ + void onConsumePurchasedItems(ErrorVo _errorVO, ArrayList _consumeList); +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnGetOwnedListListener.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnGetOwnedListListener.java new file mode 100644 index 000000000..35d76f957 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnGetOwnedListListener.java @@ -0,0 +1,20 @@ +package com.samsung.android.sdk.iap.lib.listener; + +import com.samsung.android.sdk.iap.lib.helper.task.GetOwnedListTask; +import com.samsung.android.sdk.iap.lib.vo.ErrorVo; +import com.samsung.android.sdk.iap.lib.vo.OwnedProductVo; + +import java.util.ArrayList; + +/** + * Callback Interface used with {@link GetOwnedListTask} + */ +public interface OnGetOwnedListListener { + /** + * Callback method to be invoked when {@link GetOwnedListTask} has been finished. + * + * @param _errorVO + * @param _ownedList + */ + void onGetOwnedProducts(ErrorVo _errorVO, ArrayList _ownedList); +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnGetProductsDetailsListener.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnGetProductsDetailsListener.java new file mode 100644 index 000000000..55442b181 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnGetProductsDetailsListener.java @@ -0,0 +1,20 @@ +package com.samsung.android.sdk.iap.lib.listener; + +import com.samsung.android.sdk.iap.lib.helper.task.GetProductsDetailsTask; +import com.samsung.android.sdk.iap.lib.vo.ErrorVo; +import com.samsung.android.sdk.iap.lib.vo.ProductVo; + +import java.util.ArrayList; + +/** + * Callback Interface used with {@link GetProductsDetailsTask} + */ +public interface OnGetProductsDetailsListener { + /** + * Callback method to be invoked when {@link GetProductsDetailsTask} has been finished. + * + * @param _errorVO + * @param _productList + */ + void onGetProducts(ErrorVo _errorVO, ArrayList _productList); +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnIapBindListener.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnIapBindListener.java new file mode 100644 index 000000000..ff6ca117c --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnIapBindListener.java @@ -0,0 +1,13 @@ +package com.samsung.android.sdk.iap.lib.listener; + +/** + * Callback Interface to be invoked when bind to IAPService has been finished. + */ +public interface OnIapBindListener { + /** + * Callback method to be invoked after binding to IAP service successfully. + * + * @param result + */ + public void onBindIapFinished(int result); +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnPaymentListener.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnPaymentListener.java new file mode 100644 index 000000000..00a098365 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnPaymentListener.java @@ -0,0 +1,15 @@ +package com.samsung.android.sdk.iap.lib.listener; + +import com.samsung.android.sdk.iap.lib.vo.ErrorVo; +import com.samsung.android.sdk.iap.lib.vo.PurchaseVo; + +/** + * Callback Interface to be invoked when payment has been finished. + */ +public interface OnPaymentListener { + /** + * Callback method to be invoked when payment has been finished. There is return data for result of financial transaction whenever it was + * successful or failed. + */ + void onPayment(ErrorVo _errorVO, PurchaseVo _purchaseVO); +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnSucceedBind.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnSucceedBind.java new file mode 100644 index 000000000..3db6ffc21 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/listener/OnSucceedBind.java @@ -0,0 +1,8 @@ +package com.samsung.android.sdk.iap.lib.listener; + +/** + * Created by sangbum7.kim on 2018-02-28. + */ + +public interface OnSucceedBind { +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/BaseService.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/BaseService.java new file mode 100644 index 000000000..d6b03eb1e --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/BaseService.java @@ -0,0 +1,76 @@ +package com.samsung.android.sdk.iap.lib.service; + +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.activity.AccountActivity; +import com.samsung.android.sdk.iap.lib.activity.DialogActivity; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.helper.IapHelper; +import com.samsung.android.sdk.iap.lib.vo.ErrorVo; + +/** + * Created by sangbum7.kim on 2018-02-28. + */ + +public abstract class BaseService { + private static final String TAG = BaseService.class.getSimpleName(); + + protected ErrorVo mErrorVo = new ErrorVo(); + protected IapHelper mIapHelper = null; + protected Context mContext = null; + + public BaseService(IapHelper _iapHelper, Context _context) { + mIapHelper = _iapHelper; + mContext = _context; + mErrorVo.setError(HelperDefine.IAP_ERROR_INITIALIZATION, mContext.getString(R.string.mids_sapps_pop_unknown_error_occurred)); + } + + public ErrorVo getErrorVo() { + return mErrorVo; + } + + public void setErrorVo(ErrorVo mErrorVo) { + this.mErrorVo = mErrorVo; + } + + public abstract void runServiceProcess(); + + public void onEndProcess() { + Log.i(TAG, "BaseService.onEndProcess"); + + if (mErrorVo.getErrorCode() == HelperDefine.IAP_ERROR_NEED_SA_LOGIN) { + Intent intent = new Intent(mContext, AccountActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + return; + } else if (mErrorVo.getErrorCode() != HelperDefine.IAP_ERROR_NONE) { + if (mErrorVo.getErrorCode() != HelperDefine.IAP_ERROR_NETWORK_NOT_AVAILABLE && mErrorVo.isShowDialog()) { + Intent intent = new Intent(mContext, DialogActivity.class); + intent.putExtra("Title", mContext.getString(R.string.dream_ph_pheader_couldnt_complete_purchase)); + intent.putExtra("Message", mErrorVo.getErrorString()); + intent.putExtra("DialogType", HelperDefine.DIALOG_TYPE_NOTIFICATION); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } + } + + if (mIapHelper != null) { + BaseService baseService = mIapHelper.getServiceProcess(true); + if (baseService != null) { + baseService.runServiceProcess(); + } else { + mIapHelper.dispose(); + } + } + onReleaseProcess(); + } + + public void releaseProcess() { + onReleaseProcess(); + } + + abstract void onReleaseProcess(); +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/ConsumePurchasedItems.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/ConsumePurchasedItems.java new file mode 100644 index 000000000..3766b4a25 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/ConsumePurchasedItems.java @@ -0,0 +1,62 @@ +package com.samsung.android.sdk.iap.lib.service; + +import android.content.Context; +import android.util.Log; + +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.helper.IapHelper; +import com.samsung.android.sdk.iap.lib.listener.OnConsumePurchasedItemsListener; +import com.samsung.android.sdk.iap.lib.vo.ConsumeVo; + +import java.util.ArrayList; + +/** + * Created by sangbum7.kim on 2018-02-28. + */ + +public class ConsumePurchasedItems extends BaseService { + private static final String TAG = ConsumePurchasedItems.class.getSimpleName(); + + private OnConsumePurchasedItemsListener mOnConsumePurchasedItemsListener = null; + private static String mPurchaseIds = ""; + protected ArrayList mConsumeList = null; + + public ConsumePurchasedItems(IapHelper _iapHelper, Context _context, OnConsumePurchasedItemsListener _onConsumePurchasedItemsListener) { + super(_iapHelper, _context); + mOnConsumePurchasedItemsListener = _onConsumePurchasedItemsListener; + } + + public static void setPurchaseIds(String _purchaseIds) { + mPurchaseIds = _purchaseIds; + } + + public void setConsumeList(ArrayList _consumeList) { + this.mConsumeList = _consumeList; + } + + @Override + public void runServiceProcess() { + if (mIapHelper != null) { + if (mIapHelper.safeConsumePurchasedItems(ConsumePurchasedItems.this, + mPurchaseIds, + mIapHelper.getShowErrorDialog()) == true) { + return; + } + } + mErrorVo.setError(HelperDefine.IAP_ERROR_INITIALIZATION, mContext.getString(R.string.mids_sapps_pop_unknown_error_occurred)); + onEndProcess(); + } + + @Override + public void onReleaseProcess() { + Log.i(TAG, "ConsumePurchasedItems.onReleaseProcess"); + try { + if (mOnConsumePurchasedItemsListener != null) { + mOnConsumePurchasedItemsListener.onConsumePurchasedItems(mErrorVo, mConsumeList); + } + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/OwnedProduct.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/OwnedProduct.java new file mode 100644 index 000000000..ac3dd40f0 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/OwnedProduct.java @@ -0,0 +1,63 @@ +package com.samsung.android.sdk.iap.lib.service; + +import android.content.Context; +import android.util.Log; + +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.helper.IapHelper; +import com.samsung.android.sdk.iap.lib.listener.OnGetOwnedListListener; +import com.samsung.android.sdk.iap.lib.vo.OwnedProductVo; + +import java.util.ArrayList; + +/** + * Created by sangbum7.kim on 2018-02-28. + */ + +public class OwnedProduct extends BaseService { + private static final String TAG = OwnedProduct.class.getSimpleName(); + + private OnGetOwnedListListener mOnGetOwnedListListener = null; + private static String mProductType = ""; + protected ArrayList mOwnedList = null; + + public OwnedProduct(IapHelper _iapHelper, Context _context, OnGetOwnedListListener _onGetOwnedListListener) { + super(_iapHelper, _context); + mOnGetOwnedListListener = _onGetOwnedListListener; + } + + public static void setProductType(String _productType) { + mProductType = _productType; + } + + public void setOwnedList(ArrayList _ownedList) { + this.mOwnedList = _ownedList; + } + + @Override + public void runServiceProcess() { + Log.i(TAG, "runServiceProcess"); + if (mIapHelper != null) { + if (mIapHelper.safeGetOwnedList(OwnedProduct.this, + mProductType, + mIapHelper.getShowErrorDialog()) == true) { + return; + } + } + mErrorVo.setError(HelperDefine.IAP_ERROR_INITIALIZATION, mContext.getString(R.string.mids_sapps_pop_unknown_error_occurred)); + onEndProcess(); + } + + @Override + public void onReleaseProcess() { + Log.i(TAG, "OwnedProduct.onReleaseProcess"); + try { + if (mOnGetOwnedListListener != null) { + mOnGetOwnedListListener.onGetOwnedProducts(mErrorVo, mOwnedList); + } + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/ProductsDetails.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/ProductsDetails.java new file mode 100644 index 000000000..e0f736910 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/service/ProductsDetails.java @@ -0,0 +1,63 @@ +package com.samsung.android.sdk.iap.lib.service; + +import android.content.Context; +import android.util.Log; + +import com.samsung.android.sdk.iap.lib.R; +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; +import com.samsung.android.sdk.iap.lib.helper.IapHelper; +import com.samsung.android.sdk.iap.lib.listener.OnGetProductsDetailsListener; +import com.samsung.android.sdk.iap.lib.vo.ProductVo; + +import java.util.ArrayList; + +/** + * Created by sangbum7.kim on 2018-02-28. + */ + +public class ProductsDetails extends BaseService { + private static final String TAG = ProductsDetails.class.getSimpleName(); + + private OnGetProductsDetailsListener mOnGetProductsDetailsListener = null; + private static String mProductIds = ""; + protected ArrayList mProductsDetails = null; + + public ProductsDetails(IapHelper _iapHelper, Context _context, OnGetProductsDetailsListener _onGetProductsDetailsListener) { + super(_iapHelper, _context); + mOnGetProductsDetailsListener = _onGetProductsDetailsListener; + } + + public static void setProductId(String _productIds) { + mProductIds = _productIds; + } + + public void setProductsDetails(ArrayList _ProductsDetails) { + this.mProductsDetails = _ProductsDetails; + } + + @Override + public void runServiceProcess() { + Log.i(TAG, "succeedBind"); + if (mIapHelper != null) { + if (mIapHelper.safeGetProductsDetails(ProductsDetails.this, + mProductIds, + mIapHelper.getShowErrorDialog()) == true) { + return; + } + } + mErrorVo.setError(HelperDefine.IAP_ERROR_INITIALIZATION, mContext.getString(R.string.mids_sapps_pop_unknown_error_occurred)); + onEndProcess(); + } + + @Override + public void onReleaseProcess() { + Log.i(TAG, "OwnedProduct.onEndProcess"); + try { + if (mOnGetProductsDetailsListener != null) { + mOnGetProductsDetailsListener.onGetProducts(mErrorVo, mProductsDetails); + } + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/BaseVo.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/BaseVo.java new file mode 100644 index 000000000..76c8f39c2 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/BaseVo.java @@ -0,0 +1,146 @@ +package com.samsung.android.sdk.iap.lib.vo; + +import android.text.format.DateFormat; + +import org.json.JSONException; +import org.json.JSONObject; + +public class BaseVo { + private String mItemId; + private String mItemName; + private Double mItemPrice; + private String mItemPriceString; + private String mCurrencyUnit; + private String mCurrencyCode; + private String mItemDesc; + private String mType; + private Boolean mIsConsumable; + + public BaseVo() { + } + + public BaseVo(String _jsonString) { + try { + JSONObject jObject = new JSONObject(_jsonString); + + setItemId(jObject.optString("mItemId")); + setItemName(jObject.optString("mItemName")); + setItemPrice(jObject.optDouble("mItemPrice")); + setItemPriceString(jObject.optString("mItemPriceString")); + setCurrencyUnit(jObject.optString("mCurrencyUnit")); + setCurrencyCode(jObject.optString("mCurrencyCode")); + setItemDesc(jObject.optString("mItemDesc")); + setType(jObject.optString("mType")); + Boolean isConsumable = false; + if (jObject.optString("mConsumableYN") != null && jObject.optString("mConsumableYN").equals("Y")) { + isConsumable = true; + } + setIsConsumable(isConsumable); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public String getItemId() { + return mItemId; + } + + public void setItemId(String _itemId) { + mItemId = _itemId; + } + + public String getItemName() { + return mItemName; + } + + public void setItemName(String _itemName) { + mItemName = _itemName; + } + + public Double getItemPrice() { + return mItemPrice; + } + + public void setItemPrice(Double _itemPrice) { + mItemPrice = _itemPrice; + } + + public String getItemPriceString() { + return mItemPriceString; + } + + public void setItemPriceString(String _itemPriceString) { + mItemPriceString = _itemPriceString; + } + + public String getCurrencyUnit() { + return mCurrencyUnit; + } + + public void setCurrencyUnit(String _currencyUnit) { + mCurrencyUnit = _currencyUnit; + } + + public String getCurrencyCode() { + return mCurrencyCode; + } + + public void setCurrencyCode(String _currencyCode) { + mCurrencyCode = _currencyCode; + } + + public String getItemDesc() { + return mItemDesc; + } + + public void setItemDesc(String _itemDesc) { + mItemDesc = _itemDesc; + } + + public String getType() { + return mType; + } + + public void setType(String _itemDesc) { + mType = _itemDesc; + } + + public Boolean getIsConsumable() { + return mIsConsumable; + } + + public void setIsConsumable(Boolean _consumableYN) { + mIsConsumable = _consumableYN; + } + + + public String dump() { + String dump = null; + + dump = "ItemId : " + getItemId() + "\n" + + "ItemName : " + getItemName() + "\n" + + "ItemPrice : " + getItemPrice() + "\n" + + "ItemPriceString : " + getItemPriceString() + "\n" + + "ItemDesc : " + getItemDesc() + "\n" + + "CurrencyUnit : " + getCurrencyUnit() + "\n" + + "CurrencyCode : " + getCurrencyCode() + "\n" + + "IsConsumable : " + getIsConsumable() + "\n" + + "Type : " + getType(); + + return dump; + } + + protected String getDateString(long _timeMills) { + String result = ""; + String dateFormat = "yyyy-MM-dd HH:mm:ss"; + + try { + result = DateFormat.format(dateFormat, _timeMills).toString(); + } catch (Exception e) { + e.printStackTrace(); + result = ""; + } + + return result; + } +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/ConsumeVo.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/ConsumeVo.java new file mode 100644 index 000000000..87fef9461 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/ConsumeVo.java @@ -0,0 +1,75 @@ +package com.samsung.android.sdk.iap.lib.vo; + +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; + +public class ConsumeVo { + private static final String TAG = ConsumeVo.class.getSimpleName(); + + private String mPurchaseId; + private String mStatusString; + private int mStatusCode; + + private String mJsonString = ""; + + public ConsumeVo(String _jsonString) { + setJsonString(_jsonString); + try { + JSONObject jObject = new JSONObject(_jsonString); + + Log.i(TAG, jObject.toString(4)); + + setPurchaseId(jObject.optString("mPurchaseId")); + setStatusString(jObject.optString("mStatusString")); + setStatusCode(jObject.optInt("mStatusCode")); + } catch (JSONException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getPurchaseId() { + return mPurchaseId; + } + + public void setPurchaseId(String _paymentId) { + mPurchaseId = _paymentId; + } + + public String getStatusString() { + return mStatusString; + } + + public void setStatusString(String _statusString) { + mStatusString = _statusString; + } + + public int getStatusCode() { + return mStatusCode; + } + + public void setStatusCode(int _statusCode) { + mStatusCode = _statusCode; + } + + public String getJsonString() { + return mJsonString; + } + + public void setJsonString(String _jsonString) { + mJsonString = _jsonString; + } + + public String dump() { + String dump = null; + + dump = "PurchaseId : " + getPurchaseId() + "\n" + + "StatusString : " + getStatusString() + "\n" + + "StatusCode : " + getStatusCode(); + + return dump; + } +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/ErrorVo.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/ErrorVo.java new file mode 100644 index 000000000..8f691fe2d --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/ErrorVo.java @@ -0,0 +1,59 @@ +package com.samsung.android.sdk.iap.lib.vo; + +import com.samsung.android.sdk.iap.lib.helper.HelperDefine; + +public class ErrorVo { + private int mErrorCode = HelperDefine.IAP_PAYMENT_IS_CANCELED; + private String mErrorString = ""; + private String mErrorDetailsString = ""; + private String mExtraString = ""; + private boolean mShowDialog = false; + + public void setError(int _errorCode, String _errorString) { + mErrorCode = _errorCode; + mErrorString = _errorString; + } + + public void setError(int _errorCode, String _errorString, String _errorDetails) { + mErrorCode = _errorCode; + mErrorString = _errorString; + mErrorDetailsString = _errorDetails; + } + + public int getErrorCode() { + return mErrorCode; + } + + public String getErrorString() { + return mErrorString; + } + + public String getErrorDetailsString() { + return mErrorDetailsString; + } + + public String getExtraString() { + return mExtraString; + } + + public void setExtraString(String _extraString) { + mExtraString = _extraString; + } + + public boolean isShowDialog() { + return mShowDialog; + } + + public void setShowDialog(boolean _showDialog) { + mShowDialog = _showDialog; + } + + public String dump() { + String dump = + "ErrorCode : " + getErrorCode() + "\n" + + "ErrorString : " + getErrorString() + "\n" + + "ErrorDetailsString : " + getErrorDetailsString() + "\n" + + "ExtraString : " + getExtraString(); + return dump; + } +} diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/OwnedProductVo.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/OwnedProductVo.java new file mode 100644 index 000000000..9bb1c9c4e --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/OwnedProductVo.java @@ -0,0 +1,115 @@ +package com.samsung.android.sdk.iap.lib.vo; + +import android.util.Base64; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.UnsupportedEncodingException; + +public class OwnedProductVo extends BaseVo { + private static final String TAG = OwnedProductVo.class.getSimpleName(); + + private String mPaymentId; + private String mPurchaseId; + private String mPurchaseDate; + private String mPassThroughParam; + + // Expiration date for a item which is "subscription" type + // ======================================================================== + private String mSubscriptionEndDate = ""; + // ======================================================================== + + private String mJsonString = ""; + + public OwnedProductVo() { + } + + public OwnedProductVo(String _jsonString) { + super(_jsonString); + setJsonString(_jsonString); + + try { + JSONObject jObject = new JSONObject(_jsonString); + setPaymentId(jObject.optString("mPaymentId")); + setPurchaseId(jObject.optString("mPurchaseId")); + setPurchaseDate(getDateString(jObject.optLong("mPurchaseDate"))); + jObject.remove("mPurchaseDate"); + jObject.put("mPurchaseDate", getPurchaseDate()); + + String decodedPassThroughParam = new String(Base64.decode(jObject.optString("mPassThroughParam"), 0), "UTF-8"); + setPassThroughParam(decodedPassThroughParam); + + if (jObject.optLong("mSubscriptionEndDate") != 0) { + setSubscriptionEndDate(getDateString(jObject.optLong("mSubscriptionEndDate"))); + } + jObject.remove("mSubscriptionEndDate"); + jObject.put("mSubscriptionEndDate", getSubscriptionEndDate()); + setJsonString(jObject.toString()); + } catch (JSONException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + public String getPaymentId() { + return mPaymentId; + } + + public void setPaymentId(String _paymentId) { + mPaymentId = _paymentId; + } + + public String getPurchaseId() { + return mPurchaseId; + } + + public void setPurchaseId(String _purchaseId) { + mPurchaseId = _purchaseId; + } + + public String getPurchaseDate() { + return mPurchaseDate; + } + + public void setPurchaseDate(String _purchaseDate) { + mPurchaseDate = _purchaseDate; + } + + public String getSubscriptionEndDate() { + return mSubscriptionEndDate; + } + + public void setSubscriptionEndDate(String _subscriptionEndDate) { + mSubscriptionEndDate = _subscriptionEndDate; + } + + public String getPassThroughParam() { + return mPassThroughParam; + } + + public void setPassThroughParam(String _passThroughParam) { + mPassThroughParam = _passThroughParam; + } + + public String getJsonString() { + return mJsonString; + } + + public void setJsonString(String _jsonString) { + mJsonString = _jsonString; + } + + public String dump() { + String dump = super.dump() + "\n"; + + dump += "PaymentID : " + getPaymentId() + "\n" + + "PurchaseID : " + getPurchaseId() + "\n" + + "PurchaseDate : " + getPurchaseDate() + "\n" + + "PassThroughParam : " + getPassThroughParam() + "\n" + + "SubscriptionEndDate : " + getSubscriptionEndDate(); + + return dump; + } +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/ProductVo.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/ProductVo.java new file mode 100644 index 000000000..635056069 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/ProductVo.java @@ -0,0 +1,223 @@ +package com.samsung.android.sdk.iap.lib.vo; + +import org.json.JSONException; +import org.json.JSONObject; + +public class ProductVo extends BaseVo { + private static final String TAG = ProductVo.class.getSimpleName(); + + //Subscription data + private String mSubscriptionDurationUnit; + private String mSubscriptionDurationMultiplier; + + // Tiered Subscription data + private String mTieredPrice = ""; + private String mTieredPriceString = ""; + private String mTieredSubscriptionYN = ""; + private String mTieredSubscriptionDurationUnit = ""; + private String mTieredSubscriptionDurationMultiplier = ""; + private String mTieredSubscriptionCount = ""; + private String mShowStartDate = ""; + private String mShowEndDate = ""; + + private String mItemImageUrl; + private String mItemDownloadUrl; + private String mReserved1; + private String mReserved2; + private String mFreeTrialPeriod; + + private String mJsonString; + + public ProductVo() { + } + + public ProductVo(String _jsonString) { + super(_jsonString); + setJsonString(_jsonString); + + try { + JSONObject jObject = new JSONObject(_jsonString); + + setSubscriptionDurationUnit(jObject.optString("mSubscriptionDurationUnit")); + setSubscriptionDurationMultiplier(jObject.optString("mSubscriptionDurationMultiplier")); + + setTieredSubscriptionYN(jObject.optString("mTieredSubscriptionYN")); + setTieredSubscriptionDurationUnit(jObject.optString("mTieredSubscriptionDurationUnit")); + setTieredSubscriptionDurationMultiplier(jObject.optString("mTieredSubscriptionDurationMultiplier")); + setTieredSubscriptionCount(jObject.optString("mTieredSubscriptionCount")); + setTieredPrice(jObject.optString("mTieredPrice")); + setTieredPriceString(jObject.optString("mTieredPriceString")); + setShowStartDate(getDateString(jObject.optLong("mShowStartDate"))); + setShowEndDate(getDateString(jObject.optLong("mShowEndDate"))); + + setItemImageUrl(jObject.optString("mItemImageUrl")); + setItemDownloadUrl(jObject.optString("mItemDownloadUrl")); + setReserved1(jObject.optString("mReserved1")); + setReserved2(jObject.optString("mReserved2")); + setFreeTrialPeriod(jObject.optString("mFreeTrialPeriod")); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public String getSubscriptionDurationUnit() { + return mSubscriptionDurationUnit; + } + + public void setSubscriptionDurationUnit(String _subscriptionDurationUnit) { + mSubscriptionDurationUnit = _subscriptionDurationUnit; + } + + public String getSubscriptionDurationMultiplier() { + return mSubscriptionDurationMultiplier; + } + + public void setSubscriptionDurationMultiplier( + String _subscriptionDurationMultiplier) { + mSubscriptionDurationMultiplier = _subscriptionDurationMultiplier; + } + + public String getTieredSubscriptionYN() { + return mTieredSubscriptionYN; + } + + public void setTieredSubscriptionYN(String _tieredSubscriptionYN) { + this.mTieredSubscriptionYN = _tieredSubscriptionYN; + } + + public String getTieredPrice() { + return mTieredPrice; + } + + public void setTieredPrice(String _tieredPrice) { + this.mTieredPrice = _tieredPrice; + } + + public String getTieredPriceString() { + return mTieredPriceString; + } + + public void setTieredPriceString(String _tieredPriceString) { + this.mTieredPriceString = _tieredPriceString; + } + + public String getTieredSubscriptionDurationUnit() { + return mTieredSubscriptionDurationUnit; + } + + public void setTieredSubscriptionDurationUnit(String _tieredSubscriptionDurationUnit) { + this.mTieredSubscriptionDurationUnit = _tieredSubscriptionDurationUnit; + } + + public String getTieredSubscriptionDurationMultiplier() { + return mTieredSubscriptionDurationMultiplier; + } + + public void setTieredSubscriptionDurationMultiplier(String _tieredSubscriptionDurationMultiplier) { + this.mTieredSubscriptionDurationMultiplier = _tieredSubscriptionDurationMultiplier; + } + + public String getTieredSubscriptionCount() { + return mTieredSubscriptionCount; + } + + public void setTieredSubscriptionCount(String _tieredSubscriptionCount) { + this.mTieredSubscriptionCount = _tieredSubscriptionCount; + } + + public String getShowStartDate() { + return mShowStartDate; + } + + public void setShowStartDate(String showStartDate) { + this.mShowStartDate = showStartDate; + } + + public String getShowEndDate() { + return mShowEndDate; + } + + public void setShowEndDate(String showEndDate) { + this.mShowEndDate = showEndDate; + } + + public String getItemImageUrl() { + return mItemImageUrl; + } + + public void setItemImageUrl(String _itemImageUrl) { + mItemImageUrl = _itemImageUrl; + } + + public String getItemDownloadUrl() { + return mItemDownloadUrl; + } + + public void setItemDownloadUrl(String _itemDownloadUrl) { + mItemDownloadUrl = _itemDownloadUrl; + } + + public String getReserved1() { + return mReserved1; + } + + public void setReserved1(String _reserved1) { + mReserved1 = _reserved1; + } + + public String getReserved2() { + return mReserved2; + } + + public void setReserved2(String _reserved2) { + mReserved2 = _reserved2; + } + + public String getFreeTrialPeriod() { + return mFreeTrialPeriod; + } + + public void setFreeTrialPeriod(String _freeTrialPeriod) { + mFreeTrialPeriod = _freeTrialPeriod; + } + + public String getJsonString() { + return mJsonString; + } + + public void setJsonString(String _jsonString) { + mJsonString = _jsonString; + } + + public String tieredDump() { + String dump = ""; + if (getTieredSubscriptionYN().equals("Y") == true) { + dump = "TieredSubscriptionYN : " + getTieredSubscriptionYN() + "\n" + + "TieredPrice : " + getTieredPrice() + "\n" + + "TieredPriceString : " + getTieredPriceString() + "\n" + + "TieredSubscriptionCount : " + getTieredSubscriptionCount() + "\n" + + "TieredSubscriptionDurationUnit : " + getTieredSubscriptionDurationUnit() + "\n" + + "TieredSubscriptionDurationMultiplier : " + getTieredSubscriptionDurationMultiplier() + "\n" + + "ShowStartDate : " + getShowStartDate() + "\n" + + "ShowEndDate : " + getShowEndDate(); + + } + return dump; + } + + public String dump() { + String dump = super.dump() + "\n"; + + dump += "SubscriptionDurationUnit : " + + getSubscriptionDurationUnit() + "\n" + + "SubscriptionDurationMultiplier : " + + getSubscriptionDurationMultiplier() + "\n" + + "ItemImageUrl : " + getItemImageUrl() + "\n" + + "ItemDownloadUrl : " + getItemDownloadUrl() + "\n" + + "Reserved1 : " + getReserved1() + "\n" + + "Reserved2 : " + getReserved2() + "\n" + + "FreeTrialPeriod : " + getFreeTrialPeriod() + "\n" + + tieredDump(); + return dump; + } +} \ No newline at end of file diff --git a/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/PurchaseVo.java b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/PurchaseVo.java new file mode 100644 index 000000000..9181cbbf5 --- /dev/null +++ b/IAP6Helper/src/main/java/com/samsung/android/sdk/iap/lib/vo/PurchaseVo.java @@ -0,0 +1,172 @@ +package com.samsung.android.sdk.iap.lib.vo; + +import android.util.Base64; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.UnsupportedEncodingException; + +public class PurchaseVo extends BaseVo { + private static final String TAG = PurchaseVo.class.getSimpleName(); + + private String mPaymentId; + private String mPurchaseId; + private String mPurchaseDate; + private String mVerifyUrl; + private String mPassThroughParam; + + private String mItemImageUrl; + private String mItemDownloadUrl; + private String mReserved1; + private String mReserved2; + private String mOrderId; + private String mUdpSignature; + + private String mJsonString; + + public PurchaseVo(String _jsonString) { + super(_jsonString); + setJsonString(_jsonString); + + try { + JSONObject jObject = new JSONObject(_jsonString); + + setPaymentId(jObject.optString("mPaymentId")); + setPurchaseId(jObject.optString("mPurchaseId")); + setPurchaseDate(getDateString(jObject.optLong("mPurchaseDate"))); + jObject.remove("mPurchaseDate"); + jObject.put("mPurchaseDate", getPurchaseDate()); + String decodedPassThroughParam = new String(Base64.decode(jObject.optString("mPassThroughParam"), 0), "UTF-8"); + setPassThroughParam(decodedPassThroughParam); + + setItemImageUrl(jObject.optString("mItemImageUrl")); + setItemDownloadUrl(jObject.optString("mItemDownloadUrl")); + setReserved1(jObject.optString("mReserved1")); + setReserved2(jObject.optString("mReserved2")); + setOrderId(jObject.optString("mOrderId")); + + setVerifyUrl(jObject.optString("mVerifyUrl")); + setUdpSignature(jObject.optString("mUdpSignature")); + + setJsonString(jObject.toString()); + } catch (JSONException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + public String getPaymentId() { + return mPaymentId; + } + + public void setPaymentId(String _paymentId) { + mPaymentId = _paymentId; + } + + public String getPurchaseId() { + return mPurchaseId; + } + + public void setPurchaseId(String _purchaseId) { + mPurchaseId = _purchaseId; + } + + public String getPurchaseDate() { + return mPurchaseDate; + } + + public void setPurchaseDate(String _purchaseDate) { + mPurchaseDate = _purchaseDate; + } + + public String getVerifyUrl() { + return mVerifyUrl; + } + + public void setVerifyUrl(String _verifyUrl) { + mVerifyUrl = _verifyUrl; + } + + public String getPassThroughParam() { + return mPassThroughParam; + } + + public void setPassThroughParam(String _passThroughParam) { + mPassThroughParam = _passThroughParam; + } + + public String getItemImageUrl() { + return mItemImageUrl; + } + + public void setItemImageUrl(String _itemImageUrl) { + mItemImageUrl = _itemImageUrl; + } + + public String getItemDownloadUrl() { + return mItemDownloadUrl; + } + + public void setItemDownloadUrl(String _itemDownloadUrl) { + mItemDownloadUrl = _itemDownloadUrl; + } + + public String getReserved1() { + return mReserved1; + } + + public void setReserved1(String _reserved1) { + mReserved1 = _reserved1; + } + + public String getReserved2() { + return mReserved2; + } + + public void setReserved2(String _reserved2) { + mReserved2 = _reserved2; + } + + public String getOrderId() { + return mOrderId; + } + + public void setOrderId(String orderId) { + this.mOrderId = orderId; + } + + public String getUdpSignature() { + return mUdpSignature; + } + + public void setUdpSignature(String udpSignature) { + this.mUdpSignature = udpSignature; + } + + public String getJsonString() { + return mJsonString; + } + + public void setJsonString(String _jsonString) { + mJsonString = _jsonString; + } + + public String dump() { + String dump = super.dump() + "\n"; + + dump += "PaymentID : " + getPaymentId() + "\n" + + "PurchaseId : " + getPurchaseId() + "\n" + + "PurchaseDate : " + getPurchaseDate() + "\n" + + "PassThroughParam : " + getPassThroughParam() + "\n" + + "VerifyUrl : " + getVerifyUrl() + "\n" + + "ItemImageUrl : " + getItemImageUrl() + "\n" + + "ItemDownloadUrl : " + getItemDownloadUrl() + "\n" + + "Reserved1 : " + getReserved1() + "\n" + + "Reserved2 : " + getReserved2() + "\n" + + "UdpSignature : " + getUdpSignature(); + + return dump; + } +} \ No newline at end of file diff --git a/IAP6Helper/src/main/res/color/dialog_button_text_color.xml b/IAP6Helper/src/main/res/color/dialog_button_text_color.xml new file mode 100644 index 000000000..a2bed714a --- /dev/null +++ b/IAP6Helper/src/main/res/color/dialog_button_text_color.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/IAP6Helper/src/main/res/drawable-hdpi/tw_widget_progressbar_effect_holo_light.png b/IAP6Helper/src/main/res/drawable-hdpi/tw_widget_progressbar_effect_holo_light.png new file mode 100644 index 000000000..f8e90af62 Binary files /dev/null and b/IAP6Helper/src/main/res/drawable-hdpi/tw_widget_progressbar_effect_holo_light.png differ diff --git a/IAP6Helper/src/main/res/drawable-hdpi/tw_widget_progressbar_holo_light.png b/IAP6Helper/src/main/res/drawable-hdpi/tw_widget_progressbar_holo_light.png new file mode 100644 index 000000000..981e8980a Binary files /dev/null and b/IAP6Helper/src/main/res/drawable-hdpi/tw_widget_progressbar_holo_light.png differ diff --git a/IAP6Helper/src/main/res/drawable-mdpi/tw_widget_progressbar_effect_holo_light.png b/IAP6Helper/src/main/res/drawable-mdpi/tw_widget_progressbar_effect_holo_light.png new file mode 100644 index 000000000..f8e90af62 Binary files /dev/null and b/IAP6Helper/src/main/res/drawable-mdpi/tw_widget_progressbar_effect_holo_light.png differ diff --git a/IAP6Helper/src/main/res/drawable-mdpi/tw_widget_progressbar_holo_light.png b/IAP6Helper/src/main/res/drawable-mdpi/tw_widget_progressbar_holo_light.png new file mode 100644 index 000000000..981e8980a Binary files /dev/null and b/IAP6Helper/src/main/res/drawable-mdpi/tw_widget_progressbar_holo_light.png differ diff --git a/IAP6Helper/src/main/res/drawable-xhdpi/tw_widget_progressbar_effect_holo_light.png b/IAP6Helper/src/main/res/drawable-xhdpi/tw_widget_progressbar_effect_holo_light.png new file mode 100644 index 000000000..2960eb02a Binary files /dev/null and b/IAP6Helper/src/main/res/drawable-xhdpi/tw_widget_progressbar_effect_holo_light.png differ diff --git a/IAP6Helper/src/main/res/drawable-xhdpi/tw_widget_progressbar_holo_light.png b/IAP6Helper/src/main/res/drawable-xhdpi/tw_widget_progressbar_holo_light.png new file mode 100644 index 000000000..67f5018f2 Binary files /dev/null and b/IAP6Helper/src/main/res/drawable-xhdpi/tw_widget_progressbar_holo_light.png differ diff --git a/IAP6Helper/src/main/res/drawable-xxhdpi/tw_widget_progressbar_effect_holo_light.png b/IAP6Helper/src/main/res/drawable-xxhdpi/tw_widget_progressbar_effect_holo_light.png new file mode 100644 index 000000000..7e4cdecca Binary files /dev/null and b/IAP6Helper/src/main/res/drawable-xxhdpi/tw_widget_progressbar_effect_holo_light.png differ diff --git a/IAP6Helper/src/main/res/drawable-xxhdpi/tw_widget_progressbar_holo_light.png b/IAP6Helper/src/main/res/drawable-xxhdpi/tw_widget_progressbar_holo_light.png new file mode 100644 index 000000000..540d26ccf Binary files /dev/null and b/IAP6Helper/src/main/res/drawable-xxhdpi/tw_widget_progressbar_holo_light.png differ diff --git a/IAP6Helper/src/main/res/drawable/circle_60x60_dark.png b/IAP6Helper/src/main/res/drawable/circle_60x60_dark.png new file mode 100644 index 000000000..7b6235e74 Binary files /dev/null and b/IAP6Helper/src/main/res/drawable/circle_60x60_dark.png differ diff --git a/IAP6Helper/src/main/res/drawable/circle_60x60_light.png b/IAP6Helper/src/main/res/drawable/circle_60x60_light.png new file mode 100644 index 000000000..4bd0dd532 Binary files /dev/null and b/IAP6Helper/src/main/res/drawable/circle_60x60_light.png differ diff --git a/IAP6Helper/src/main/res/drawable/dialog_button_animation.xml b/IAP6Helper/src/main/res/drawable/dialog_button_animation.xml new file mode 100644 index 000000000..7ed940974 --- /dev/null +++ b/IAP6Helper/src/main/res/drawable/dialog_button_animation.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IAP6Helper/src/main/res/drawable/dialog_full_holo_light.9.png b/IAP6Helper/src/main/res/drawable/dialog_full_holo_light.9.png new file mode 100644 index 000000000..e134c41a0 Binary files /dev/null and b/IAP6Helper/src/main/res/drawable/dialog_full_holo_light.9.png differ diff --git a/IAP6Helper/src/main/res/drawable/dialog_radius_dark.xml b/IAP6Helper/src/main/res/drawable/dialog_radius_dark.xml new file mode 100644 index 000000000..9efa7d341 --- /dev/null +++ b/IAP6Helper/src/main/res/drawable/dialog_radius_dark.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/IAP6Helper/src/main/res/drawable/dialog_radius_light.xml b/IAP6Helper/src/main/res/drawable/dialog_radius_light.xml new file mode 100644 index 000000000..033283fa6 --- /dev/null +++ b/IAP6Helper/src/main/res/drawable/dialog_radius_light.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/IAP6Helper/src/main/res/drawable/progress_dialog_animation_dark.xml b/IAP6Helper/src/main/res/drawable/progress_dialog_animation_dark.xml new file mode 100644 index 000000000..b16189a7a --- /dev/null +++ b/IAP6Helper/src/main/res/drawable/progress_dialog_animation_dark.xml @@ -0,0 +1,5 @@ + + diff --git a/IAP6Helper/src/main/res/drawable/progress_dialog_animation_light.xml b/IAP6Helper/src/main/res/drawable/progress_dialog_animation_light.xml new file mode 100644 index 000000000..3279b8598 --- /dev/null +++ b/IAP6Helper/src/main/res/drawable/progress_dialog_animation_light.xml @@ -0,0 +1,5 @@ + + diff --git a/IAP6Helper/src/main/res/drawable/progressbar_middle.xml b/IAP6Helper/src/main/res/drawable/progressbar_middle.xml new file mode 100644 index 000000000..0dd4e4119 --- /dev/null +++ b/IAP6Helper/src/main/res/drawable/progressbar_middle.xml @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/IAP6Helper/src/main/res/drawable/tw_widget_progressbar_effect_holo_light.png b/IAP6Helper/src/main/res/drawable/tw_widget_progressbar_effect_holo_light.png new file mode 100644 index 000000000..f8e90af62 Binary files /dev/null and b/IAP6Helper/src/main/res/drawable/tw_widget_progressbar_effect_holo_light.png differ diff --git a/IAP6Helper/src/main/res/drawable/tw_widget_progressbar_holo_light.png b/IAP6Helper/src/main/res/drawable/tw_widget_progressbar_holo_light.png new file mode 100644 index 000000000..981e8980a Binary files /dev/null and b/IAP6Helper/src/main/res/drawable/tw_widget_progressbar_holo_light.png differ diff --git a/IAP6Helper/src/main/res/layout/dialog_dark.xml b/IAP6Helper/src/main/res/layout/dialog_dark.xml new file mode 100644 index 000000000..448730a03 --- /dev/null +++ b/IAP6Helper/src/main/res/layout/dialog_dark.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + +