diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 61da587..fc2cb02 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,13 +18,19 @@ tools:targetApi="31"> + android:exported="true" + android:launchMode="singleTop"> + + + + + diff --git a/app/src/main/java/com/example/palto/PaltoActivity.kt b/app/src/main/java/com/example/palto/PaltoActivity.kt index 1df8c28..8a70afa 100644 --- a/app/src/main/java/com/example/palto/PaltoActivity.kt +++ b/app/src/main/java/com/example/palto/PaltoActivity.kt @@ -5,42 +5,46 @@ import android.nfc.Tag import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity +import androidx.activity.viewModels class PaltoActivity : AppCompatActivity() { + private var nfcAdapter: NfcAdapter? = null + private val paltoViewModel: PaltoViewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_palto) // get the NFC Adapter - this.nfcAdapter = NfcAdapter.getDefaultAdapter(this) + nfcAdapter = NfcAdapter.getDefaultAdapter(this) // check if NFC is supported - if (this.nfcAdapter == null) { + if (nfcAdapter == null) { Log.e("NFC", "NFC is not supported") return } // check if NFC is disabled - if (!(this.nfcAdapter!!.isEnabled)) { + if (nfcAdapter?.isEnabled == false) { Log.w("NFC", "NFC is not enabled") } - // TEST - /* + setContentView(R.layout.activity_palto) + /* val url = URL("https://www.faraphel.fr/palto/api/auth/token/") val connection = url.openConnection() - val auth_data = Json.decodeFromString(connection.content)*/ + val auth_data = Json.decodeFromString(connection.content) + */ } override fun onResume() { super.onResume() - nfcAdapter!!.enableReaderMode( + nfcAdapter?.enableReaderMode( this, - this::processTag, + paltoViewModel.tagLiveData::postValue, NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null ) @@ -50,11 +54,11 @@ class PaltoActivity : AppCompatActivity() { super.onPause() // disable the NFC discovery - this.nfcAdapter!!.disableReaderMode(this) + nfcAdapter?.disableReaderMode(this) } @OptIn(ExperimentalStdlibApi::class) fun processTag(tag: Tag) { - Log.d("NFC", "Tag ID : ${tag.id.toHexString()}") + Log.d("NFC", "Tag ID : " + tag.id.toHexString()) } } diff --git a/app/src/main/java/com/example/palto/PaltoViewModel.kt b/app/src/main/java/com/example/palto/PaltoViewModel.kt new file mode 100644 index 0000000..9d69dc4 --- /dev/null +++ b/app/src/main/java/com/example/palto/PaltoViewModel.kt @@ -0,0 +1,9 @@ +package com.example.palto + +import android.nfc.Tag +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class PaltoViewModel: ViewModel() { + val tagLiveData = MutableLiveData() +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/model/Card.kt b/app/src/main/java/com/example/palto/model/Card.kt index fade8d9..8c55422 100644 --- a/app/src/main/java/com/example/palto/model/Card.kt +++ b/app/src/main/java/com/example/palto/model/Card.kt @@ -2,5 +2,22 @@ package com.example.palto.model import java.io.Serializable data class Card( - val id: String -) : Serializable \ No newline at end of file + val id: String, + val uid: ByteArray, + val department: String, + val owner: String +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as Card + + return uid.contentEquals(other.uid) + } + + override fun hashCode(): Int { + return uid.contentHashCode() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListAdapter.kt b/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListAdapter.kt index 565422c..a7788b1 100644 --- a/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListAdapter.kt +++ b/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListAdapter.kt @@ -1,14 +1,13 @@ package com.example.palto.ui.attendanceList -import androidx.recyclerview.widget.RecyclerView import android.view.LayoutInflater import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter -import com.example.palto.model.Card - +import androidx.recyclerview.widget.RecyclerView import com.example.palto.databinding.FragmentAttendanceItemBinding +import com.example.palto.model.Card /** * @@ -30,9 +29,10 @@ class AttendanceListAdapter : ) } + @OptIn(ExperimentalStdlibApi::class) override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = getItem(position) - holder.cardId.text = item.id + holder.cardId.text = item.uid.toHexString() //holder.contentView.text = item.content } diff --git a/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListFragment.kt b/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListFragment.kt index 598ef9e..68773ab 100644 --- a/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListFragment.kt +++ b/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListFragment.kt @@ -1,13 +1,17 @@ package com.example.palto.ui.attendanceList +import android.nfc.NfcAdapter +import android.nfc.Tag import android.os.Bundle -import androidx.fragment.app.Fragment -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Observer import androidx.navigation.navGraphViewModels +import com.example.palto.PaltoViewModel import com.example.palto.R import com.example.palto.databinding.FragmentAttendanceListBinding @@ -17,22 +21,49 @@ import com.example.palto.databinding.FragmentAttendanceListBinding class AttendanceListFragment : Fragment() { private val attendanceListViewModel: AttendanceListViewModel by - navGraphViewModels(R.id.nav_graph) + navGraphViewModels(R.id.nav_graph) { AttendanceListViewModel.Factory } + private val paltoViewModel: PaltoViewModel by + activityViewModels() + + private var _binding: FragmentAttendanceListBinding? = null + // This property is only valid between onCreateView and onDestroyView + private val binding get() = _binding!! + + /** + * Only inflate the view. + */ override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - val binding = FragmentAttendanceListBinding.inflate(inflater, container, false) - - val adapter = AttendanceListAdapter() - binding.list.adapter = adapter - - attendanceListViewModel.cardsLiveData.observe(viewLifecycleOwner) { - it -> adapter.submitList(it) - } + _binding = FragmentAttendanceListBinding.inflate(inflater, container, false) return binding.root } + + /** + * Logic on the returned view of onCreateView. + */ + override fun onViewCreated( + view: View, + savedInstanceState: Bundle? + ) { + super.onViewCreated(view, savedInstanceState) + + // Set the adapter of the view for managing automatically the list of items on the screen. + val adapter = AttendanceListAdapter() + binding.list.adapter = adapter + attendanceListViewModel.cardsLiveData.observe(viewLifecycleOwner) { + Log.d("NFC", "A card has been had to the list") + adapter.submitList(it) + } + + // Set the listener for a new NFC tag. + paltoViewModel.tagLiveData.observe(viewLifecycleOwner) { + Log.d("NFC", "tag observer has been notified") + attendanceListViewModel.insertCard(it) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListViewModel.kt b/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListViewModel.kt index 5e366d2..a4efa38 100644 --- a/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListViewModel.kt +++ b/app/src/main/java/com/example/palto/ui/attendanceList/AttendanceListViewModel.kt @@ -1,5 +1,7 @@ package com.example.palto.ui.attendanceList +import android.nfc.Tag +import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -7,32 +9,41 @@ import androidx.lifecycle.ViewModelProvider import com.example.palto.data.network.ServerDataSource import com.example.palto.data.repository.AttendanceRepository import com.example.palto.model.Card -import kotlin.random.Random +/** + * ViewModel of a session which has a list of attendances. + */ class AttendanceListViewModel( private val attendanceRepository: AttendanceRepository ) : ViewModel() { - private val cardsList: MutableList = mutableListOf() - val cardsLiveData: LiveData> = MutableLiveData(cardsList) + val cardsLiveData: MutableLiveData> = MutableLiveData(emptyList()) - fun insertCard(cardId: String) { - val card = Card(cardId) - cardsList.add(card) + fun insertCard(tag: Tag) { + val card = Card( + "0", + tag.id, + "tmp", + "tmp" + ) + cardsLiveData.value = (cardsLiveData.value ?: emptyList()) + card + Log.d("NFC", "view model: A card has been had to the list") + } + + /** + * ViewModel Factory. + */ + companion object { + + val Factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun create( + modelClass: Class + ): T { + return AttendanceListViewModel( + AttendanceRepository(ServerDataSource()) + ) as T + } + } } } - -class AttendanceListViewModelFactory : ViewModelProvider.Factory { - - //@Suppress("UNCHECKED_CAST") - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(AttendanceListViewModel::class.java)) { - return AttendanceListViewModel( - attendanceRepository = AttendanceRepository( - dataSource = ServerDataSource() - ) - ) as T - } - throw IllegalArgumentException("Unknown ViewModel class") - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/palto/ui/login/LoginFragment.kt b/app/src/main/java/com/example/palto/ui/login/LoginFragment.kt index 93b53e6..acf12be 100644 --- a/app/src/main/java/com/example/palto/ui/login/LoginFragment.kt +++ b/app/src/main/java/com/example/palto/ui/login/LoginFragment.kt @@ -24,8 +24,7 @@ class LoginFragment : Fragment() { private var _binding: FragmentLoginBinding? = null - // This property is only valid between onCreateView and - // onDestroyView. + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView( @@ -73,7 +72,7 @@ class LoginFragment : Fragment() { showLoginFailed(it) } loginResult.success?.let { - findNavController().navigate(R.id.action_loginFragment_to_attendanceFragment) + //findNavController().navigate(R.id.action_loginFragment_to_attendanceFragment) //updateUiWithUser(it) } }) diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index f87aa9a..4b9c3fd 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -3,23 +3,19 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" - app:startDestination="@id/loginFragment"> + app:startDestination="@id/attendanceListFragment"> - - + tools:layout="@layout/fragment_login" /> diff --git a/build.gradle.kts b/build.gradle.kts index ef164ea..8e8f4ab 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.application") version "8.1.4" apply false + id("com.android.application") version "8.2.0" apply false id("org.jetbrains.kotlin.android") version "1.9.0" apply false } \ No newline at end of file