Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Zach Sweigart committed Aug 22, 2019
0 parents commit 033b9b0
Show file tree
Hide file tree
Showing 49 changed files with 1,278 additions and 0 deletions.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Plaid Link Sample Android App
Detailed instructions on how to integrate with Plaid Link for Android can be found in our main documentation at [plaid.com/docs/link/android][link-android-docs].

This repository contains a sample application that demonstrates integration and use of Plaid Link for Android. There are activities that show how to open link from Kotlin or Java.

# Getting Started
## Requirements
Android Studio 3.0 or greater
A Plaid public_key; available from the Plaid Dashboard

## Running the app
1. Clone the repository
``` sh
git clone https://github.com/plaid/plaid-link-android.git
```
2. Open the repository with Android Studio (or IntelliJ)
3. Add your plaid public key from the Plaid Dashboard to the donottranslate.xml file
``` xml
<string name="plaid_public_key">TODO Add your key here</string>
```
4. Build and run from Android Studio (green arrow or Run -> Run App)

![](./docs/images/AndroidToolbarRun.png)

![](./docs/images/AndroidRunMenu.png)

Or run from the command line
``` sh
./gradlew installDebug
adb shell am start -n "com.plaid.linksample/com.plaid.linksample.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
```

# App Features
The repository contains a java and kotlin application class and a java and kotlin activity. From the kotlin activity you can open the java activity using the menu in the action bar and similarly from the java activity you can open the kotlin activity from the same menu. If you want to test the java appplication class instead of the kotlin application class just change the name in the application tag in the Android manifest to ```name=".LinkSampleJavaApplication"```.

When running the app, the floating action button will start the Link flow and when the flow completes (with a success, cancellation, error, or crash) you will see the results in the main activity.

1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
225 changes: 225 additions & 0 deletions app/app.iml

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
signingConfigs {
release {
storeFile file('../keystore/release.jks')
storePassword 'release'
keyAlias = 'PlaidLinkSample'
keyPassword 'plaid1234'
}
}

compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
applicationId "com.plaid.linksample"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation 'com.plaid.link:sdk-core:0.1.1'

implementation 'androidx.appcompat:appcompat:1.0.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0-alpha09'

testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
Binary file added app/debug/app.aab
Binary file not shown.
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# 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
Binary file added app/release/app.aab
Binary file not shown.
46 changes: 46 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.plaid.linksample">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".LinkSampleApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">

<activity
android:name=".MainActivity"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

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

<activity android:name="com.plaid.link.LinkActivity" />

<!--<provider-->
<!--android:name="com.plaid.link.PlaidContentProvider"-->
<!--android:authorities="com.plaid.link.PlaidContentProvider"-->
<!--android:exported="true" />-->

<meta-data
android:name="com.plaid.link.public_key"
android:value="@string/plaid_public_key" />

</application>

</manifest>
18 changes: 18 additions & 0 deletions app/src/main/java/com/plaid/linksample/LinkSampleApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.plaid.linksample

import android.app.Application
import com.plaid.link.Plaid
import com.plaid.linkbase.models.PlaidOptions
import com.plaid.linkbase.models.PlaidEnvironment
import com.plaid.plog.LogLevel

class LinkSampleApplication : Application() {

override fun onCreate() {
super.onCreate()

val plaidOptions = PlaidOptions(if (BuildConfig.DEBUG) LogLevel.VERBOSE else LogLevel.ASSERT, PlaidEnvironment.SANDBOX)

Plaid.create(this, plaidOptions)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.plaid.linksample;

import android.app.Application;

import com.plaid.link.Plaid;
import com.plaid.linkbase.models.PlaidOptions;
import com.plaid.linkbase.models.PlaidEnvironment;
import com.plaid.plog.LogLevel;

public class LinkSampleJavaApplication extends Application {

@Override
public void onCreate() {
super.onCreate();

PlaidOptions plaidOptions = new PlaidOptions.Builder()
.environment(PlaidEnvironment.SANDBOX)
.logLevel(BuildConfig.DEBUG ? LogLevel.DEBUG : LogLevel.ASSERT)
.build();

Plaid.create(this, plaidOptions);
}
}
110 changes: 110 additions & 0 deletions app/src/main/java/com/plaid/linksample/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.plaid.linksample

import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.plaid.link.LinkActivity
import com.plaid.link.Plaid
import com.plaid.linkbase.models.LinkCancellation
import com.plaid.linkbase.models.LinkConfiguration
import com.plaid.linkbase.models.LinkConnection
import com.plaid.linkbase.models.PlaidApiError
import com.plaid.linkbase.models.PlaidProduct
import kotlinx.android.synthetic.main.activity_main.toolbar

class MainActivity : AppCompatActivity() {

companion object {
const val LINK_REQUEST_CODE = 1
}

private lateinit var contentTextView: TextView

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
contentTextView = findViewById(R.id.content)

val fab = findViewById<FloatingActionButton>(R.id.open_link_fab)
fab.setOnClickListener {
val intent = Intent(this, LinkActivity::class.java)
intent.putExtra(
Plaid.LINK_CONFIGURATION, LinkConfiguration(
clientName = "Test App",
products = listOf(PlaidProduct.TRANSACTIONS)
)
)
startActivityForResult(intent, LINK_REQUEST_CODE)
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, intent)
if (requestCode == LINK_REQUEST_CODE) {
when (resultCode) {
Plaid.RESULT_SUCCESS ->
(data?.getSerializableExtra(Plaid.LINK_RESULT) as LinkConnection).let {
contentTextView.text = getString(
R.string.content_success,
it.publicToken,
it.linkConnectionMetadata.accountId,
it.linkConnectionMetadata.accountName,
it.linkConnectionMetadata.institutionId,
it.linkConnectionMetadata.institutionName
)
}
Plaid.RESULT_CANCELLED ->
(data?.getSerializableExtra(Plaid.LINK_RESULT) as LinkCancellation).let {
contentTextView.text = getString(
R.string.content_cancelled,
it.institutionId,
it.institutionName,
it.linkSessionId,
it.status
)
}
Plaid.RESULT_EXIT ->
(data?.getSerializableExtra(Plaid.LINK_RESULT) as PlaidApiError).let {
contentTextView.text = getString(
R.string.content_exit,
it.displayMessage,
it.errorCode,
it.errorMessage,
it.institutionId,
it.institutionName,
it.status
)
}
Plaid.RESULT_EXCEPTION ->
(data?.getSerializableExtra(Plaid.LINK_RESULT) as java.lang.Exception).let {
contentTextView.text = getString(
R.string.content_exception,
it.javaClass.toString(),
it.message
)
}
}
}
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.kotlin_menu, menu)
return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean =
when (item.itemId) {
R.id.show_java -> {
val intent = Intent(this@MainActivity, MainJavaActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
true
}
else -> super.onOptionsItemSelected(item)
}
}
Loading

0 comments on commit 033b9b0

Please sign in to comment.