diff --git a/build.gradle b/build.gradle
index 96361f4a..5a7a56ba 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,9 @@ ext {
appVersionName = '1.0.0-SNAPSHOT'
kotlinVersion = '1.3.41'
+
javaUtilsVersion = '1.0.8'
+ androidUtilsVersion = '1.1.0'
junitVersion = '4.12'
assertJVersion = '3.12.2'
@@ -12,6 +14,7 @@ ext {
mockitoVersion = '2.22.0'
mockitoKotlinVersion = '1.6.0'
+ slf4JVersion = '1.7.26'
logbackVersion = '1.2.3'
}
@@ -23,7 +26,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.3'
+ classpath 'com.android.tools.build:gradle:3.4.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// Nexus staging plugin has to be downgraded to 0.10.0 to be applicable to sub projects, see https://github.com/UweTrottmann/SeriesGuide/commit/ca33e8ad2fa6cc5c426450c8aef3417ba073ca7f
diff --git a/fints4javaAndroidApp/build.gradle b/fints4javaAndroidApp/build.gradle
new file mode 100644
index 00000000..c4a7b978
--- /dev/null
+++ b/fints4javaAndroidApp/build.gradle
@@ -0,0 +1,49 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+
+android {
+ compileSdkVersion 28
+
+
+ defaultConfig {
+ applicationId "net.dankito.banking.fints4java.android"
+ minSdkVersion 15
+ targetSdkVersion 28
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ implementation project(':fints4javaLib')
+// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ api "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
+
+ api "net.dankito.utils:android-utils:$androidUtilsVersion", {
+ exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
+ exclude group: 'com.android.support', module: 'appcompat-v7'
+ exclude group: 'com.android.support', module: 'design'
+ }
+
+ api "org.slf4j:slf4j-android:$slf4JVersion"
+
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.android.support:design:28.0.0'
+ implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+ implementation 'android.arch.navigation:navigation-fragment:1.0.0'
+ implementation 'android.arch.navigation:navigation-ui:1.0.0'
+ implementation 'android.arch.lifecycle:extensions:1.1.1'
+ implementation 'android.arch.navigation:navigation-fragment-ktx:1.0.0'
+ implementation 'android.arch.navigation:navigation-ui-ktx:1.0.0'
+}
diff --git a/fints4javaAndroidApp/proguard-rules.pro b/fints4javaAndroidApp/proguard-rules.pro
new file mode 100644
index 00000000..f1b42451
--- /dev/null
+++ b/fints4javaAndroidApp/proguard-rules.pro
@@ -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
diff --git a/fints4javaAndroidApp/src/main/AndroidManifest.xml b/fints4javaAndroidApp/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..3bf7c4f2
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/AndroidManifest.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/Base64ServiceAndroid.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/Base64ServiceAndroid.kt
new file mode 100644
index 00000000..271cbd89
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/Base64ServiceAndroid.kt
@@ -0,0 +1,22 @@
+package net.dankito.banking.fints4java.android
+
+import android.util.Base64
+import net.dankito.fints.util.IBase64Service
+import java.nio.charset.Charset
+
+
+open class Base64ServiceAndroid : IBase64Service {
+
+ override fun encode(text: String, charset: Charset): String {
+ val bytes = text.toByteArray(charset)
+
+ return Base64.encodeToString(bytes, Base64.NO_WRAP)
+ }
+
+ override fun decode(base64: String, charset: Charset): String {
+ val decoded = Base64.decode(base64, Base64.NO_WRAP)
+
+ return String(decoded, charset)
+ }
+
+}
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt
new file mode 100644
index 00000000..b37a5b21
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt
@@ -0,0 +1,67 @@
+package net.dankito.banking.fints4java.android
+
+import android.os.Bundle
+import android.support.design.widget.FloatingActionButton
+import android.support.design.widget.NavigationView
+import android.support.v4.widget.DrawerLayout
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.Toolbar
+import android.view.Menu
+import androidx.navigation.findNavController
+import net.dankito.banking.fints4java.android.ui.MainWindowPresenter
+import net.dankito.banking.fints4java.android.ui.dialogs.AddAccountDialog
+
+class MainActivity : AppCompatActivity() {
+
+// private lateinit var appBarConfiguration: AppBarConfiguration
+
+ val presenter = MainWindowPresenter()
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ initUi()
+ }
+
+ private fun initUi() {
+ setContentView(R.layout.activity_main)
+
+ val toolbar: Toolbar = findViewById(R.id.toolbar)
+ setSupportActionBar(toolbar)
+
+ val fab: FloatingActionButton = findViewById(R.id.fab)
+ fab.setOnClickListener { view ->
+ AddAccountDialog().show(this, presenter)
+ }
+
+ val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
+ val navView: NavigationView = findViewById(R.id.nav_view)
+ val navController = findNavController(R.id.nav_host_fragment)
+
+// // Passing each menu ID as a set of Ids because each
+// // menu should be considered as top level destinations.
+// appBarConfiguration = AppBarConfiguration(
+// setOf(
+// R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow,
+// R.id.nav_tools, R.id.nav_share, R.id.nav_send
+// ), drawerLayout
+// )
+//
+// setupActionBarWithNavController(navController, appBarConfiguration)
+// navView.setupWithNavController(navController)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ menuInflater.inflate(R.menu.main, menu)
+
+ return true
+ }
+
+// override fun onSupportNavigateUp(): Boolean {
+// val navController = findNavController(R.id.nav_host_fragment)
+// return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
+// }
+
+}
diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/MainWindowPresenter.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/MainWindowPresenter.kt
new file mode 100644
index 00000000..b69f193e
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/MainWindowPresenter.kt
@@ -0,0 +1,85 @@
+package net.dankito.banking.fints4java.android.ui
+
+import net.dankito.banking.fints4java.android.Base64ServiceAndroid
+import net.dankito.fints.FinTsClient
+import net.dankito.fints.FinTsClientCallback
+import net.dankito.fints.banks.BankFinder
+import net.dankito.fints.model.BankData
+import net.dankito.fints.model.BankInfo
+import net.dankito.fints.model.CustomerData
+import net.dankito.fints.model.TanProcedure
+import net.dankito.fints.model.mapper.BankDataMapper
+import net.dankito.fints.response.client.FinTsClientResponse
+import net.dankito.fints.response.client.GetTransactionsResponse
+import net.dankito.utils.IThreadPool
+import net.dankito.utils.ThreadPool
+
+
+open class MainWindowPresenter {
+
+ protected val callback = object : FinTsClientCallback {
+
+ override fun askUserForTanProcedure(supportedTanProcedures: List): TanProcedure? {
+ // TODO: show dialog and ask user
+ return supportedTanProcedures.first()
+ }
+
+ }
+
+ protected val finTsClient = FinTsClient(callback, Base64ServiceAndroid())
+
+ protected val bankFinder: BankFinder = BankFinder()
+
+ protected val threadPool: IThreadPool = ThreadPool()
+
+ protected val bankDataMapper = BankDataMapper()
+
+
+ protected val accountAddedListeners = mutableListOf<(BankData, CustomerData) -> Unit>()
+
+
+ open fun checkIfAccountExists(bankInfo: BankInfo, customerId: String, pin: String,
+ callback: (FinTsClientResponse) -> Unit) {
+
+ val bank = bankDataMapper.mapFromBankInfo(bankInfo)
+ val customer = CustomerData(customerId, pin)
+
+ finTsClient.checkIfAccountExistsAsync(bank, customer) { response ->
+ if (response.isSuccessful) {
+ callAccountAddedListeners(bank, customer)
+ }
+
+ callback(response)
+ }
+ }
+
+
+ open fun getAccountTransactionsAsync(bank: BankData, customer: CustomerData,
+ callback: (GetTransactionsResponse) -> Unit) {
+
+ finTsClient.tryGetTransactionsOfLast90DaysWithoutTanAsync(bank, customer, callback)
+ }
+
+
+ open fun searchForBankAsync(enteredBankCode: String, callback: (List) -> Unit) {
+ threadPool.runAsync {
+ callback(searchForBank(enteredBankCode))
+ }
+ }
+
+ open fun searchForBank(enteredBankCode: String): List {
+ return bankFinder.findBankByBankCode(enteredBankCode)
+ }
+
+
+ open fun addAccountAddedListener(listener: (BankData, CustomerData) -> Unit) {
+ accountAddedListeners.add(listener)
+ }
+
+ protected open fun callAccountAddedListeners(bank: BankData, customer: CustomerData) {
+ ArrayList(accountAddedListeners).forEach {
+ it(bank, customer) // TODO: use RxJava for this
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/AccountTransactionAdapter.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/AccountTransactionAdapter.kt
new file mode 100644
index 00000000..b05970aa
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/AccountTransactionAdapter.kt
@@ -0,0 +1,43 @@
+package net.dankito.banking.fints4java.android.ui.adapter
+
+import android.view.View
+import net.dankito.banking.fints4java.android.R
+import net.dankito.banking.fints4java.android.ui.adapter.viewholder.AccountTransactionViewHolder
+import net.dankito.fints.model.AccountTransaction
+import net.dankito.utils.android.extensions.setTextColorToColorResource
+import net.dankito.utils.android.ui.adapter.ListRecyclerAdapter
+import java.math.BigDecimal
+import java.text.DateFormat
+
+
+open class AccountTransactionAdapter
+ : ListRecyclerAdapter() {
+
+ companion object {
+ val BookingDateFormat = DateFormat.getDateInstance(DateFormat.SHORT)
+ }
+
+
+ override fun getListItemLayoutId() = R.layout.list_item_account_transaction
+
+ override fun createViewHolder(itemView: View): AccountTransactionViewHolder {
+ return AccountTransactionViewHolder(itemView)
+ }
+
+ override fun bindItemToView(viewHolder: AccountTransactionViewHolder, item: AccountTransaction) {
+ viewHolder.txtvwBookingDate.text = BookingDateFormat.format(item.bookingDate)
+
+ viewHolder.txtvwBookingText.text = item.bookingText ?: ""
+
+ viewHolder.txtvwOtherPartyName.text = item.otherPartyName ?: ""
+
+ viewHolder.txtvwUsage1.text = item.usage
+
+ viewHolder.txtvwUsage2.visibility = View.GONE // TODO
+ viewHolder.txtvwUsage2.text = "" // TODO
+
+ viewHolder.txtvwAmount.text = item.amount.toString()
+ viewHolder.txtvwAmount.setTextColorToColorResource(if (item.amount >= BigDecimal.ZERO) R.color.positiveAmount else R.color.negativeAmount)
+ }
+
+}
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/viewholder/AccountTransactionViewHolder.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/viewholder/AccountTransactionViewHolder.kt
new file mode 100644
index 00000000..b0169615
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/viewholder/AccountTransactionViewHolder.kt
@@ -0,0 +1,23 @@
+package net.dankito.banking.fints4java.android.ui.adapter.viewholder
+
+import android.support.v7.widget.RecyclerView
+import android.view.View
+import android.widget.TextView
+import kotlinx.android.synthetic.main.list_item_account_transaction.view.*
+
+
+class AccountTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+
+ val txtvwBookingDate: TextView = itemView.txtvwBookingDate
+
+ val txtvwBookingText: TextView = itemView.txtvwBookingText
+
+ val txtvwOtherPartyName: TextView = itemView.txtvwOtherPartyName
+
+ val txtvwUsage1: TextView = itemView.txtvwUsage1
+
+ val txtvwUsage2: TextView = itemView.txtvwUsage2
+
+ val txtvwAmount: TextView = itemView.txtvwAmount
+
+}
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt
new file mode 100644
index 00000000..50a3b103
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt
@@ -0,0 +1,143 @@
+package net.dankito.banking.fints4java.android.ui.dialogs
+
+import android.os.Bundle
+import android.support.v4.app.DialogFragment
+import android.support.v7.app.AlertDialog
+import android.support.v7.app.AppCompatActivity
+import android.text.Editable
+import android.text.TextWatcher
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import kotlinx.android.synthetic.main.dialog_add_account.*
+import kotlinx.android.synthetic.main.dialog_add_account.view.*
+import net.dankito.banking.fints4java.android.R
+import net.dankito.banking.fints4java.android.ui.MainWindowPresenter
+import net.dankito.fints.model.BankInfo
+import net.dankito.fints.response.client.FinTsClientResponse
+import net.dankito.utils.android.extensions.asActivity
+
+
+class AddAccountDialog : DialogFragment() {
+
+ companion object {
+ const val DialogTag = "AddAccountDialog"
+ }
+
+
+ private lateinit var presenter: MainWindowPresenter
+
+ private var selectedBank: BankInfo? = null
+
+
+ fun show(activity: AppCompatActivity, presenter: MainWindowPresenter, fullscreen: Boolean = false) {
+ this.presenter = presenter
+
+ val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.Dialog
+ setStyle(STYLE_NORMAL, style)
+
+ show(activity.supportFragmentManager, DialogTag)
+ }
+
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ val rootView = inflater.inflate(R.layout.dialog_add_account, container, false)
+
+ rootView?.let {
+ setupUI(rootView)
+ }
+
+ return rootView
+ }
+
+ private fun setupUI(rootView: View) {
+ rootView.edtxtBankCode.addTextChangedListener(bankCodeChangedWatcher)
+
+ rootView.edtxtCustomerId.addTextChangedListener(otherEditTextChangedWatcher)
+ rootView.edtxtPin.addTextChangedListener(otherEditTextChangedWatcher)
+
+ rootView.btnSelect.setOnClickListener { addAccount() }
+ rootView.btnCancel.setOnClickListener { dismiss() }
+ }
+
+ private fun addAccount() {
+ selectedBank?.let { selectedBank -> // should always be non-null at this stage
+ val customerId = edtxtCustomerId.text.toString()
+ val pin = edtxtPin.text.toString()
+
+ presenter.checkIfAccountExists(selectedBank, customerId, pin) { response ->
+ context?.asActivity()?.runOnUiThread {
+ handleAccountCheckResponseOnUiThread(response)
+ }
+ }
+ }
+ }
+
+ private fun handleAccountCheckResponseOnUiThread(response: FinTsClientResponse) {
+ context?.let { context ->
+ if (response.isSuccessful) {
+ AlertDialog.Builder(context)
+ .setMessage("Successfully added account")
+ .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
+ .show()
+ this.dismiss()
+ }
+ else {
+ AlertDialog.Builder(context).setMessage("Could not add account: ${response.exception ?: response.errorsToShowToUser.joinToString("\n")}").show()
+ }
+ }
+ }
+
+
+ val bankCodeChangedWatcher = object : TextWatcher {
+
+ override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }
+
+ override fun onTextChanged(enteredText: CharSequence?, start: Int, before: Int, count: Int) {
+ enteredText?.let { searchForBankAsync(enteredText) }
+ }
+
+ override fun afterTextChanged(s: Editable?) { }
+
+ }
+
+ val otherEditTextChangedWatcher = object : TextWatcher {
+
+ override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }
+
+ override fun onTextChanged(enteredText: CharSequence?, start: Int, before: Int, count: Int) {
+ checkIfRequiredDataEnteredOnUiThread()
+ }
+
+ override fun afterTextChanged(s: Editable?) { }
+
+ }
+
+ private fun searchForBankAsync(enteredBankCode: CharSequence) {
+ presenter.searchForBankAsync(enteredBankCode.toString()) { foundBanks ->
+ context?.asActivity()?.runOnUiThread {
+ showFoundBanksOnUiThread(foundBanks)
+ }
+ }
+ }
+
+ private fun showFoundBanksOnUiThread(foundBanks: List) {
+ if (foundBanks.isNotEmpty()) {
+ selectedBank = foundBanks.first()
+ }
+ else {
+ selectedBank = null
+ }
+
+ checkIfRequiredDataEnteredOnUiThread()
+ }
+
+ private fun checkIfRequiredDataEnteredOnUiThread() {
+ val requiredDataEntered = selectedBank != null
+ && edtxtCustomerId.text.toString().isNotEmpty() // TODO: check if it is of length 10?
+ && edtxtPin.text.toString().isNotEmpty() // TODO: check if it is of length 5?
+
+ btnSelect.isEnabled = requiredDataEntered
+ }
+
+}
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt
new file mode 100644
index 00000000..e3e88bb9
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt
@@ -0,0 +1,85 @@
+package net.dankito.banking.fints4java.android.ui.home
+
+import android.arch.lifecycle.ViewModelProviders
+import android.os.Bundle
+import android.support.v4.app.Fragment
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import net.dankito.banking.fints4java.android.MainActivity
+import net.dankito.banking.fints4java.android.R
+import net.dankito.banking.fints4java.android.ui.MainWindowPresenter
+import net.dankito.banking.fints4java.android.ui.adapter.AccountTransactionAdapter
+import net.dankito.fints.model.BankData
+import net.dankito.fints.model.CustomerData
+import net.dankito.utils.android.extensions.asActivity
+import org.slf4j.LoggerFactory
+
+
+class HomeFragment : Fragment() {
+
+ companion object {
+ private val log = LoggerFactory.getLogger(HomeFragment::class.java)
+ }
+
+
+ private lateinit var homeViewModel: HomeViewModel
+
+ private val transactionAdapter = AccountTransactionAdapter()
+
+
+ private lateinit var presenter: MainWindowPresenter
+
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ homeViewModel =
+ ViewModelProviders.of(this).get(HomeViewModel::class.java)
+ val root = inflater.inflate(R.layout.fragment_home, container, false)
+// val textView: TextView = root.findViewById(R.id.text_home)
+// homeViewModel.text.observe(this, Observer {
+// textView.text = it
+// })
+
+
+ val rcyvwAccountTransactions: RecyclerView = root.findViewById(R.id.rcyvwAccountTransactions)
+ rcyvwAccountTransactions.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
+ rcyvwAccountTransactions.adapter = transactionAdapter
+
+ initLogic()
+
+ return root
+ }
+
+
+ private fun initLogic() {
+
+ // TODO: this is such a bad code style
+ (context as? MainActivity)?.presenter?.let { presenter ->
+ this.presenter = presenter
+
+ presenter.addAccountAddedListener { bank, customer ->
+ retrieveAccountTransactions(bank, customer)
+ }
+ }
+ }
+
+ private fun retrieveAccountTransactions(bank: BankData, customer: CustomerData) {
+ presenter.getAccountTransactionsAsync(bank, customer) { response ->
+ context?.asActivity()?.runOnUiThread {
+ if (response.isSuccessful) {
+ transactionAdapter.items = response.bookedTransactions
+ }
+ else {
+ // TODO: show error
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeViewModel.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeViewModel.kt
new file mode 100644
index 00000000..e801d897
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeViewModel.kt
@@ -0,0 +1,13 @@
+package net.dankito.banking.fints4java.android.ui.home
+
+import android.arch.lifecycle.LiveData
+import android.arch.lifecycle.MutableLiveData
+import android.arch.lifecycle.ViewModel
+
+class HomeViewModel : ViewModel() {
+
+ private val _text = MutableLiveData().apply {
+ value = "This is home Fragment"
+ }
+ val text: LiveData = _text
+}
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml b/fints4javaAndroidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..e86fe0a9
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/fints4javaAndroidApp/src/main/res/drawable/ic_launcher_background.xml b/fints4javaAndroidApp/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..e2561079
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/fints4javaAndroidApp/src/main/res/drawable/side_nav_bar.xml b/fints4javaAndroidApp/src/main/res/drawable/side_nav_bar.xml
new file mode 100644
index 00000000..f9628c21
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/drawable/side_nav_bar.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/layout/activity_main.xml b/fints4javaAndroidApp/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..f4df16d8
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/layout/activity_main.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
diff --git a/fints4javaAndroidApp/src/main/res/layout/app_bar_main.xml b/fints4javaAndroidApp/src/main/res/layout/app_bar_main.xml
new file mode 100644
index 00000000..61e654a7
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/layout/app_bar_main.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/layout/content_main.xml b/fints4javaAndroidApp/src/main/res/layout/content_main.xml
new file mode 100644
index 00000000..b7cf46c2
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/layout/content_main.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/layout/dialog_add_account.xml b/fints4javaAndroidApp/src/main/res/layout/dialog_add_account.xml
new file mode 100644
index 00000000..17698d04
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/layout/dialog_add_account.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/layout/fragment_home.xml b/fints4javaAndroidApp/src/main/res/layout/fragment_home.xml
new file mode 100644
index 00000000..2e6cd81b
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/layout/fragment_home.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/layout/list_item_account_transaction.xml b/fints4javaAndroidApp/src/main/res/layout/list_item_account_transaction.xml
new file mode 100644
index 00000000..bd2851eb
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/layout/list_item_account_transaction.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/layout/nav_header_main.xml b/fints4javaAndroidApp/src/main/res/layout/nav_header_main.xml
new file mode 100644
index 00000000..b697ad54
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/layout/nav_header_main.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/fints4javaAndroidApp/src/main/res/menu/activity_main_drawer.xml b/fints4javaAndroidApp/src/main/res/menu/activity_main_drawer.xml
new file mode 100644
index 00000000..d761f80d
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/menu/activity_main_drawer.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/fints4javaAndroidApp/src/main/res/menu/main.xml b/fints4javaAndroidApp/src/main/res/menu/main.xml
new file mode 100644
index 00000000..bad96f38
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/menu/main.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/fints4javaAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/fints4javaAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-hdpi/ic_launcher.png b/fints4javaAndroidApp/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..898f3ed5
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png b/fints4javaAndroidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 00000000..dffca360
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-mdpi/ic_launcher.png b/fints4javaAndroidApp/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..64ba76f7
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png b/fints4javaAndroidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 00000000..dae5e082
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher.png b/fints4javaAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..e5ed4659
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/fints4javaAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..14ed0af3
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png b/fints4javaAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..b0907cac
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/fints4javaAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..d8ae0315
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/fints4javaAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..2c18de9e
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/fints4javaAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/fints4javaAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..beed3cdd
Binary files /dev/null and b/fints4javaAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/fints4javaAndroidApp/src/main/res/navigation/mobile_navigation.xml b/fints4javaAndroidApp/src/main/res/navigation/mobile_navigation.xml
new file mode 100644
index 00000000..33b7d7eb
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/navigation/mobile_navigation.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/values-v21/styles.xml b/fints4javaAndroidApp/src/main/res/values-v21/styles.xml
new file mode 100644
index 00000000..fd7a0584
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/values-v21/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/fints4javaAndroidApp/src/main/res/values/colors.xml b/fints4javaAndroidApp/src/main/res/values/colors.xml
new file mode 100644
index 00000000..e981babe
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/values/colors.xml
@@ -0,0 +1,7 @@
+
+
+
+ #00FF00
+ #FF0000
+
+
diff --git a/fints4javaAndroidApp/src/main/res/values/dimens.xml b/fints4javaAndroidApp/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..c64b72ba
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/values/dimens.xml
@@ -0,0 +1,22 @@
+
+
+ 16dp
+ 16dp
+ 8dp
+ 176dp
+ 16dp
+
+ 100dp
+ 4dp
+ 60dp
+ 70dp
+ 4dp
+ 6dp
+
+ 4dp
+ 24dp
+ 40dp
+ 12dp
+ 120dp
+
+
\ No newline at end of file
diff --git a/fints4javaAndroidApp/src/main/res/values/drawables.xml b/fints4javaAndroidApp/src/main/res/values/drawables.xml
new file mode 100644
index 00000000..be008299
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/values/drawables.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/fints4javaAndroidApp/src/main/res/values/strings.xml b/fints4javaAndroidApp/src/main/res/values/strings.xml
new file mode 100644
index 00000000..a2189b60
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/values/strings.xml
@@ -0,0 +1,19 @@
+
+ FinTS
+
+ Select
+ Cancel
+
+ Open navigation drawer
+ Close navigation drawer
+ Android Studio
+ android.studio@android.com
+ Navigation header
+
+ Home
+
+ Bank code:
+ Customer Id:
+ Pin:
+
+
diff --git a/fints4javaAndroidApp/src/main/res/values/styles.xml b/fints4javaAndroidApp/src/main/res/values/styles.xml
new file mode 100644
index 00000000..545b9c6d
--- /dev/null
+++ b/fints4javaAndroidApp/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/settings.gradle b/settings.gradle
index 310bf533..9730720e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -2,4 +2,6 @@ rootProject.name = 'fints4java'
include ':fints4javaLib'
+include ':fints4javaAndroidApp'
+
include ':BankListCreator'
\ No newline at end of file