AttendanceList fonctionnelle avec lecture des cartes NFC

This commit is contained in:
biloute02 2023-12-30 17:46:08 +01:00
parent 0775eb13da
commit d7bade2287
10 changed files with 135 additions and 62 deletions

View file

@ -18,13 +18,19 @@
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".PaltoActivity" android:name=".PaltoActivity"
android:exported="true" > android:exported="true"
android:launchMode="singleTop">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity> </activity>
</application> </application>

View file

@ -5,42 +5,46 @@ import android.nfc.Tag
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.activity.viewModels
class PaltoActivity : AppCompatActivity() { class PaltoActivity : AppCompatActivity() {
private var nfcAdapter: NfcAdapter? = null private var nfcAdapter: NfcAdapter? = null
private val paltoViewModel: PaltoViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_palto)
// get the NFC Adapter // get the NFC Adapter
this.nfcAdapter = NfcAdapter.getDefaultAdapter(this) nfcAdapter = NfcAdapter.getDefaultAdapter(this)
// check if NFC is supported // check if NFC is supported
if (this.nfcAdapter == null) { if (nfcAdapter == null) {
Log.e("NFC", "NFC is not supported") Log.e("NFC", "NFC is not supported")
return return
} }
// check if NFC is disabled // check if NFC is disabled
if (!(this.nfcAdapter!!.isEnabled)) { if (nfcAdapter?.isEnabled == false) {
Log.w("NFC", "NFC is not enabled") 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 url = URL("https://www.faraphel.fr/palto/api/auth/token/")
val connection = url.openConnection() val connection = url.openConnection()
val auth_data = Json.decodeFromString(connection.content)*/ val auth_data = Json.decodeFromString(connection.content)
*/
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
nfcAdapter!!.enableReaderMode( nfcAdapter?.enableReaderMode(
this, this,
this::processTag, paltoViewModel.tagLiveData::postValue,
NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK,
null null
) )
@ -50,11 +54,11 @@ class PaltoActivity : AppCompatActivity() {
super.onPause() super.onPause()
// disable the NFC discovery // disable the NFC discovery
this.nfcAdapter!!.disableReaderMode(this) nfcAdapter?.disableReaderMode(this)
} }
@OptIn(ExperimentalStdlibApi::class) @OptIn(ExperimentalStdlibApi::class)
fun processTag(tag: Tag) { fun processTag(tag: Tag) {
Log.d("NFC", "Tag ID : ${tag.id.toHexString()}") Log.d("NFC", "Tag ID : " + tag.id.toHexString())
} }
} }

View file

@ -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<Tag>()
}

View file

@ -2,5 +2,22 @@ package com.example.palto.model
import java.io.Serializable import java.io.Serializable
data class Card( data class Card(
val id: String val id: String,
) : Serializable 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()
}
}

View file

@ -1,14 +1,13 @@
package com.example.palto.ui.attendanceList package com.example.palto.ui.attendanceList
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter 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.databinding.FragmentAttendanceItemBinding
import com.example.palto.model.Card
/** /**
* *
@ -30,9 +29,10 @@ class AttendanceListAdapter :
) )
} }
@OptIn(ExperimentalStdlibApi::class)
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = getItem(position) val item = getItem(position)
holder.cardId.text = item.id holder.cardId.text = item.uid.toHexString()
//holder.contentView.text = item.content //holder.contentView.text = item.content
} }

View file

@ -1,13 +1,17 @@
package com.example.palto.ui.attendanceList package com.example.palto.ui.attendanceList
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.navigation.navGraphViewModels import androidx.navigation.navGraphViewModels
import com.example.palto.PaltoViewModel
import com.example.palto.R import com.example.palto.R
import com.example.palto.databinding.FragmentAttendanceListBinding import com.example.palto.databinding.FragmentAttendanceListBinding
@ -17,22 +21,49 @@ import com.example.palto.databinding.FragmentAttendanceListBinding
class AttendanceListFragment : Fragment() { class AttendanceListFragment : Fragment() {
private val attendanceListViewModel: AttendanceListViewModel by 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( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): 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 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)
}
}
} }

View file

@ -1,5 +1,7 @@
package com.example.palto.ui.attendanceList package com.example.palto.ui.attendanceList
import android.nfc.Tag
import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@ -7,32 +9,41 @@ import androidx.lifecycle.ViewModelProvider
import com.example.palto.data.network.ServerDataSource import com.example.palto.data.network.ServerDataSource
import com.example.palto.data.repository.AttendanceRepository import com.example.palto.data.repository.AttendanceRepository
import com.example.palto.model.Card import com.example.palto.model.Card
import kotlin.random.Random
/**
* ViewModel of a session which has a list of attendances.
*/
class AttendanceListViewModel( class AttendanceListViewModel(
private val attendanceRepository: AttendanceRepository private val attendanceRepository: AttendanceRepository
) : ViewModel() { ) : ViewModel() {
private val cardsList: MutableList<Card> = mutableListOf() val cardsLiveData: MutableLiveData<List<Card>> = MutableLiveData(emptyList())
val cardsLiveData: LiveData<List<Card>> = MutableLiveData(cardsList)
fun insertCard(cardId: String) { fun insertCard(tag: Tag) {
val card = Card(cardId) val card = Card(
cardsList.add(card) "0",
} tag.id,
} "tmp",
"tmp"
class AttendanceListViewModelFactory : ViewModelProvider.Factory {
//@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(AttendanceListViewModel::class.java)) {
return AttendanceListViewModel(
attendanceRepository = AttendanceRepository(
dataSource = ServerDataSource()
) )
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 <T : ViewModel> create(
modelClass: Class<T>
): T {
return AttendanceListViewModel(
AttendanceRepository(ServerDataSource())
) as T ) as T
} }
throw IllegalArgumentException("Unknown ViewModel class") }
} }
} }

View file

@ -24,8 +24,7 @@ class LoginFragment : Fragment() {
private var _binding: FragmentLoginBinding? = null private var _binding: FragmentLoginBinding? = null
// This property is only valid between onCreateView and // This property is only valid between onCreateView and onDestroyView.
// onDestroyView.
private val binding get() = _binding!! private val binding get() = _binding!!
override fun onCreateView( override fun onCreateView(
@ -73,7 +72,7 @@ class LoginFragment : Fragment() {
showLoginFailed(it) showLoginFailed(it)
} }
loginResult.success?.let { loginResult.success?.let {
findNavController().navigate(R.id.action_loginFragment_to_attendanceFragment) //findNavController().navigate(R.id.action_loginFragment_to_attendanceFragment)
//updateUiWithUser(it) //updateUiWithUser(it)
} }
}) })

View file

@ -3,23 +3,19 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph" android:id="@+id/nav_graph"
app:startDestination="@id/loginFragment"> app:startDestination="@id/attendanceListFragment">
<fragment <fragment
android:id="@+id/loginFragment" android:id="@+id/loginFragment"
android:name="com.example.palto.ui.login.LoginFragment" android:name="com.example.palto.ui.login.LoginFragment"
android:label="fragment._login" android:label="fragment._login"
tools:layout="@layout/fragment_login" > tools:layout="@layout/fragment_login" />
<action
android:id="@+id/action_loginFragment_to_attendanceFragment"
app:destination="@id/attendanceFragment" />
</fragment>
<fragment <fragment
android:id="@+id/sessionListFragment" android:id="@+id/sessionListFragment"
android:name="com.example.palto.ui.sessionList.SessionListFragment" android:name="com.example.palto.ui.sessionList.SessionListFragment"
android:label="fragment_session_list" android:label="fragment_session_list"
tools:layout="@layout/fragment_session_list" /> tools:layout="@layout/fragment_session_list" />
<fragment <fragment
android:id="@+id/attendanceFragment" android:id="@+id/attendanceListFragment"
android:name="com.example.palto.ui.attendanceList.AttendanceListFragment" android:name="com.example.palto.ui.attendanceList.AttendanceListFragment"
android:label="fragment_attendance_list" android:label="fragment_attendance_list"
tools:layout="@layout/fragment_attendance_list" /> tools:layout="@layout/fragment_attendance_list" />

View file

@ -1,5 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { 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 id("org.jetbrains.kotlin.android") version "1.9.0" apply false
} }