Merge pull request #9 from TanelOrumaa/iter3UI

Iter3 UI
This commit is contained in:
Henrik Lepson 2021-10-21 20:31:26 +03:00 committed by GitHub
commit 71db5cc9e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1051 additions and 88 deletions

View File

@ -59,4 +59,7 @@ dependencies {
//For cryptography //For cryptography
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69'
//SecureDataStoring
implementation("androidx.security:security-crypto:1.0.0")
} }

View File

@ -78,10 +78,13 @@ class AuthFragment : Fragment() {
card.use { card.use {
try { try {
val comms = Comms(it, viewModel.userCan) val comms = Comms(it, viewModel.userCan)
val response = comms.readPersonalData(byteArrayOf(1, 2, 6)) val response = comms.readPersonalData(byteArrayOf(1, 2, 6, 3, 4, 8))
viewModel.setUserFirstName(response[1]) viewModel.setUserFirstName(response[1])
viewModel.setUserLastName(response[0]) viewModel.setUserLastName(response[0])
viewModel.setUserIdentificationNumber(response[2]) viewModel.setUserIdentificationNumber(response[2])
viewModel.setGender(response[3])
viewModel.setCitizenship(response[4])
viewModel.setExpiration(response[5])
requireActivity().runOnUiThread{ requireActivity().runOnUiThread{
binding!!.timeCounter.text = getString(R.string.data_read) binding!!.timeCounter.text = getString(R.string.data_read)
} }
@ -89,6 +92,8 @@ class AuthFragment : Fragment() {
requireActivity().runOnUiThread { requireActivity().runOnUiThread {
binding!!.timeCounter.text = getString(R.string.no_success) binding!!.timeCounter.text = getString(R.string.no_success)
} }
// If the CAN is wrong we will also delete the saved CAN so that the user won't use it again.
viewModel.deleteCan(requireContext())
// Gives user some time to read the error message // Gives user some time to read the error message
Thread.sleep(1000) Thread.sleep(1000)
goToTheStart() goToTheStart()

View File

@ -1,5 +1,6 @@
package com.tarkvaraprojekt.mobileauthapp package com.tarkvaraprojekt.mobileauthapp
import android.app.AlertDialog
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -8,11 +9,14 @@ import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentCanBinding import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentCanBinding
import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel
/** /**
* Fragment that deals with asking the user for six digit CAN * Fragment that deals with asking the user for a six digit CAN. If the CAN is already saved
* then the fragment is skipped immediately and if the CAN is not saved then the user
* is asked whether it should be saved for the future or not before continuing.
*/ */
class CanFragment : Fragment() { class CanFragment : Fragment() {
@ -20,6 +24,12 @@ class CanFragment : Fragment() {
private var binding: FragmentCanBinding? = null private var binding: FragmentCanBinding? = null
// Navigation arguments:
// saving = true means that we are navigating here from the settings menu and must return to the settings menu.
// reading = true means that we are only reading the information from the ID card that does not need PIN 1,
// this information is passed on to the next PinFragment.
private val args: CanFragmentArgs by navArgs()
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -31,27 +41,92 @@ class CanFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
checkIfSkip()
binding!!.nextButton.setOnClickListener { goToNextFragment() } // If the user arrives from the settings menu then the button should say
// save instead of continue.
if (args.saving) {
binding!!.nextButton.text = getString(R.string.save_text)
}
binding!!.nextButton.setOnClickListener { checkEnteredCan() }
binding!!.cancelButton.setOnClickListener { goToTheStart() } binding!!.cancelButton.setOnClickListener { goToTheStart() }
} }
private fun goToNextFragment() { /**
val enteredCan = binding!!.canEditText.editText?.text.toString() * Checks if the current fragment can be skipped or not.
if (enteredCan.length != 6) { * If the user has CAN saved on the device there is no need to ask it again.
Toast.makeText(requireContext(), getString(R.string.length_can), Toast.LENGTH_SHORT) */
.show() private fun checkIfSkip() {
} else { if (viewModel.userCan.length == 6) {
viewModel.setUserCan( goToTheNextFragment()
binding!!.canEditText.editText?.text.toString()
)
findNavController().navigate(R.id.action_canFragment_to_authFragment)
} }
} }
/**
* Takes user to the next fragment, which is PinFragment.
*/
private fun goToTheNextFragment() {
val action = CanFragmentDirections.actionCanFragmentToPinFragment(reading = args.reading)
findNavController().navigate(action)
}
/**
* Checks whether the user has entered a 6 digit can to the input field.
* If yes then the user is allowed to continue otherwise the user is
* allowed to modify the entered can.
*/
private fun checkEnteredCan() {
val enteredCan = binding!!.canEditText.editText?.text.toString()
if (enteredCan.length == 6) {
viewModel.setUserCan(enteredCan)
if (args.saving) {
viewModel.storeCan(requireContext())
goToTheStart()
} else {
val storeCanQuestion = getDialog()
storeCanQuestion?.show()
}
} else {
Toast.makeText(requireContext(), getString(R.string.length_can), Toast.LENGTH_SHORT)
.show()
}
}
/**
* Builds a dialog that asks the user whether the entered CAN should be saved
* on the device or not.
*/
private fun getDialog(): AlertDialog? {
return activity?.let { frag ->
val builder = AlertDialog.Builder(frag)
builder.apply {
// If response is positive then save the CAN on the device.
setPositiveButton(R.string.save_text) { _, _ ->
viewModel.storeCan(
requireContext()
)
goToTheNextFragment()
}
setNegativeButton(R.string.deny_text) { _, _ ->
goToTheNextFragment()
}
}
builder.setMessage(R.string.can_save_request)
builder.setTitle(R.string.save_can_title)
builder.create()
}
}
/**
* Navigates the user back to the start depending on where the user arrived.
* If the user arrived from the settings menu then the start is the settings menu
* not the HomeFragment.
*/
private fun goToTheStart() { private fun goToTheStart() {
viewModel.clearUserInfo() if (args.saving) {
findNavController().navigate(R.id.action_canFragment_to_homeFragment) findNavController().navigate(R.id.action_canFragment_to_settingsFragment)
} else {
findNavController().navigate(R.id.action_canFragment_to_homeFragment)
}
} }
override fun onDestroy() { override fun onDestroy() {

View File

@ -10,6 +10,13 @@ import androidx.navigation.fragment.findNavController
import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentHomeBinding import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentHomeBinding
import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel
/**
* HomeFragment is only shown to the user when then the user launches the application. When the application
* is launched by another application or a website then this Fragment will be skipped.
* This fragment uses the fields from the MainActivity by casting the activity to MainActivity.
* This might not be the best practice, but the application uses a single activity design so it should
* always work.
*/
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
private val viewModel: SmartCardViewModel by activityViewModels() private val viewModel: SmartCardViewModel by activityViewModels()
@ -22,17 +29,72 @@ class HomeFragment : Fragment() {
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
binding = FragmentHomeBinding.inflate(inflater, container, false) binding = FragmentHomeBinding.inflate(inflater, container, false)
// Making settings menu active again
(activity as MainActivity).menuAvailable = true
return binding!!.root return binding!!.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initialChecks()
binding!!.beginButton.setOnClickListener { goToNextFragment() } binding!!.beginButton.setOnClickListener { goToTheNextFragment() }
} }
private fun goToNextFragment() { /**
findNavController().navigate(R.id.action_homeFragment_to_pinFragment) * Method where all the initial checks that should be done before any user input is accepted should be added.
*/
private fun initialChecks() {
viewModel.checkCan(requireContext())
viewModel.checkPin(requireContext())
displayStates()
}
/**
* Starts the process of interacting with the ID card by sending user to the CAN fragment.
*/
private fun goToTheNextFragment() {
// Making settings menu inactive
(activity as MainActivity).menuAvailable = false
// Currently saving is true because the application is not yet integrated with
// other applications or websites.
val action = HomeFragmentDirections.actionHomeFragmentToCanFragment(reading = true)
findNavController().navigate(action)
}
/**
* Displays texts that inform the user whether the CAN and PIN 1 are saved on the device or not.
* This might help the user to save some time as checking menu is not necessary unless the user
* wishes to make changes to the saved CAN or PIN 1.
*/
private fun displayStates() {
canState()
pinState()
}
/**
* Checks the state of the CAN, saved or not saved. Updates the text and logo.
*/
private fun canState() {
if (viewModel.userCan.length == 6) {
binding!!.canStatusText.text = getString(R.string.can_status_saved)
binding!!.canStatusLogo.setImageResource(R.drawable.ic_check_logo)
} else {
binding!!.canStatusText.text = getString(R.string.can_status_negative)
binding!!.canStatusLogo.setImageResource(R.drawable.ic_info_logo)
}
}
/**
* Checks the state of the PIN 1, saved or not saved. Updates the text and logo.
*/
private fun pinState() {
if (viewModel.userPin.length in 4..12) {
binding!!.pinStatusText.text = getString(R.string.pin_status_saved)
binding!!.pinStatusLogo.setImageResource(R.drawable.ic_check_logo)
} else {
binding!!.pinStatusText.text = getString(R.string.pin_status_negative)
binding!!.pinStatusLogo.setImageResource(R.drawable.ic_info_logo)
}
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -1,24 +1,51 @@
package com.tarkvaraprojekt.mobileauthapp package com.tarkvaraprojekt.mobileauthapp
import android.nfc.NfcAdapter
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import com.tarkvaraprojekt.mobileauthapp.databinding.ActivityMainBinding import com.tarkvaraprojekt.mobileauthapp.databinding.ActivityMainBinding
/**
* The only activity of the application (single activity design).
*/
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var navigationController: NavController private lateinit var navigationController: NavController
// If true the settings menu can be accessed from the toolbar in the upper part of the screen.
var menuAvailable: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater) val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setSupportActionBar(binding.toolbar)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navigationController = navHostFragment.navController navigationController = navHostFragment.navController
} }
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.menu_settings_option -> {
if (menuAvailable) {
navigationController.navigate(R.id.action_homeFragment_to_settingsFragment)
true
} else {
Toast.makeText(this, getString(R.string.unavailable), Toast.LENGTH_SHORT).show()
false
}
}
else -> super.onOptionsItemSelected(item)
}
} }

View File

@ -1,5 +1,6 @@
package com.tarkvaraprojekt.mobileauthapp package com.tarkvaraprojekt.mobileauthapp
import android.app.AlertDialog
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -8,11 +9,14 @@ import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentPinBinding import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentPinBinding
import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel
/** /**
* Fragment that deals with asking the user for PIN1 * Fragment that deals with asking the user for PIN 1. If the user has already saved the PIN 1 then it is not asked again
* and the fragment is skipped and if the PIN 1 is not saved then the user is asked whether it should be saved or
* not before continuing.
*/ */
class PinFragment : Fragment() { class PinFragment : Fragment() {
@ -20,6 +24,12 @@ class PinFragment : Fragment() {
private var binding: FragmentPinBinding? = null private var binding: FragmentPinBinding? = null
// Navigation arguments:
// saving = true means that the user must be returned to the settings menu
// reading = true means that we are reading information from the ID card that does
// not require PIN 1 so it is not necessary to ask it.
private val args: CanFragmentArgs by navArgs()
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -31,33 +41,94 @@ class PinFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
checkIfSkip()
binding!!.nextButton.setOnClickListener { goToNextFragment() } // If the user arrives from the settings menu then the button says
// save instead of continue.
if (args.saving) {
binding!!.nextButton.text = getString(R.string.save_text)
}
binding!!.nextButton.setOnClickListener { checkEnteredPin() }
binding!!.cancelButton.setOnClickListener { goToTheStart() } binding!!.cancelButton.setOnClickListener { goToTheStart() }
// Currently PIN 1 is not required and thus this step is immediately skipped.
// In the future the UI flow will be changed in the nav_graph.
goToNextFragment()
} }
private fun goToNextFragment() { /**
val enteredPin1 = binding!!.pinEditText.editText?.text.toString() * Checks if the current fragment can be skipped or not.
if (enteredPin1.length in 4..12) { * If the user has PIN 1 saved on the device or PIN 1 is not required
viewModel.setUserPin( * then the PIN 1 won't be asked.
binding!!.pinEditText.editText?.text.toString() */
) private fun checkIfSkip() {
findNavController().navigate(R.id.action_pinFragment_to_canFragment) if (args.reading) {
} else { goToTheNextFragment()
// Currently it is not important to enter PIN1 so we will allow the user to leave this field empty } else if (viewModel.userPin.length in 4..12) {
//Toast.makeText(requireContext(), getString(R.string.length_pin), Toast.LENGTH_SHORT) goToTheNextFragment()
// .show()
viewModel.setUserPin("1234")
findNavController().navigate(R.id.action_pinFragment_to_canFragment)
} }
} }
/**
* Takes user to the next fragment, which is AuthFragment.
*/
private fun goToTheNextFragment() {
findNavController().navigate(R.id.action_pinFragment_to_authFragment)
}
/**
* Checks whether the user has entered a PIN 1 with length between [4, 12] in the
* input field. If yes then the user is allowed to continue otherwise the user is
* allowed to modify the entered PIN 1.
*/
private fun checkEnteredPin() {
val enteredPin = binding!!.pinEditText.editText?.text.toString()
if (enteredPin.length in 4..12) {
viewModel.setUserPin(enteredPin)
if (args.saving) {
viewModel.storePin(requireContext())
goToTheStart()
} else {
val storePinQuestion = getDialog()
storePinQuestion?.show()
}
} else {
Toast.makeText(requireContext(), getString(R.string.length_pin), Toast.LENGTH_SHORT)
.show()
}
}
/**
* Builds a dialog that asks the user whether the entered PIN 1 should be saved
* on the device or not.
*/
private fun getDialog(): AlertDialog? {
return activity?.let { frag ->
val builder = AlertDialog.Builder(frag)
builder.apply {
// If response is positive save the PIN 1 on the device.
setPositiveButton(R.string.save_text) { _, _ ->
viewModel.storePin(
requireContext()
)
goToTheNextFragment()
}
setNegativeButton(R.string.deny_text) { _, _ ->
goToTheNextFragment()
}
}
builder.setMessage(R.string.pin_save_request)
builder.setTitle(R.string.save_pin_title)
builder.create()
}
}
/**
* Returns user to the start. If the user arrived from the settings menu then the start is
* settings menu not the HomeFragment.
*/
private fun goToTheStart() { private fun goToTheStart() {
viewModel.clearUserInfo() if (args.saving) {
findNavController().navigate(R.id.action_pinFragment_to_homeFragment) findNavController().navigate(R.id.action_pinFragment_to_settingsFragment)
} else {
viewModel.clearUserInfo()
findNavController().navigate(R.id.action_pinFragment_to_homeFragment)
}
} }
override fun onDestroy() { override fun onDestroy() {

View File

@ -33,13 +33,25 @@ class UserFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
displayInformation()
binding!!.userName.text =
getString(R.string.user_name, viewModel.userFirstName, viewModel.userLastName)
binding!!.identificationNumber.text = viewModel.userIdentificationNumber
binding!!.clearButton.setOnClickListener { goToTheStart() } binding!!.clearButton.setOnClickListener { goToTheStart() }
} }
/**
* Assigns text values to the fields in order to display user information.
*/
private fun displayInformation() {
binding!!.userName.text =
getString(R.string.user_name, viewModel.userFirstName, viewModel.userLastName)
binding!!.identificationNumber.text = viewModel.userIdentificationNumber
binding!!.gender.text = viewModel.gender
binding!!.expiration.text = viewModel.expiration.replace(" ", "/")
binding!!.citizenship.text = viewModel.citizenship
}
/**
* Navigates user back to the start and also deletes any temporary information.
*/
private fun goToTheStart() { private fun goToTheStart() {
viewModel.clearUserInfo() viewModel.clearUserInfo()
findNavController().navigate(R.id.action_userFragment_to_homeFragment) findNavController().navigate(R.id.action_userFragment_to_homeFragment)

View File

@ -0,0 +1,141 @@
package com.tarkvaraprojekt.mobileauthapp.menu
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.tarkvaraprojekt.mobileauthapp.R
import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentSettingsBinding
import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel
/**
* This fragment allows the user to save the CAN and the PIN 1 and also to delete them if necessary.
* Should only be accessible for the user from the HomeFragment and not during the
* authentication process itself.
*/
class SettingsFragment : Fragment() {
private val viewModel: SmartCardViewModel by activityViewModels()
private var binding: FragmentSettingsBinding? = null
private var showPin: Boolean = false
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentSettingsBinding.inflate(inflater, container, false)
return binding!!.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
showCanField()
showPinField()
togglePinButton()
binding!!.canMenuAction.setOnClickListener { canAction() }
binding!!.pinMenuAction.setOnClickListener { pinAction() }
binding!!.pinMenuShow.setOnClickListener { togglePin() }
binding!!.returnButton.setOnClickListener { backToHome() }
}
/**
* Method for showing the CAN field to the user and can be used to refresh the field as well.
*/
private fun showCanField() {
if (viewModel.userCan.length == 6) {
binding!!.canSaved.text = getString(R.string.saved_can, viewModel.userCan)
binding!!.canMenuAction.text = getString(R.string.can_delete)
} else {
binding!!.canSaved.text = getString(R.string.saved_can, getString(R.string.missing))
binding!!.canMenuAction.text = getString(R.string.can_add)
}
}
/**
* Method that allows the user to delete saved CAN from the device and also to save new a CAN if
* currently there is no CAN saved.
*/
private fun canAction() {
if (viewModel.userCan.length == 6) {
viewModel.deleteCan(requireContext())
showCanField()
} else {
val action = SettingsFragmentDirections.actionSettingsFragmentToCanFragment(saving = true)
findNavController().navigate(action)
}
}
/**
* Method for showing the PIN 1 field to the user and can be used to refresh the field as well.
* The PIN 1 is hidden by default and when it is hidden it is always shown as **** despite the
* length of the PIN 1. Can be made visible with toggle button.
*/
private fun showPinField() {
if (viewModel.userPin.length in 4..12) {
binding!!.pinMenuShow.visibility = Button.VISIBLE
if (showPin)
binding!!.pinSaved.text = getString(R.string.saved_pin, viewModel.userPin)
else
binding!!.pinSaved.text = getString(R.string.saved_pin, getString(R.string.hidden_pin))
binding!!.pinMenuAction.text = getString(R.string.pin1_delete)
} else {
binding!!.pinMenuShow.visibility = Button.GONE
binding!!.pinSaved.text = getString(R.string.saved_pin, getString(R.string.missing))
binding!!.pinMenuAction.text = getString(R.string.pin1_add)
}
}
/**
* Method that allows the user to delete saved PIN 1 from the device and also to save a new PIN 1 if
* currently there is no PIN 1 saved.
*/
private fun pinAction() {
if (viewModel.userPin.length in 4..12) {
viewModel.deletePin(requireContext())
showPinField()
} else {
val action = SettingsFragmentDirections.actionSettingsFragmentToPinFragment(saving = true)
findNavController().navigate(action)
}
}
/**
* Hides the PIN 1 or makes it visible.
*/
private fun togglePin() {
showPin = !showPin
togglePinButton()
showPinField()
}
/**
* Updates the text on the button that controls the visiblity of the PIN 1.
*/
private fun togglePinButton() {
if (showPin) {
binding!!.pinMenuShow.text = getString(R.string.hide)
} else {
binding!!.pinMenuShow.text = getString(R.string.show)
}
}
/**
* Navigates back to home fragment.
*/
private fun backToHome() {
findNavController().navigate(R.id.action_settingsFragment_to_homeFragment)
}
override fun onDestroy() {
super.onDestroy()
binding = null
}
}

View File

@ -1,6 +1,10 @@
package com.tarkvaraprojekt.mobileauthapp.model package com.tarkvaraprojekt.mobileauthapp.model
import android.content.Context
import android.content.SharedPreferences
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKeys
class SmartCardViewModel: ViewModel() { class SmartCardViewModel: ViewModel() {
@ -19,12 +23,24 @@ class SmartCardViewModel: ViewModel() {
private var _userIdentificationNumber: String = "" private var _userIdentificationNumber: String = ""
val userIdentificationNumber get() = _userIdentificationNumber val userIdentificationNumber get() = _userIdentificationNumber
private var _gender: String = ""
val gender get() = _gender
private var _expiration: String = ""
val expiration get() = _expiration
private var _citizenship: String = ""
val citizenship get() = _citizenship
fun clearUserInfo() { fun clearUserInfo() {
_userPin = "" _userPin = ""
_userCan = "" _userCan = ""
_userFirstName = "" _userFirstName = ""
_userLastName = "" _userLastName = ""
_userIdentificationNumber = "" _userIdentificationNumber = ""
_expiration = ""
_citizenship = ""
_gender = ""
} }
fun setUserPin(newUserPin: String) { fun setUserPin(newUserPin: String) {
@ -47,4 +63,67 @@ class SmartCardViewModel: ViewModel() {
_userIdentificationNumber = newUserIdentificationNumber _userIdentificationNumber = newUserIdentificationNumber
} }
fun setExpiration(newExpiration: String) {
_expiration = newExpiration
}
fun setCitizenship(newCitizenship: String) {
_citizenship = newCitizenship
}
fun setGender(newGender: String) {
_gender = newGender
}
private fun getSharedPreferences(context: Context): SharedPreferences {
val masterKeyAlias: String = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
return EncryptedSharedPreferences.create(
"user_creds",
masterKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}
fun storeCan(context: Context) {
val sharedPreferences: SharedPreferences = getSharedPreferences(context)
sharedPreferences.edit().putString("CAN", userCan).apply()
}
fun checkCan(context: Context) {
val sharedPreferences: SharedPreferences = getSharedPreferences(context)
val foundCan = sharedPreferences.getString("CAN", null)
foundCan?.let {
_userCan = it
}
}
// Must be called from AuthFragment as well, when CAN is wrong.
fun deleteCan(context: Context) {
val sharedPreferences: SharedPreferences = getSharedPreferences(context)
sharedPreferences.edit().remove("CAN").apply()
_userCan = ""
}
fun storePin(context: Context) {
val sharedPreferences: SharedPreferences = getSharedPreferences(context)
sharedPreferences.edit().putString("PIN1", userPin).apply()
}
fun checkPin(context: Context) {
val sharedPreferences: SharedPreferences = getSharedPreferences(context)
val foundPin = sharedPreferences.getString("PIN1", null)
foundPin?.let {
_userPin = it
}
}
fun deletePin(context: Context) {
val sharedPreferences: SharedPreferences = getSharedPreferences(context)
sharedPreferences.edit().remove("PIN1").apply()
_userPin = ""
}
} }

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- For material card views as recommended in the material.io website -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorPrimary" android:state_checked="true"/>
<item android:alpha="0.12" android:color="?attr/colorOnSurface" android:state_checked="false"/>
</selector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56 1.84,0.63 3.37,1.91 4.33,3.56zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82c0.43,-1.43 1.08,-2.76 1.91,-3.96zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2 0,0.68 0.06,1.34 0.14,2L4.26,14zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56 -1.84,-0.63 -3.37,-1.9 -4.33,-3.56zM8.03,8L5.08,8c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8zM12,19.96c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96h3.82c-0.43,1.43 -1.08,2.76 -1.91,3.96zM14.34,14L9.66,14c-0.09,-0.66 -0.16,-1.32 -0.16,-2 0,-0.68 0.07,-1.35 0.16,-2h4.68c0.09,0.65 0.16,1.32 0.16,2 0,0.68 -0.07,1.34 -0.16,2zM14.59,19.56c0.6,-1.11 1.06,-2.31 1.38,-3.56h2.95c-0.96,1.65 -2.49,2.93 -4.33,3.56zM16.36,14c0.08,-0.66 0.14,-1.32 0.14,-2 0,-0.68 -0.06,-1.34 -0.14,-2h3.38c0.16,0.64 0.26,1.31 0.26,2s-0.1,1.36 -0.26,2h-3.38z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
</vector>

View File

@ -6,12 +6,28 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity"> tools:context=".MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.fragment.app.FragmentContainerView <androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment" android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="0dp"
app:defaultNavHost="true" app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" /> app:navGraph="@navigation/nav_graph"
app:layout_constraintTop_toBottomOf="@id/toolbar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -14,7 +14,10 @@
android:layout_margin="8dp" android:layout_margin="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="1dp"
app:strokeColor="@color/stroke_color"
app:cardElevation="0dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -59,7 +62,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:text="@string/next_text" android:text="@string/next_text"
android:textSize="18sp" android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/cancel_button" app:layout_constraintStart_toEndOf="@id/cancel_button"
app:layout_constraintTop_toBottomOf="@id/card_view" /> app:layout_constraintTop_toBottomOf="@id/card_view" />
@ -70,7 +73,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:text="@string/cancel_text" android:text="@string/cancel_text"
android:textSize="18sp" android:textSize="15sp"
app:layout_constraintEnd_toStartOf="@id/next_button" app:layout_constraintEnd_toStartOf="@id/next_button"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/card_view" /> app:layout_constraintTop_toBottomOf="@id/card_view" />

View File

@ -14,7 +14,10 @@
android:layout_margin="8dp" android:layout_margin="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="1dp"
app:strokeColor="@color/stroke_color"
app:cardElevation="0dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -63,7 +66,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:text="@string/next_text" android:text="@string/next_text"
android:textSize="18sp" android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/cancel_button" app:layout_constraintStart_toEndOf="@id/cancel_button"
app:layout_constraintTop_toBottomOf="@id/card_view" /> app:layout_constraintTop_toBottomOf="@id/card_view" />
@ -74,7 +77,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:text="@string/cancel_text" android:text="@string/cancel_text"
android:textSize="18dp" android:textSize="15sp"
app:layout_constraintEnd_toStartOf="@id/next_button" app:layout_constraintEnd_toStartOf="@id/next_button"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/card_view" /> app:layout_constraintTop_toBottomOf="@id/card_view" />

View File

@ -7,23 +7,87 @@
android:padding="24dp" android:padding="24dp"
tools:context=".HomeFragment"> tools:context=".HomeFragment">
<TextView <LinearLayout
android:id="@+id/home_fragment_text" android:id="@+id/saved_states"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/home_fragment" android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.google.android.material.card.MaterialCardView
android:id="@+id/can_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
app:strokeWidth="1dp"
app:strokeColor="@color/stroke_color"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/can_status_logo"
android:layout_marginStart="12dp"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/can_status_text"
android:textSize="20sp"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/pin_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
app:strokeWidth="1dp"
app:strokeColor="@color/stroke_color"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/pin_status_logo"
android:layout_marginStart="12dp"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/pin_status_text"
android:textSize="20sp"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<!-- Temporary button for testing purposes -->
<Button <Button
android:id="@+id/begin_button" android:id="@+id/begin_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/begin_text" android:text="@string/begin_text"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
app:layout_constraintTop_toBottomOf="@id/home_fragment_text" android:textSize="15sp"
app:layout_constraintTop_toBottomOf="@id/saved_states"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>

View File

@ -14,7 +14,10 @@
android:layout_margin="8dp" android:layout_margin="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="1dp"
app:strokeColor="@color/stroke_color"
app:cardElevation="0dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -62,6 +65,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:text="@string/next_text" android:text="@string/next_text"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/cancel_button" app:layout_constraintStart_toEndOf="@id/cancel_button"
app:layout_constraintTop_toBottomOf="@id/card_view" /> app:layout_constraintTop_toBottomOf="@id/card_view" />
@ -72,6 +76,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:text="@string/cancel_text" android:text="@string/cancel_text"
android:textSize="15sp"
app:layout_constraintEnd_toStartOf="@id/next_button" app:layout_constraintEnd_toStartOf="@id/next_button"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/card_view" /> app:layout_constraintTop_toBottomOf="@id/card_view" />

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="12dp"
tools:context=".menu.SettingsFragment">
<com.google.android.material.card.MaterialCardView
android:id="@+id/settings_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:strokeWidth="1dp"
app:strokeColor="@color/stroke_color"
app:cardElevation="0dp">
<LinearLayout
android:id="@+id/can_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:id="@+id/can_saved"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:padding="12dp"
android:text="@string/saved_can" />
<Button
android:id="@+id/can_menu_action"
android:layout_margin="12dp"
android:textSize="15sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/pin_saved"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:padding="12dp"
android:text="@string/saved_pin"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/pin_menu_action"
android:layout_margin="12dp"
android:textSize="15sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/pin_menu_show"
android:layout_margin="12dp"
android:textSize="15sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<Button
android:id="@+id/return_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/return_text"
android:layout_margin="24dp"
android:textSize="15sp"
app:layout_constraintTop_toBottomOf="@id/settings_card"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -14,7 +14,10 @@
android:layout_margin="8dp" android:layout_margin="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="1dp"
app:strokeColor="@color/stroke_color"
app:cardElevation="0dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -54,6 +57,54 @@
android:textSize="20sp" android:textSize="20sp"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView
android:id="@+id/gender_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/gender_label"
android:textSize="14sp" />
<TextView
android:id="@+id/gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/expiration_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/expiration_label"
android:textSize="14sp" />
<TextView
android:id="@+id/expiration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/citizenship_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/citizenship_label"
android:textSize="14sp" />
<TextView
android:id="@+id/citizenship"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout> </LinearLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_settings_option"
android:title="@string/menu_settings_title"
android:icon="@drawable/ic_settings"
app:showAsAction="always"/>
</menu>

View File

@ -9,51 +9,81 @@
android:id="@+id/homeFragment" android:id="@+id/homeFragment"
android:name="com.tarkvaraprojekt.mobileauthapp.HomeFragment" android:name="com.tarkvaraprojekt.mobileauthapp.HomeFragment"
android:label="fragment_home" android:label="fragment_home"
tools:layout="@layout/fragment_home" > tools:layout="@layout/fragment_home">
<action <action
android:id="@+id/action_homeFragment_to_pinFragment" android:id="@+id/action_homeFragment_to_settingsFragment"
app:destination="@id/pinFragment" app:destination="@id/settingsFragment"
/> app:popUpTo="@id/homeFragment" />
<action
android:id="@+id/action_homeFragment_to_canFragment"
app:destination="@id/canFragment"
app:popUpTo="@id/homeFragment" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/pinFragment" android:id="@+id/pinFragment"
android:name="com.tarkvaraprojekt.mobileauthapp.PinFragment" android:name="com.tarkvaraprojekt.mobileauthapp.PinFragment"
android:label="fragment_pin" android:label="fragment_pin"
tools:layout="@layout/fragment_pin" > tools:layout="@layout/fragment_pin">
<action
android:id="@+id/action_pinFragment_to_canFragment"
app:destination="@id/canFragment"
app:popUpTo="@id/homeFragment" />
<action <action
android:id="@+id/action_pinFragment_to_homeFragment" android:id="@+id/action_pinFragment_to_homeFragment"
app:destination="@id/homeFragment" app:destination="@id/homeFragment"
app:popUpTo="@id/homeFragment" app:popUpTo="@id/homeFragment"
app:popUpToInclusive="true" /> app:popUpToInclusive="true" />
<action
android:id="@+id/action_pinFragment_to_settingsFragment"
app:destination="@id/settingsFragment"
app:popUpTo="@id/settingsFragment"
app:popUpToInclusive="true" />
<argument
android:name="saving"
android:defaultValue="false"
app:argType="boolean" />
<action
android:id="@+id/action_pinFragment_to_authFragment"
app:destination="@id/authFragment"
app:popUpTo="@id/homeFragment" />
<argument
android:name="reading"
app:argType="boolean"
android:defaultValue="false" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/canFragment" android:id="@+id/canFragment"
android:name="com.tarkvaraprojekt.mobileauthapp.CanFragment" android:name="com.tarkvaraprojekt.mobileauthapp.CanFragment"
android:label="fragment_can" android:label="fragment_can"
tools:layout="@layout/fragment_can" > tools:layout="@layout/fragment_can">
<action
android:id="@+id/action_canFragment_to_authFragment"
app:destination="@id/authFragment"
app:popUpTo="@id/homeFragment"/>
<action <action
android:id="@+id/action_canFragment_to_homeFragment" android:id="@+id/action_canFragment_to_homeFragment"
app:destination="@id/homeFragment" app:destination="@id/homeFragment"
app:popUpTo="@id/homeFragment" app:popUpTo="@id/homeFragment"
app:popUpToInclusive="true" /> app:popUpToInclusive="true" />
<action
android:id="@+id/action_canFragment_to_settingsFragment"
app:destination="@id/settingsFragment"
app:popUpTo="@id/settingsFragment"
app:popUpToInclusive="true" />
<argument
android:name="saving"
android:defaultValue="false"
app:argType="boolean" />
<action
android:id="@+id/action_canFragment_to_pinFragment"
app:destination="@id/pinFragment"
app:popUpTo="@id/homeFragment" />
<argument
android:name="reading"
app:argType="boolean"
android:defaultValue="false" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/authFragment" android:id="@+id/authFragment"
android:name="com.tarkvaraprojekt.mobileauthapp.AuthFragment" android:name="com.tarkvaraprojekt.mobileauthapp.AuthFragment"
android:label="fragment_auth" android:label="fragment_auth"
tools:layout="@layout/fragment_auth" > tools:layout="@layout/fragment_auth">
<action <action
android:id="@+id/action_authFragment_to_userFragment" android:id="@+id/action_authFragment_to_userFragment"
app:destination="@id/userFragment" app:destination="@id/userFragment"
app:popUpTo="@id/homeFragment"/> app:popUpTo="@id/homeFragment" />
<action <action
android:id="@+id/action_authFragment_to_homeFragment" android:id="@+id/action_authFragment_to_homeFragment"
app:destination="@id/homeFragment" app:destination="@id/homeFragment"
@ -64,11 +94,28 @@
android:id="@+id/userFragment" android:id="@+id/userFragment"
android:name="com.tarkvaraprojekt.mobileauthapp.UserFragment" android:name="com.tarkvaraprojekt.mobileauthapp.UserFragment"
android:label="fragment_user" android:label="fragment_user"
tools:layout="@layout/fragment_user" > tools:layout="@layout/fragment_user">
<action <action
android:id="@+id/action_userFragment_to_homeFragment" android:id="@+id/action_userFragment_to_homeFragment"
app:destination="@id/homeFragment" app:destination="@id/homeFragment"
app:popUpTo="@id/homeFragment" app:popUpTo="@id/homeFragment"
app:popUpToInclusive="true"/> app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/settingsFragment"
android:name="com.tarkvaraprojekt.mobileauthapp.menu.SettingsFragment"
android:label="fragment_settings"
tools:layout="@layout/fragment_settings">
<action
android:id="@+id/action_settingsFragment_to_canFragment"
app:destination="@id/canFragment" />
<action
android:id="@+id/action_settingsFragment_to_pinFragment"
app:destination="@id/pinFragment" />
<action
android:id="@+id/action_settingsFragment_to_homeFragment"
app:destination="@id/homeFragment"
app:popUpTo="@id/homeFragment"
app:popUpToInclusive="true" />
</fragment> </fragment>
</navigation> </navigation>

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Must translate to English, but should work now -->
<string name="app_name">NFC authentication</string>
<string name="home_fragment">Work in progress</string>
<!-- string resources for HomeFragment -->
<string name="pin_status_saved">PIN 1 on salvestatud</string>
<string name="pin_status_negative">PIN 1 ei ole salvestatud</string>
<string name="can_status_saved">CAN on salvestatud</string>
<string name="can_status_negative">CAN ei ole salvestatud</string>
<string name="begin_text">LOE ID KAARTI</string>
<string name="next_text">EDASI</string>
<string name="cancel_text">KATKESTA</string>
<string name="save_text">SALVESTA</string>
<string name="deny_text">EI</string>
<string name="return_text">TAGASI</string>
<!-- string resources for PinFragment -->
<string name="pin_fragment">Palun sisesta PIN 1</string>
<string name="enter_pin">PIN 1</string>
<string name="example_pin">Näide. 1234</string>
<string name="length_pin">PIN 1 lubatud pikkus on 4..12</string>
<string name="pin_save_request">Praegu ei ole rakenduses PIN 1 salvestatud. Kas sa soovid sisestatud PIN 1-te salvestada? Sellisel juhul sisestatakse see järgmisel korral automaatselt. Salvestatud PIN 1-te saab alati menüüs muuta ja kustutada.</string>
<string name="save_pin_title">Salvesta PIN 1</string>
<!-- string resources for CanFragment -->
<string name="example_can">Näide. 123456</string>
<string name="text_can">CAN</string>
<string name="enter_can">Sisesta ID kaardi CAN (Card Access Number)</string>
<string name="length_can">CANi pikkus on vale</string>
<string name="card_detected">Kaart on tuvastatud. Hoia kaarti vastu telefoni.</string>
<string name="data_read">Andmed loetud. Võid edasi minna.</string>
<string name="can_save_request">Praegu ei ole rakenduses CAN salvestatud. Kas sa soovid sisestatud CANi salvestada? Sellisel juhul sisestatakse see järgmisel korral automaatselt. Salvestatud CANi saab alati menüüs muuta ja kustutada.</string>
<string name="save_can_title">Salvesta CAN</string>
<!-- string resources for AuthFragment layout -->
<string name="auth_instruction_text">ID kaardiga ühenduse loomiseks pane kaart vastu telefoni</string>
<string name="time_left">Aega on jäänud %d sek</string>
<string name="no_time">Aeg on otsas</string>
<string name="no_success">Vale CAN</string>
<!-- string resources for UserFragment layout -->
<string name="user_name_label">NIMI</string>
<string name="user_name">%1$s %2$s</string>
<string name="identification_number_label">ISIKUKOOD</string>
<string name="expiration_label">KEHTIV KUNI</string>
<string name="citizenship_label">KODAKONDSUS</string>
<string name="gender_label">SUGU</string>
<string name="clear_button">UNUSTA</string>
<!-- menu -->
<string name="menu_settings_title">Seaded</string>
<string name="menu_language_title">Keel</string>
<string name="menu_action_unavailable">Toiming pole hetkel saadaval</string>
<string name="saved_can">CAN: %s</string>
<string name="can_add">Lisa CAN</string>
<string name="can_delete">Kustuta CAN</string>
<string name="saved_pin">PIN1: %s</string>
<string name="pin1_add">Lisa PIN1</string>
<string name="pin1_delete">Kustuta PIN1</string>
<string name="missing">puudub</string>
<string name="show">NÄITA</string>
<string name="hide">PEIDA</string>
<string name="hidden_pin">****</string>
<string name="unavailable">Seaded pole hetkel saadaval</string>
</resources>

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">NFC authentication</string>
<string name="home_fragment">Work in progress</string>
<string name="begin_text">LOE ID KAARTI</string>
<string name="next_text">EDASI</string>
<string name="cancel_text">KATKESTA</string>
<string name="save_text">SALVESTA</string>
<string name="deny_text">EI</string>
<string name="return_text">TAGASI</string>
<!-- string resources for HomeFragment -->
<string name="pin_status_saved">PIN 1 on salvestatud</string>
<string name="pin_status_negative">PIN 1 ei ole salvestatud</string>
<string name="can_status_saved">CAN on salvestatud</string>
<string name="can_status_negative">CAN ei ole salvestatud</string>
<!-- string resources for PinFragment -->
<string name="pin_fragment">Palun sisesta PIN 1</string>
<string name="enter_pin">PIN 1</string>
<string name="example_pin">Näide. 1234</string>
<string name="length_pin">PIN 1 lubatud pikkus on 4..12</string>
<string name="pin_save_request">Praegu ei ole rakenduses PIN 1 salvestatud. Kas sa soovid sisestatud PIN 1-te salvestada? Sellisel juhul sisestatakse see järgmisel korral automaatselt. Salvestatud PIN 1-te saab alati menüüs muuta ja kustutada.</string>
<string name="save_pin_title">Salvesta PIN 1</string>
<!-- string resources for CanFragment -->
<string name="example_can">Näide. 123456</string>
<string name="text_can">CAN</string>
<string name="enter_can">Sisesta ID kaardi CAN (Card Access Number)</string>
<string name="length_can">CANi pikkus on vale</string>
<string name="card_detected">Kaart on tuvastatud. Hoia kaarti vastu telefoni.</string>
<string name="data_read">Andmed loetud. Võid edasi minna.</string>
<string name="can_save_request">Praegu ei ole rakenduses CAN salvestatud. Kas sa soovid sisestatud CANi salvestada? Sellisel juhul sisestatakse see järgmisel korral automaatselt. Salvestatud CANi saab alati menüüs muuta ja kustutada.</string> <string name="save_can_title">Salvesta CAN</string>
<!-- string resources for AuthFragment layout -->
<string name="auth_instruction_text">ID kaardiga ühenduse loomiseks pane kaart vastu telefoni</string>
<string name="time_left">Aega on jäänud %d sek</string>
<string name="no_time">Aeg on otsas</string>
<string name="no_success">Vale CAN</string>
<!-- string resources for UserFragment layout -->
<string name="user_name_label">NIMI</string>
<string name="user_name">%1$s %2$s</string>
<string name="identification_number_label">ISIKUKOOD</string>
<string name="clear_button">UNUSTA</string>
<string name="expiration_label">KEHTIV KUNI</string>
<string name="citizenship_label">KODAKONDSUS</string>
<string name="gender_label">SUGU</string>
<!-- menu -->
<string name="menu_settings_title">Seaded</string>
<string name="menu_language_title">Keel</string>
<string name="menu_action_unavailable">Toiming pole hetkel saadaval</string>
<string name="saved_can">CAN: %s</string>
<string name="can_add">Lisa CAN</string>
<string name="can_delete">Kustuta CAN</string>
<string name="saved_pin">PIN1: %s</string>
<string name="pin1_add">Lisa PIN1</string>
<string name="pin1_delete">Kustuta PIN1</string>
<string name="missing">puudub</string>
<string name="show">NÄITA</string>
<string name="hide">PEIDA</string>
<string name="hidden_pin">****</string>
<string name="unavailable">Seaded pole hetkel saadaval</string>
</resources>

View File

@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.MobileAuthApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <style name="Theme.MobileAuthApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/blue_200</item> <item name="colorPrimary">@color/blue_200</item>
<item name="colorPrimaryVariant">@color/blue_700</item> <item name="colorPrimaryVariant">@color/blue_700</item>

View File

@ -13,5 +13,4 @@
<color name="blue_700">#1976d2</color> <color name="blue_700">#1976d2</color>
<color name="orange_200">#ffcc80</color> <color name="orange_200">#ffcc80</color>
<color name="orange_700">#f57c00</color> <color name="orange_700">#f57c00</color>
</resources> </resources>

View File

@ -1,16 +1,27 @@
<resources> <resources>
<string name="app_name">Mobile Authenticator</string> <string name="app_name">NFC authentication</string>
<string name="home_fragment">Work in progress</string> <string name="home_fragment">Work in progress</string>
<string name="begin_text">ALUSTA</string> <string name="begin_text">LOE ID KAARTI</string>
<string name="next_text">EDASI</string> <string name="next_text">EDASI</string>
<string name="cancel_text">KATKESTA</string> <string name="cancel_text">KATKESTA</string>
<string name="save_text">SALVESTA</string>
<string name="deny_text">EI</string>
<string name="return_text">TAGASI</string>
<!-- string resources for HomeFragment -->
<string name="pin_status_saved">PIN 1 on salvestatud</string>
<string name="pin_status_negative">PIN 1 ei ole salvestatud</string>
<string name="can_status_saved">CAN on salvestatud</string>
<string name="can_status_negative">CAN ei ole salvestatud</string>
<!-- string resources for PinFragment --> <!-- string resources for PinFragment -->
<string name="pin_fragment">Palun sisesta PIN 1</string> <string name="pin_fragment">Palun sisesta PIN 1</string>
<string name="enter_pin">PIN 1</string> <string name="enter_pin">PIN 1</string>
<string name="example_pin">Näide. 1234</string> <string name="example_pin">Näide. 1234</string>
<string name="length_pin">PIN 1 lubatud pikkus on 4..12</string> <string name="length_pin">PIN 1 lubatud pikkus on 4..12</string>
<string name="pin_save_request">Praegu ei ole rakenduses PIN 1 salvestatud. Kas sa soovid sisestatud PIN 1-te salvestada? Sellisel juhul sisestatakse see järgmisel korral automaatselt. Salvestatud PIN 1-te saab alati menüüs muuta ja kustutada.</string>
<string name="save_pin_title">Salvesta PIN 1</string>
<!-- string resources for CanFragment --> <!-- string resources for CanFragment -->
<string name="example_can">Näide. 123456</string> <string name="example_can">Näide. 123456</string>
@ -19,6 +30,8 @@
<string name="length_can">CANi pikkus on vale</string> <string name="length_can">CANi pikkus on vale</string>
<string name="card_detected">Kaart on tuvastatud. Hoia kaarti vastu telefoni.</string> <string name="card_detected">Kaart on tuvastatud. Hoia kaarti vastu telefoni.</string>
<string name="data_read">Andmed loetud. Võid edasi minna.</string> <string name="data_read">Andmed loetud. Võid edasi minna.</string>
<string name="can_save_request">Praegu ei ole rakenduses CAN salvestatud. Kas sa soovid sisestatud CANi salvestada? Sellisel juhul sisestatakse see järgmisel korral automaatselt. Salvestatud CANi saab alati menüüs muuta ja kustutada.</string>
<string name="save_can_title">Salvesta CAN</string>
<!-- string resources for AuthFragment layout --> <!-- string resources for AuthFragment layout -->
<string name="auth_instruction_text">ID kaardiga ühenduse loomiseks pane kaart vastu telefoni</string> <string name="auth_instruction_text">ID kaardiga ühenduse loomiseks pane kaart vastu telefoni</string>
@ -30,5 +43,24 @@
<string name="user_name_label">NIMI</string> <string name="user_name_label">NIMI</string>
<string name="user_name">%1$s %2$s</string> <string name="user_name">%1$s %2$s</string>
<string name="identification_number_label">ISIKUKOOD</string> <string name="identification_number_label">ISIKUKOOD</string>
<string name="expiration_label">KEHTIV KUNI</string>
<string name="citizenship_label">KODAKONDSUS</string>
<string name="gender_label">SUGU</string>
<string name="clear_button">UNUSTA</string> <string name="clear_button">UNUSTA</string>
<!-- menu -->
<string name="menu_settings_title">Seaded</string>
<string name="menu_language_title">Keel</string>
<string name="menu_action_unavailable">Toiming pole hetkel saadaval</string>
<string name="saved_can">CAN: %s</string>
<string name="can_add">Lisa CAN</string>
<string name="can_delete">Kustuta CAN</string>
<string name="saved_pin">PIN1: %s</string>
<string name="pin1_add">Lisa PIN 1</string>
<string name="pin1_delete">Kustuta PIN 1</string>
<string name="missing">puudub</string>
<string name="show">NÄITA</string>
<string name="hide">PEIDA</string>
<string name="hidden_pin">****</string>
<string name="unavailable">Seaded pole hetkel saadaval</string>
</resources> </resources>

View File

@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.MobileAuthApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <style name="Theme.MobileAuthApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/blue_500</item> <item name="colorPrimary">@color/blue_500</item>
<item name="colorPrimaryVariant">@color/blue_700</item> <item name="colorPrimaryVariant">@color/blue_700</item>