Skip to content
This repository was archived by the owner on Jan 12, 2019. It is now read-only.

Commit ed89cf2

Browse files
committed
Release 5.5.0
1 parent ca36426 commit ed89cf2

File tree

23 files changed

+858
-162
lines changed

23 files changed

+858
-162
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
card.io Android SDK change log and release notes
22
================================================
33

4+
5.5.0
5+
-----
6+
* Update Gradle build plugin to 2.2.3.
7+
* Update compile and target SDK versions to 25.
8+
* Update NDK to r13b.
9+
* Increase `minSdkVersion` to 16.
10+
* Upgrade OpenCV to 2.4.13.
11+
412
5.4.2
513
-----
614
* Add Mastercard 2-series support.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ All releases follow [semantic versioning](http://semver.org/).
1313

1414
The latest version is available via `mavenCentral()`. Just add the following dependency:
1515

16-
```gradle
17-
compile 'io.card:android-sdk:5.4.2'
16+
```
17+
compile 'io.card:android-sdk:5.5.0'
1818
```
1919

2020
You can receive updates about new versions via a few different channels:
@@ -45,8 +45,8 @@ A manual entry fallback mode is provided for devices that do not meet these requ
4545

4646
##### If you use gradle, then add the following dependency from `mavenCentral()`:
4747

48-
```gradle
49-
compile 'io.card:android-sdk:5.4.2'
48+
```
49+
compile 'io.card:android-sdk:5.5.0'
5050
```
5151

5252
##### If you use something other than gradle, then:

SampleApp/build.gradle

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,31 @@ buildscript {
33
jcenter()
44
}
55
dependencies {
6-
classpath 'com.android.tools.build:gradle:2.2.0'
6+
classpath 'com.android.tools.build:gradle:2.2.3'
77
}
88
}
99

1010
repositories {
1111
jcenter()
12+
maven {
13+
url "https://jitpack.io"
14+
}
1215
}
1316

1417
apply plugin: 'com.android.application'
1518

1619
android {
17-
compileSdkVersion 24
18-
buildToolsVersion "24.0.1"
20+
compileSdkVersion 25
21+
buildToolsVersion "25.0.0"
22+
23+
defaultConfig {
24+
applicationId "io.card.development"
25+
minSdkVersion 18
26+
targetSdkVersion 25
27+
versionCode 1
28+
versionName "1.0.0"
29+
testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
30+
}
1931

2032
signingConfigs {
2133
myConfig {
@@ -27,10 +39,6 @@ android {
2739
}
2840

2941
buildTypes {
30-
debug {
31-
applicationIdSuffix ".debug"
32-
}
33-
3442
release {
3543
minifyEnabled true
3644
proguardFile getDefaultProguardFile('proguard-android.txt')
@@ -52,8 +60,13 @@ dependencies {
5260
if (parent != null) {
5361
compile project(':card.io')
5462
} else {
55-
compile 'io.card:android-sdk:5.4.2'
63+
compile 'io.card:android-sdk:5.5.0'
5664
}
65+
66+
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4'
67+
68+
androidTestCompile "com.android.support.test.espresso:espresso-core:2.2.2"
69+
androidTestCompile "com.github.lkorth:device-automator:01d85912ec"
5770
}
5871

5972
task wrapper(type: Wrapper) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Test Card Images
2+
3+
Card images in this folder are included for automated testing. Images should be 640px x 480px for
4+
tests.
753 KB
Loading
1.88 MB
Loading
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package io.card.payment;
2+
3+
/* CardScannerTester.java
4+
* See the file "LICENSE.md" for the full license governing this code.
5+
*/
6+
7+
import android.graphics.Bitmap;
8+
import android.graphics.BitmapFactory;
9+
import android.os.Handler;
10+
import android.view.SurfaceHolder;
11+
12+
import java.io.IOException;
13+
14+
import static android.support.test.InstrumentationRegistry.getInstrumentation;
15+
16+
public class CardScannerTester extends CardScanner {
17+
18+
private static final long FRAME_INTERVAL = (long) (1000.0 / 30);
19+
20+
private static String sCardAssetName;
21+
22+
private boolean mScanAllowed;
23+
private Handler mHandler;
24+
private byte[] mFrame;
25+
26+
public static void setCardAsset(String cardAssetName) {
27+
sCardAssetName = cardAssetName;
28+
}
29+
30+
public CardScannerTester(CardIOActivity scanActivity, int currentFrameOrientation) {
31+
super(scanActivity, currentFrameOrientation);
32+
useCamera = false;
33+
mScanAllowed = false;
34+
mHandler = new Handler();
35+
36+
try {
37+
Bitmap bitmap = BitmapFactory.decodeStream(getInstrumentation().getContext().getAssets()
38+
.open("test_card_images/" + sCardAssetName));
39+
mFrame = getNV21FormattedImage(bitmap.getWidth(), bitmap.getHeight(), bitmap);
40+
} catch (IOException e) {
41+
throw new RuntimeException(e);
42+
}
43+
}
44+
45+
private Runnable mFrameRunnable = new Runnable() {
46+
@Override
47+
public void run() {
48+
if (!mScanAllowed) {
49+
return;
50+
}
51+
52+
onPreviewFrame(mFrame, null);
53+
mHandler.postDelayed(this, FRAME_INTERVAL);
54+
}
55+
};
56+
57+
@Override
58+
boolean resumeScanning(SurfaceHolder holder) {
59+
boolean result = super.resumeScanning(holder);
60+
mScanAllowed = true;
61+
mHandler.postDelayed(mFrameRunnable, FRAME_INTERVAL);
62+
return result;
63+
}
64+
65+
@Override
66+
public void pauseScanning() {
67+
mScanAllowed = false;
68+
super.pauseScanning();
69+
}
70+
71+
private byte[] getNV21FormattedImage(int width, int height, Bitmap bitmap) {
72+
int [] argb = new int[width * height];
73+
byte [] yuv = new byte[width * height * 3 / 2];
74+
75+
bitmap.getPixels(argb, 0, width, 0, 0, width, height);
76+
encodeYUV420SP(yuv, argb, width, height);
77+
bitmap.recycle();
78+
79+
return yuv;
80+
}
81+
82+
private void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) {
83+
int frameSize = width * height;
84+
int yIndex = 0;
85+
int uvIndex = frameSize;
86+
87+
int R, G, B, Y, U, V;
88+
int index = 0;
89+
for (int j = 0; j < height; j++) {
90+
for (int i = 0; i < width; i++) {
91+
R = (argb[index] & 0xff0000) >> 16;
92+
G = (argb[index] & 0xff00) >> 8;
93+
B = (argb[index] & 0xff);
94+
95+
// well known RGB to YUV algorithm
96+
Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
97+
U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
98+
V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
99+
100+
// NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2
101+
// meaning for every 4 Y pixels there are 1 V and 1 U. Note the sampling is every
102+
// other pixel AND every other scanline.
103+
yuv420sp[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
104+
if (j % 2 == 0 && index % 2 == 0) {
105+
yuv420sp[uvIndex++] = (byte)((V<0) ? 0 : ((V > 255) ? 255 : V));
106+
yuv420sp[uvIndex++] = (byte)((U<0) ? 0 : ((U > 255) ? 255 : U));
107+
}
108+
109+
index ++;
110+
}
111+
}
112+
}
113+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package io.card.test;
2+
3+
import android.Manifest;
4+
import android.app.Activity;
5+
import android.content.Intent;
6+
7+
import org.junit.Rule;
8+
import org.junit.Test;
9+
10+
import java.lang.reflect.Field;
11+
12+
import io.card.payment.CardIOActivity;
13+
import io.card.payment.CardScannerTester;
14+
import io.card.payment.CreditCard;
15+
16+
import static com.lukekorth.deviceautomator.DeviceAutomator.onDevice;
17+
import static junit.framework.Assert.assertEquals;
18+
import static org.hamcrest.core.Is.is;
19+
import static org.junit.Assert.assertThat;
20+
21+
public class CardIOActivityTest {
22+
23+
private CardIOTestActivity mActivity;
24+
25+
@Rule
26+
public final CustomActivityTestRule<CardIOTestActivity> mActivityTestRule =
27+
new CustomActivityTestRule<>(CardIOTestActivity.class, false, false);
28+
29+
@Test(timeout = 30000)
30+
public void scansAmexCards() {
31+
CardScannerTester.setCardAsset("amex.png");
32+
33+
startScan();
34+
35+
waitForActivityToFinish();
36+
CreditCard result = getActivityResultIntent().getParcelableExtra(CardIOActivity.EXTRA_SCAN_RESULT);
37+
assertEquals("3743 260055 74998", result.getFormattedCardNumber());
38+
}
39+
40+
private void startScan() {
41+
mActivityTestRule.launchActivity(null);
42+
mActivity = mActivityTestRule.getActivity();
43+
44+
onDevice().acceptRuntimePermission(Manifest.permission.CAMERA);
45+
}
46+
47+
private void waitForActivityToFinish() {
48+
long endTime = System.currentTimeMillis() + 10000;
49+
50+
do {
51+
try {
52+
if (mActivity.isFinishing()) {
53+
return;
54+
}
55+
} catch (Exception ignored) {}
56+
} while (System.currentTimeMillis() < endTime);
57+
58+
throw new RuntimeException("Maximum wait elapsed (10s) while waiting for activity to finish");
59+
}
60+
61+
private Intent getActivityResultIntent() {
62+
assertThat("Activity did not finish", mActivity.isFinishing(), is(true));
63+
64+
try {
65+
Field resultDataField = Activity.class.getDeclaredField("mResultData");
66+
resultDataField.setAccessible(true);
67+
return (Intent) resultDataField.get(mActivity);
68+
} catch (Exception e) {
69+
throw new RuntimeException(e);
70+
}
71+
}
72+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.card.test;
2+
3+
4+
import android.app.Activity;
5+
import android.app.KeyguardManager;
6+
import android.content.Context;
7+
8+
import static android.support.test.InstrumentationRegistry.getTargetContext;
9+
10+
public class CustomActivityTestRule<T extends Activity> extends android.support.test.rule.ActivityTestRule<T> {
11+
12+
private KeyguardManager.KeyguardLock mKeyguardLock;
13+
14+
public CustomActivityTestRule(Class<T> activityClass) {
15+
super(activityClass);
16+
init();
17+
}
18+
19+
public CustomActivityTestRule(Class<T> activityClass, boolean initialTouchMode) {
20+
super(activityClass, initialTouchMode);
21+
init();
22+
}
23+
24+
public CustomActivityTestRule(Class<T> activityClass, boolean initialTouchMode, boolean launchActivity) {
25+
super(activityClass, initialTouchMode, launchActivity);
26+
init();
27+
}
28+
29+
private void init() {
30+
mKeyguardLock = ((KeyguardManager) getTargetContext().getSystemService(Context.KEYGUARD_SERVICE))
31+
.newKeyguardLock("CardIOTest");
32+
mKeyguardLock.disableKeyguard();
33+
}
34+
35+
@Override
36+
protected void afterActivityFinished() {
37+
super.afterActivityFinished();
38+
39+
mKeyguardLock.reenableKeyguard();
40+
}
41+
}

0 commit comments

Comments
 (0)