Skip to content

Commit 29e267e

Browse files
author
Chuck Greb
committed
Private beta 2
1 parent 0f3dff4 commit 29e267e

31 files changed

+584
-133
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ language: android
22

33
env:
44
global:
5-
- ANDROID_API_LEVEL=26
6-
- ANDROID_BUILD_TOOLS_VERSION=26.0.3
5+
- ANDROID_API_LEVEL=27
6+
- ANDROID_BUILD_TOOLS_VERSION=27.0.3
77

88
before_cache:
99
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,9 @@ git clone https://github.com/button/button-merchant-android.git
1515
cd button-merchant-android
1616
./gradlew clean installDebug
1717
```
18+
19+
In order to get the sample app to compile and run, you will need to define your Button App ID in your global or local `gradle.properties` file.
20+
21+
```groovy
22+
buttonMerchantAppId="__YOUR_APP_ID__"
23+
```

build.gradle

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ buildscript {
3232
jcenter()
3333
}
3434
dependencies {
35-
classpath 'com.android.tools.build:gradle:3.0.1'
35+
classpath 'com.android.tools.build:gradle:3.1.2'
3636
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
3737
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
3838

@@ -51,3 +51,27 @@ allprojects {
5151
task clean(type: Delete) {
5252
delete rootProject.buildDir
5353
}
54+
55+
subprojects {
56+
apply plugin: 'checkstyle'
57+
58+
task('checkstyle', type: Checkstyle) {
59+
group 'verification'
60+
configFile rootProject.file('checkstyle.xml')
61+
source 'src/main/java'
62+
ignoreFailures false
63+
showViolations true
64+
include '**/*.java'
65+
66+
classpath = files()
67+
}
68+
}
69+
70+
ext {
71+
supportLibVersion = '27.1.1'
72+
playServicesVersion = '15.0.0'
73+
junitVersion = '4.12'
74+
mockitoVersion = '2.16.0'
75+
espressoVersion = '3.0.2'
76+
testRunnerVersion = '1.0.2'
77+
}

button-merchant/build.gradle

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,19 @@ apply plugin: 'com.android.library'
2727
apply plugin: 'com.jfrog.bintray'
2828

2929
group = 'com.usebutton.merchant'
30-
version = sdkVersionName
30+
version = libraryVersionName
3131

3232
apply plugin: 'com.github.dcendents.android-maven'
3333

3434
android {
35-
compileSdkVersion 26
36-
buildToolsVersion '26.0.3'
35+
compileSdkVersion 27
36+
buildToolsVersion '27.0.3'
3737

3838
defaultConfig {
3939
minSdkVersion 15
40-
targetSdkVersion 26
40+
targetSdkVersion 27
4141
versionCode 1
42-
versionName "1.0"
42+
versionName version
4343

4444
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
4545
}
@@ -56,15 +56,6 @@ android {
5656
}
5757
}
5858

59-
ext {
60-
supportLibVersion = '26.1.0'
61-
playServicesVersion = '12.0.0'
62-
63-
junitVersion = '4.12'
64-
mockitoVersion = '2.16.0'
65-
espressoVersion = '3.0.1'
66-
}
67-
6859
dependencies {
6960
implementation fileTree(dir: 'libs', include: ['*.jar'])
7061

@@ -74,23 +65,25 @@ dependencies {
7465
testImplementation "org.mockito:mockito-core:$mockitoVersion"
7566
testImplementation 'com.squareup.okhttp3:mockwebserver:3.10.0'
7667
testImplementation 'org.json:json:20171018'
77-
androidTestImplementation 'com.android.support.test:runner:1.0.1'
68+
androidTestImplementation "com.android.support.test:runner:$testRunnerVersion"
7869
androidTestImplementation "com.android.support.test.espresso:espresso-core:$espressoVersion"
7970
androidTestImplementation "org.mockito:mockito-android:$mockitoVersion"
8071
}
8172

8273
bintray {
83-
user = project.hasProperty('bintrayUsername') ? project.property('bintrayUsername') : System.getenv('BINTRAY_USER')
84-
key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY')
74+
user = project.hasProperty('bintrayUsername') ? project.property('bintrayUsername') :
75+
System.getenv('BINTRAY_USER')
76+
key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') :
77+
System.getenv('BINTRAY_API_KEY')
8578

8679
configurations = ['archives']
8780
publish = true
88-
override = sdkVersionName.endsWith("-SNAPSHOT")
81+
override = libraryVersionName.endsWith("-SNAPSHOT")
8982

9083
pkg {
9184
repo = 'Internal'
9285
name = 'android-merchant-library'
93-
desc = "Button Merchant Library for Android v${sdkVersionName}"
86+
desc = "Button Merchant Library for Android v${libraryVersionName}"
9487
userOrg = 'button'
9588
websiteUrl = 'https://github.com/button/button-merchant-android'
9689
issueTrackerUrl = 'https://github.com/button/button-merchant-android/issues'
@@ -100,7 +93,7 @@ bintray {
10093
licenses = ['MIT']
10194

10295
version {
103-
name = sdkVersionName
96+
name = libraryVersionName
10497
}
10598
}
10699
}

button-merchant/src/main/java/com/usebutton/merchant/ButtonApiImpl.java

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,24 @@ final class ButtonApiImpl implements ButtonApi {
5656
private static final int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(15);
5757
private static final String CONTENT_TYPE_JSON = "application/json";
5858

59+
private final String userAgent;
60+
5961
@VisibleForTesting
60-
String BASE_URL = "https://api.usebutton.com";
62+
String baseUrl = "https://api.usebutton.com";
6163

6264
private static ButtonApi buttonApi;
6365

64-
static ButtonApi getInstance() {
66+
static ButtonApi getInstance(String userAgent) {
6567
if (buttonApi == null) {
66-
buttonApi = new ButtonApiImpl();
68+
buttonApi = new ButtonApiImpl(userAgent);
6769
}
6870

6971
return buttonApi;
7072
}
7173

7274
@VisibleForTesting
73-
ButtonApiImpl() {
74-
75+
ButtonApiImpl(String userAgent) {
76+
this.userAgent = userAgent;
7577
}
7678

7779
@Nullable
@@ -91,7 +93,7 @@ public PostInstallLink getPendingLink(String applicationId, String ifa,
9193
requestBody.put("signals", new JSONObject(signalsMap));
9294

9395
// setup url connection
94-
final URL url = new URL(BASE_URL + "/v1/web/deferred-deeplink");
96+
final URL url = new URL(baseUrl + "/v1/web/deferred-deeplink");
9597
urlConnection = (HttpURLConnection) url.openConnection();
9698
initializeUrlConnection(urlConnection);
9799

@@ -104,7 +106,7 @@ public PostInstallLink getPendingLink(String applicationId, String ifa,
104106
Log.d(TAG, "Request Body: " + requestBody);
105107
Log.d(TAG, "Response Code: " + urlConnection.getResponseCode());
106108
// check if it's successful
107-
if (!(urlConnection.getResponseCode() >= 400)) {
109+
if (urlConnection.getResponseCode() < 400) {
108110
// read response body
109111
final InputStream in = new BufferedInputStream(urlConnection.getInputStream());
110112
final BufferedReader reader =
@@ -131,12 +133,17 @@ public PostInstallLink getPendingLink(String applicationId, String ifa,
131133
JSONObject attributionJson = responseJson.optJSONObject("attribution");
132134
if (attributionJson != null) {
133135
String btnRef = attributionJson.getString("btn_ref");
134-
String utmSource = attributionJson.getString("utm_source");
136+
String utmSource = attributionJson.optString("utm_source", null);
135137
attribution = new PostInstallLink.Attribution(btnRef, utmSource);
136138
}
137139

138140
return new PostInstallLink(match, id, action, attribution);
139141
}
142+
} else {
143+
String message =
144+
"Unsuccessful Request. HTTP StatusCode: " + urlConnection.getResponseCode();
145+
Log.e(TAG, message);
146+
throw new ButtonNetworkException(message);
140147
}
141148
} catch (MalformedURLException e) {
142149
Log.e(TAG, "MalformedURLException has occurred", e);
@@ -195,7 +202,7 @@ public Void postActivity(String applicationId, String sourceToken, String ifa,
195202
requestBody.put("order", orderJson);
196203

197204
// setup url connection
198-
final URL url = new URL(BASE_URL + "/v2/session/useractivity");
205+
final URL url = new URL(baseUrl + "/v2/session/useractivity");
199206
urlConnection = (HttpURLConnection) url.openConnection();
200207
initializeUrlConnection(urlConnection);
201208

@@ -227,13 +234,13 @@ public Void postActivity(String applicationId, String sourceToken, String ifa,
227234
String status = responseJson.optJSONObject("meta").optString("status");
228235
if (status.equals("error")) {
229236
String error = responseJson.optJSONObject("error").optString("message");
230-
throw new ButtonNetworkException(new Exception(error));
237+
throw new ButtonNetworkException(error);
231238
}
232239
} else {
233240
String message =
234241
"Unsuccessful Request. HTTP StatusCode: " + urlConnection.getResponseCode();
235242
Log.e(TAG, message);
236-
throw new ButtonNetworkException(new Exception(message));
243+
throw new ButtonNetworkException(message);
237244
}
238245
} catch (MalformedURLException e) {
239246
Log.e(TAG, "MalformedURLException has occurred", e);
@@ -254,7 +261,6 @@ public Void postActivity(String applicationId, String sourceToken, String ifa,
254261
}
255262

256263
private String getUserAgent() {
257-
//TODO: Add User Agent
258-
return "";
264+
return userAgent;
259265
}
260266
}

button-merchant/src/main/java/com/usebutton/merchant/ButtonInternal.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ void removeAttributionTokenListener(ButtonRepository buttonRepository, @NonNull
5252

5353
void clearAllData(ButtonRepository buttonRepository);
5454

55-
void handlePostInstallIntent(ButtonRepository buttonRepository, PostInstallIntentListener listener,
56-
String packageName, DeviceManager deviceManager);
55+
void handlePostInstallIntent(ButtonRepository buttonRepository,
56+
PostInstallIntentListener listener, String packageName, DeviceManager deviceManager);
5757
}

button-merchant/src/main/java/com/usebutton/merchant/ButtonInternalImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737

3838
/**
3939
* ButtonInternalImpl class should implement everything needed for {@link ButtonMerchant}
40-
* The methods in the ButtonInternalImpl class should never be public because it will only be used by {@link ButtonMerchant}.
40+
* The methods in the ButtonInternalImpl class should never be public because it will only be used
41+
* by {@link ButtonMerchant}.
4142
*/
4243

4344
final class ButtonInternalImpl implements ButtonInternal {

button-merchant/src/main/java/com/usebutton/merchant/ButtonMerchant.java

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ public static void configure(@NonNull Context context, @NonNull String applicati
6262
/**
6363
* Checks the passed {@code Intent} for a Button attribution and if present stores the token.
6464
*
65-
* @param context a {@link Context) instance that can be used to access app resources like SharedPreferences.
65+
* @param context a {@link Context) instance that can be used to access app resources like
66+
* SharedPreferences.
6667
* @param intent An intent that has entered your app from a third party source.
6768
*/
6869
public static void trackIncomingIntent(@NonNull Context context, @NonNull Intent intent) {
@@ -82,14 +83,17 @@ public static void trackOrder(@NonNull Context context, @NonNull Order order,
8283
}
8384

8485
/**
85-
* The `attributionToken` from the last inbound Button attributed {@link Intent}.
86+
* The {@code attributionToken} from the last inbound Button attributed {@link Intent}.
8687
*
8788
* For attribution to work correctly, you must:
88-
* -Always access this token directly—*never cache it*.
89-
* -Never manage the lifecycle of this token—Button manages the token validity window server-side.
90-
* -Always include this value when reporting orders to your order API
89+
* <ul>
90+
* <li>Always access this token directly—*never cache it*.</li>
91+
* <li>Never manage the lifecycle of this token—Button manages the token validity window
92+
* server-side.</li>
93+
* <li>Always include this value when reporting orders to your order API.</li>
94+
* </ul>
9195
*
92-
* @return the last tracked Button attribution token.
96+
* @return the last tracked Button attribution token.
9397
**/
9498
@Nullable
9599
public static String getAttributionToken(@NonNull Context context) {
@@ -130,15 +134,17 @@ public static void clearAllData(@NonNull Context context) {
130134
/**
131135
* Checks to see if the user visited a url prior to installing your app.
132136
*
133-
* If a url is found, {@link PostInstallIntentListener#onPostInstallIntent(Intent)} will be called on the listener you passed and you
134-
* are responsible for navigating the user to the relevant content in your app. If a url is not found
135-
* or an error occurs, {@link PostInstallIntentListener#onNoPostInstallIntent(Throwable)} will be called on your listener and you can continue
136-
* with your normal launch sequence.
137+
* If a url is found, {@link PostInstallIntentListener#onPostInstallIntent(Intent)} will be
138+
* called on the listener you passed and you are responsible for navigating the user to the
139+
* relevant content in your app. If a url is not found or an error occurs,
140+
* {@link PostInstallIntentListener#onNoPostInstallIntent(Throwable)} will be called on your
141+
* listener and you can continue with your normal launch sequence.
137142
*
138-
* This method checks for a post-install url exactly *one time* after a user has installed your app.
139-
* Subsequent calls will result in a call to {@link PostInstallIntentListener#onNoPostInstallIntent(Throwable)} on your listener. You do not need to wait
140-
* for the listener before continuing with your normal launch sequence but you should be prepared to handle
141-
* an intent if a post-install url is found.
143+
* This method checks for a post-install url exactly *one time* after a user has installed your
144+
* app. Subsequent calls will result in a call to
145+
* {@link PostInstallIntentListener#onNoPostInstallIntent(Throwable)} on your listener. You do
146+
* not need to wait for the listener before continuing with your normal launch sequence but you
147+
* should be prepared to handle an intent if a post-install url is found.
142148
*
143149
* @param context context
144150
* @param listener The listener for be notified when a post install url is found.
@@ -152,7 +158,10 @@ public static void handlePostInstallIntent(@NonNull Context context, @NonNull
152158
private static ButtonRepository getButtonRepository(Context context) {
153159
PersistenceManager persistenceManager =
154160
PersistenceManagerImpl.getInstance(context.getApplicationContext());
155-
ButtonApi buttonApi = ButtonApiImpl.getInstance();
161+
162+
DeviceManager deviceManager = getDeviceManager(context);
163+
164+
ButtonApi buttonApi = ButtonApiImpl.getInstance(deviceManager.getUserAgent());
156165

157166
return ButtonRepositoryImpl.getInstance(buttonApi, persistenceManager, executorService);
158167
}

button-merchant/src/main/java/com/usebutton/merchant/DeviceManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,6 @@ interface DeviceManager {
5050
* @return true if the app was installed more than 12 hours ago.
5151
*/
5252
boolean isOldInstallation();
53+
54+
String getUserAgent();
5355
}

0 commit comments

Comments
 (0)