i have an app that scan a nfc tag uid and check in a local database (in the downloads folder) if the uid is present and a the good time (between start date and end date written inside database.csv). the goal is to give access or not. It works on android 6 and 7 but from android 13 i'm not able to modify the code in order to give access to this file for the app.(due to READ_EXTERNAL_STORAGE deprecated). Do you have an idea if it's possible? i saw some thing about mediastore and Storage Access Framework but i'm not able to understand what i need to modify.
the full code is here in case of :
class MainActivity : Activity() {
private var nfcAdapter: NfcAdapter? = null
private lateinit var resultTextView: TextView
private lateinit var statusTextView: TextView
private lateinit var compteurTextView: TextView
private lateinit var resetButton: Button
// Liste des informations sur les tags valides (UID, dates de validité)
private var validTags = mutableListOf<TagInfo>()
// Compteur du nombre de tags valides scannés
private var compteur = 0
// Service de vibration
private lateinit var vibrator: Vibrator
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initialisation des éléments de l'interface
resultTextView = findViewById(R.id.resultTextView)
statusTextView = findViewById(R.id.statusTextView)
compteurTextView = findViewById(R.id.compteurTextView)
resetButton = findViewById(R.id.resetButton)
// Initialisation de l'adaptateur NFC
nfcAdapter = NfcAdapter.getDefaultAdapter(this)
if (nfcAdapter == null) {
Toast.makeText(this, "Pas de NFC sur ce téléphone", Toast.LENGTH_SHORT).show()
finish()
return
}
if (!nfcAdapter!!.isEnabled) {
Toast.makeText(this, "NFC est désactivé...", Toast.LENGTH_SHORT).show()
}
// Initialisation du service de vibration
vibrator = getSystemService(VIBRATOR_SERVICE) as Vibrator
// Charger le compteur depuis les préférences
loadCounter()
// Vérification des permissions nécessaires
if (checkPermission()) {
// Charger les UIDs et dates de validité depuis le fichier CSV
loadValidUids()
} else {
// Si la permission n'est pas accordée, demandez-la
requestPermission()
}
// Bouton pour réinitialiser le compteur avec confirmation
resetButton.setOnClickListener {
// Afficher une boîte de dialogue de confirmation
val builder = android.app.AlertDialog.Builder(this)
builder.setTitle("Réinitialisation du compteur")
builder.setMessage("Êtes-vous sûr de vouloir réinitialiser le compteur ?")
builder.setPositiveButton("Oui") { dialog, which ->
// Si l'utilisateur confirme, réinitialiser le compteur
compteur = 0
saveCounter() // Sauvegarder le compteur réinitialisé
compteurTextView.text = "Cartes validées: $compteur"
Toast.makeText(this, "Compteur réinitialisé", Toast.LENGTH_SHORT).show()
}
builder.setNegativeButton("Non") { dialog, which ->
// Si l'utilisateur annule, ne rien faire
dialog.dismiss()
}
// Afficher la boîte de dialogue
builder.show()
}
}
// Vérification de la permission
private fun checkPermission(): Boolean {
return ActivityCompat.checkSelfPermission(
this,
Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
}
// Demander la permission de lire le stockage externe
private fun requestPermission() {
// Demander la permission READ_EXTERNAL_STORAGE
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
1 // Code de demande de permission
)
}
// Gérer la réponse à la demande de permission
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 1) { // Code de demande que vous avez utilisé (1 dans ce cas)
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission accordée, charger les UIDs
loadValidUids()
} else {
// Permission refusée, afficher un message d'erreur ou une action alternative
Toast.makeText(this, "Permission de lire les fichiers requise", Toast.LENGTH_SHORT).show()
}
}
}
// Charge les UIDs et les dates de validité depuis un fichier CSV
private fun loadValidUids() {
// Chemin vers le fichier CSV dans le dossier Téléchargement
val filePath = "/storage/emulated/0/Download/database.csv"
val databaseFile = File(filePath)
// Vérifier si le fichier existe
if (databaseFile.exists()) {
try {
// Ouvrir et lire le fichier CSV
val inputStream = FileInputStream(databaseFile)
val reader = BufferedReader(InputStreamReader(inputStream))
// Effacer les anciennes données
validTags.clear()
// Format de date DD/MM/YYYY
val sdf = SimpleDateFormat("dd/MM/yyyy") // Format de date attendu dans le CSV
var line: String? = reader.readLine()
while (line != null) {
val columns = line.split(",") // Séparer les colonnes par la virgule
if (columns.size == 3) {
val uid = columns[0].trim()
val startDate = sdf.parse(columns[1].trim())
val endDate = sdf.parse(columns[2].trim())
// Ajouter le tag à la liste si les données sont valides
validTags.add(TagInfo(uid, startDate, endDate))
}
line = reader.readLine() // Lire la ligne suivante
}
reader.close()
} catch (e: Exception) {
Toast.makeText(this, "Erreur de lecture de la BDD", Toast.LENGTH_SHORT).show()
e.printStackTrace()
}
} else {
Toast.makeText(this, "BDD non trouvée", Toast.LENGTH_SHORT).show()
}
}
// Vérifier si un UID est valide et si la date actuelle est dans la plage de validité
private fun isTagValid(uid: String): Boolean {
val currentDate = Date() // Récupérer la date actuelle
// Chercher le tag dans la liste des tags valides
for (tag in validTags) {
if (tag.uid == uid && currentDate.after(tag.startDate) && currentDate.before(tag.endDate)) {
return true // Le tag est valide
}
}
return false // Le tag n'est pas valide
}
// Gérer le scan NFC lorsqu'une activité est reprise
override fun onResume() {
super.onResume()
// Vérifier si un tag NFC est détecté
if (NfcAdapter.ACTION_TAG_DISCOVERED == intent.action) {
val tag = intent.getParcelableExtra<android.nfc.Tag>(NfcAdapter.EXTRA_TAG)
val uid = tag?.id?.joinToString(":") { "%02x".format(it) }
resultTextView.text = "$uid"
// Vérifier si l'UID existe dans la liste et si la date est valide
if (uid != null && isTagValid(uid.uppercase(Locale.ROOT))) {
// Incrémenter le compteur si le tag est valide
compteur++
saveCounter() // Sauvegarder la valeur mise à jour du compteur
compteurTextView.text = "Cartes validées: $compteur"
// Déclencher la vibration
vibrator.vibrate(500)
// Afficher "OK" en vert
statusTextView.text = "Entrée Autorisée"
statusTextView.setTextColor(ContextCompat.getColor(this, android.R.color.holo_green_dark))
} else {
// Afficher "NOK" en rouge
statusTextView.text = "Entrée Non autorisée"
statusTextView.setTextColor(ContextCompat.getColor(this, android.R.color.holo_red_dark))
}
}
}
// Gérer la nouvelle intention NFC
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
setIntent(intent)
}
// Charger le compteur depuis les préférences
private fun loadCounter() {
val sharedPreferences = getSharedPreferences("AppPreferences", MODE_PRIVATE)
compteur = sharedPreferences.getInt("compteur", 0) // Valeur par défaut à 0
compteurTextView.text = "Cartes validées: $compteur"
}
// Sauvegarder le compteur dans les préférences
private fun saveCounter() {
val sharedPreferences = getSharedPreferences("AppPreferences", MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.putInt("compteur", compteur)
editor.apply() // Appliquer les changements de manière asynchrone
}
}