0

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
}

}

2
  • Just a Note: If you are using the internal storage you don't has to hassle with any permissions Commented Mar 26 at 9:48
  • you mean internal storage of the app? Here my database is created on pc then transfered to "download" folder. This access is automatic by the app to read the .csv file. Commented Mar 26 at 9:57

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.