Skip to content

Commit

Permalink
Merge pull request #3 from button/kleaner-kallbacks-in-kotlin
Browse files Browse the repository at this point in the history
Combine listener interface callbacks into single method
  • Loading branch information
ecgreb committed Jul 3, 2018
2 parents e6f8213 + 95ea49e commit abe5aa4
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 59 deletions.
4 changes: 3 additions & 1 deletion build.gradle
Expand Up @@ -26,7 +26,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {

ext.kotlin_version = '1.2.50'

repositories {
google()
jcenter()
Expand All @@ -37,6 +38,7 @@ buildscript {
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.8.2'
classpath 'com.dicedmelon.gradle:jacoco-android:0.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand Down
Expand Up @@ -82,7 +82,7 @@ public void trackOrder(ButtonRepository buttonRepository, DeviceManager manager,
@NonNull Order order, @Nullable final UserActivityListener listener) {
if (buttonRepository.getApplicationId() == null) {
if (listener != null) {
listener.onError(new ApplicationIdNotFoundException());
listener.onResult(new ApplicationIdNotFoundException());
}

return;
Expand All @@ -93,14 +93,14 @@ public void trackOrder(ButtonRepository buttonRepository, DeviceManager manager,
@Override
public void onTaskComplete(@Nullable Object object) {
if (listener != null) {
listener.onSuccess();
listener.onResult(null);
}
}

@Override
public void onTaskError(Throwable throwable) {
if (listener != null) {
listener.onError(throwable);
listener.onResult(throwable);
}
}
};
Expand Down Expand Up @@ -137,12 +137,12 @@ public void handlePostInstallIntent(final ButtonRepository buttonRepository,
DeviceManager deviceManager) {

if (buttonRepository.getApplicationId() == null) {
listener.onNoPostInstallIntent(new ApplicationIdNotFoundException());
listener.onResult(null, new ApplicationIdNotFoundException());
return;
}

if (deviceManager.isOldInstallation() || buttonRepository.checkedDeferredDeepLink()) {
listener.onNoPostInstallIntent(null);
listener.onResult(null, null);
return;
}

Expand All @@ -162,16 +162,16 @@ public void onTaskComplete(@Nullable PostInstallLink postInstallLink) {
setAttributionToken(buttonRepository, attribution.getBtnRef());
}

listener.onPostInstallIntent(deepLinkIntent);
listener.onResult(deepLinkIntent, null);
return;
}

listener.onNoPostInstallIntent(null);
listener.onResult(null, null);
}

@Override
public void onTaskError(Throwable throwable) {
listener.onNoPostInstallIntent(throwable);
listener.onResult(null, throwable);
}
}, deviceManager);
}
Expand Down
Expand Up @@ -26,22 +26,22 @@
package com.usebutton.merchant;

import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

/**
* Callbacks for post-install intent handler.
*/
public interface PostInstallIntentListener {

/**
* A post-install url was found. You are responsible for navigating the user
* -to the appropriate content by starting the attached intent.
*/
void onPostInstallIntent(@NonNull Intent intent);

/**
* No post-install url was found. Continue with your normal launch sequence.
* This callback is used to notify the application that the request to check for a post-app
* install deep link is complete. If a deep link was found, it will be returned here. If an
* error was encountered while making the request, it will optionally be returned here.
*
* @param intent if a post-install link was found it will be returned here in the intent data.
* The intent can be started to navigate the user to the appropriate location in the app. If no
* post-install intent was found, this param will be {@code null}.
* @param t if an error was encountered while making the request it will be returned in this
* param, otherwise {@code null}.
*/
void onNoPostInstallIntent(@Nullable Throwable t);
void onResult(@Nullable Intent intent, @Nullable Throwable t);
}
Expand Up @@ -33,7 +33,5 @@
* @see ButtonMerchant#trackOrder(android.content.Context, Order, UserActivityListener)
*/
public interface UserActivityListener {
void onSuccess();

void onError(@Nullable Throwable t);
void onResult(@Nullable Throwable t);
}
Expand Up @@ -121,7 +121,7 @@ public void trackOrder_nullApplicationId() {
buttonInternal.trackOrder(buttonRepository, mock(DeviceManager.class), mock(Order.class),
listener);

verify(listener).onError(any(ApplicationIdNotFoundException.class));
verify(listener).onResult(any(ApplicationIdNotFoundException.class));
verify(buttonRepository, never()).postUserActivity(any(DeviceManager.class),
any(Order.class),
any(Task.Listener.class));
Expand Down Expand Up @@ -160,7 +160,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable {

buttonInternal.trackOrder(buttonRepository, mock(DeviceManager.class), mock(Order.class),
listener);
verify(listener).onSuccess();
verify(listener).onResult(null);
}

@Test
Expand All @@ -184,7 +184,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable {

buttonInternal.trackOrder(buttonRepository, mock(DeviceManager.class), mock(Order.class),
listener);
verify(listener).onError(throwable);
verify(listener).onResult(throwable);
}

@Test
Expand Down Expand Up @@ -297,8 +297,7 @@ public void handlePostInstallIntent_returnValidPostInstallLink_setSourceToken()

listenerArgumentCaptor.getValue().onTaskComplete(postInstallLink);

verify(postInstallIntentListener).onPostInstallIntent(any(Intent.class));
verify(postInstallIntentListener, never()).onNoPostInstallIntent(any(Throwable.class));
verify(postInstallIntentListener).onResult(any(Intent.class), (Throwable) isNull());
verify(buttonRepository).setSourceToken("valid_source_token");
}

Expand All @@ -324,8 +323,7 @@ public void handlePostInstallIntent_returnInvalidPostInstallLink_doNotSetSourceT

listenerArgumentCaptor.getValue().onTaskComplete(postInstallLink);

verify(postInstallIntentListener, never()).onPostInstallIntent(any(Intent.class));
verify(postInstallIntentListener).onNoPostInstallIntent((Throwable) isNull());
verify(postInstallIntentListener).onResult(null, null);
verify(buttonRepository, never()).setSourceToken(anyString());
}

Expand All @@ -343,9 +341,8 @@ public void handlePostInstallIntent_nullApplicationId_throwException() {

verify(buttonRepository, never()).getPendingLink(any(Task.Listener.class),
any(DeviceManager.class));
verify(postInstallIntentListener, never()).onPostInstallIntent(any(Intent.class));
verify(buttonRepository, never()).setSourceToken(anyString());
verify(postInstallIntentListener).onNoPostInstallIntent(
verify(postInstallIntentListener).onResult((Intent) isNull(),
any(ApplicationIdNotFoundException.class));
}

Expand All @@ -368,8 +365,8 @@ public void handlePostInstallIntent_throwButtonNetworkException() {

listenerArgumentCaptor.getValue().onTaskError(new ButtonNetworkException(""));

verify(postInstallIntentListener).onNoPostInstallIntent(any(ButtonNetworkException.class));
verify(postInstallIntentListener, never()).onPostInstallIntent(any(Intent.class));
verify(postInstallIntentListener).onResult((Intent) isNull(),
any(ButtonNetworkException.class));
}

@Test
Expand Down Expand Up @@ -404,7 +401,7 @@ public void handlePostInstallIntent_oldInstallation_doNotUpdateCheckDeferredDeep
"com.usebutton.merchant",
deviceManager);

verify(postInstallIntentListener).onNoPostInstallIntent((Throwable) isNull());
verify(postInstallIntentListener).onResult(null, null);
verify(buttonRepository, never()).updateCheckDeferredDeepLink(anyBoolean());
}

Expand All @@ -422,7 +419,7 @@ public void handlePostInstallIntent_checkedDeferredDeepLink_doNotUpdateCheckDefe
"com.usebutton.merchant",
deviceManager);

verify(postInstallIntentListener).onNoPostInstallIntent((Throwable) isNull());
verify(postInstallIntentListener).onResult((Intent) isNull(), (Throwable) isNull());
verify(buttonRepository, never()).updateCheckDeferredDeepLink(anyBoolean());
}
}
}
2 changes: 2 additions & 0 deletions sample/build.gradle
Expand Up @@ -24,6 +24,7 @@
*/

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

def BUTTON_MERCHANT_API_KEY = hasProperty('buttonMerchantAppId') ? '"' + buttonMerchantAppId + '"'
: '"app-1234567890abcdef"'
Expand Down Expand Up @@ -59,6 +60,7 @@ dependencies {
implementation "com.android.support:appcompat-v7:$supportLibVersion"
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
implementation "com.android.support:design:$supportLibVersion"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation "junit:junit:$junitVersion"
androidTestImplementation "com.android.support.test:runner:$testRunnerVersion"
androidTestImplementation "com.android.support.test.espresso:espresso-core:$espressoVersion"
Expand Down
5 changes: 5 additions & 0 deletions sample/src/main/AndroidManifest.xml
Expand Up @@ -60,6 +60,11 @@
</intent-filter>
</activity>

<activity
android:name=".KotlinActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"/>

</application>

</manifest>
128 changes: 128 additions & 0 deletions sample/src/main/java/com/usebutton/merchant/sample/KotlinActivity.kt
@@ -0,0 +1,128 @@
package com.usebutton.merchant.sample

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.TextView
import android.widget.Toast
import com.usebutton.merchant.ButtonMerchant
import com.usebutton.merchant.Order.Builder
import com.usebutton.merchant.sample.R.id
import java.util.Random

class KotlinActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)

ButtonMerchant.trackIncomingIntent(this, intent)
val token = ButtonMerchant.getAttributionToken(this)
Log.d(TAG, "Attribution Token is $token")

val textView = findViewById<TextView>(R.id.attribution_token)
textView.text = ButtonMerchant.getAttributionToken(this)

checkForPostInstallIntent()
initTrackNewIntentButton()
initTackOrderButton()
initClearDataButton()
initAttributionTokenListener()
}

private fun checkForPostInstallIntent() {
ButtonMerchant.handlePostInstallIntent(this) { intent, t ->
if (intent != null) {
startActivity(intent)
} else if (t != null) {
Log.e(TAG, "Error checking post install intent", t)
}
}
}

private fun initTrackNewIntentButton() {
findViewById<View>(id.track_new_intent).setOnClickListener { v ->
val intent = Intent()
intent.data = Uri.parse(TEST_URL + Random().nextInt(100000))
ButtonMerchant.trackIncomingIntent(v.context, intent)
}
}

private fun initTackOrderButton() {
findViewById<View>(id.track_order).setOnClickListener {
val order = Builder("order-id-123")
.setAmount(8999)
.setCurrencyCode("USD")
.build()
ButtonMerchant.trackOrder(this, order) { t ->
if (t == null) {
toastify("Order track success")
} else {
toastify("Order track error")
}
}
}
}

private fun initClearDataButton() {
findViewById<View>(id.clear_all_data).setOnClickListener {
ButtonMerchant.clearAllData(this)
Log.d(TAG, "Cleared all data")

val token = ButtonMerchant.getAttributionToken(this)
Log.d(TAG, "Attribution Token is $token")

val textView = findViewById<TextView>(id.attribution_token)
textView.text = ButtonMerchant.getAttributionToken(this)
}
}

private fun initAttributionTokenListener() {
ButtonMerchant.addAttributionTokenListener(this) { token ->
runOnUiThread {
findViewById<TextView>(id.attribution_token).text = token
}
}
}

private fun toastify(message: String) {
runOnUiThread {
Toast.makeText(this@KotlinActivity, message, Toast.LENGTH_SHORT).show()
}
}

companion object {
private const val TAG = "KotlinActivity"
private const val TEST_URL = "https://sample-merchant.usebutton.com/?btn_ref=srctok-test"
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.main_menu, menu)
val kotlinItem = menu.findItem(R.id.action_switch_kotlin)
val javaItem = menu.findItem(R.id.action_switch_java)
kotlinItem.isVisible = false
javaItem.isVisible = true
return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_switch_kotlin -> {
}
R.id.action_switch_java -> {
val i = Intent(this@KotlinActivity, MainActivity::class.java)
finish()
startActivity(i)
}
}
return super.onOptionsItemSelected(item)
}
}

0 comments on commit abe5aa4

Please sign in to comment.