Datei auf Handy speichern

  • Antworten:2
  • Bentwortet
Robbiani Renato
  • Forum-Beiträge: 648

18.08.2024, 20:35:44 via Website

Hallo zusammen

Ich möchte eine Datei auf dem Handy speichern und wieder lesen. Die App erstelle ich in Kotlin. Dies mache ich mit folgendem Code:

private fun writeToFile(data: String, datname : String) {
    try { //MODE_PRIVATE Daten können nur von der App gelesen werden

// var str_pfad = ctx.applicationInfo.dataDir
// var str_file = File(str_pfad, datname).toString()
val fileOutputStream: FileOutputStream = openFileOutput(datname, MODE_PRIVATE)
fileOutputStream.write(data.toByteArray())
fileOutputStream.close()
} catch (e: Exception) {
e.printStackTrace()
}
}

private fun readFromFile(datname : String): String {
    var fileInputStream: FileInputStream? = null
    var inputStreamReader: InputStreamReader? = null
    var bufferedReader: BufferedReader? = null
    val stringBuilder = StringBuilder()

    try {

// var str_pfad = ctx.applicationInfo.dataDir
// var str_file = File(str_pfad, datname).toString()
fileInputStream = openFileInput(datname)
inputStreamReader = InputStreamReader(fileInputStream)
bufferedReader = BufferedReader(inputStreamReader)

        var text: String? = bufferedReader.readLine()
        while (text != null) {
            text += '\n'
            stringBuilder.append(text)
            text = bufferedReader.readLine()
        }
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        try {
            bufferedReader?.close()
            inputStreamReader?.close()
            fileInputStream?.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    return stringBuilder.toString()
}

Dieser Code läuft auf meinem Handy mit Android 12 ohne Probleme. Mein Kollege hat Android 13 und dort läuft es nicht. Dort kommt die folgende Fehlermeldung:

java.io.FileNotFoundException: /data/user/0/ch.robbisoft.lustigesrechnen/files: open failed: EISDIR (Is a directory)

Wenn ich nun den Dateinamen mit dem Pfad erweitere, läuft die App nicht mehr.

var str_pfad = ctx.applicationInfo.dataDir
var str_file = File(str_pfad, datname).toString()

Das kann ich auch verstehen, weil "openFileInput" keine Trenner akzeptiert. Die Lösungen, welche ich im Internet gefunden habe, funktionieren bei mir nicht.

Wahrscheinlich mache ich grundsätzlich ein Fehler. Darum meine Frage, wie muss ich eine Datei schreiben und lesen, damit es funktioniert?

package ch.robbisoft.lustigesrechnen

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.speech.tts.TextToSpeech
import android.text.Editable
import android.text.TextWatcher
import android.util.AttributeSet
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.widget.EditText
import android.widget.SeekBar
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.*
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.widget.addTextChangedListener
import ch.robbisoft.lustigesrechnen.databinding.ActivityMainBinding
import kotlin.math.abs
import androidx.preference.PreferenceManager
import java.util.Locale
import kotlin.math.absoluteValue
import java.io.*
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

class MainActivity : AppCompatActivity(), TextToSpeech.OnInitListener {

var rechte = arrayOf(
    Manifest.permission.WRITE_EXTERNAL_STORAGE,
    Manifest.permission.READ_EXTERNAL_STORAGE
)
private var str_text: String? = null
private var tts: TextToSpeech? = null

private lateinit var ctx: Context
private lateinit var ac_ctx: Context

private lateinit var binding: ActivityMainBinding
private var zahl_eins: Int = 0
private var zahl_zwei: Int = 0
private var resultat: Int = 0
private var frage : String = ""
private var addi: Boolean = true   //Additionrchnung
private var subi: Boolean = false  //Subtraktionrechnung
private var mult: Boolean = false  //Multiplikationrechnung
private var divi: Boolean = false  //Divisionenrechnung
private var gros: Int = 20         //Wie gross ist der Zahlenraum
private var negativ: Boolean = false //Negative Resultate zulassen
private var hundert: Boolean = true //Hundertergrenze überschreiten zulassen
private var zahl_richtig : Int = 0 // Anzahl der richtig gelösten Aufgaben
private var zahl_falsch : Int = 0 // Anzahl der falsch gelösten Aufgaben
private var str_rechnung : String = "" //Rechnung für Sprachausgabe
private var str_protokoll : String = ""
private var str_proname : String = "" //Name der Protokolldatei
private val formater = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")
private var b_schreib : Boolean = true //Soll ins Protokoll geschrieben werden
                                        //Damit beim Aufruf der Activity anzeige nicht ins Protokoll geschrieben wird

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    binding = ActivityMainBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)

// setContentView(R.layout.activity_main)

    ctx = applicationContext
    ac_ctx = this
    tts = TextToSpeech(ac_ctx, ac_ctx as MainActivity)

    //Daten laden

// val prefs = PreferenceManager.getDefaultSharedPreferences(ac_ctx)
val prefs = ctx.getSharedPreferences("lustig", Context.MODE_PRIVATE)
if (prefs.contains("Key_ad")) {
addi = prefs.getBoolean("Key_ad", true)
subi = prefs.getBoolean("Key_su", true)
mult = prefs.getBoolean("Key_mu", false)
divi = prefs.getBoolean("Key_di", false)
gros = prefs.getInt("Key_gr", 20)
negativ = prefs.getBoolean("Key_negativ", false)
hundert = prefs.getBoolean("Key_hundert", true)
str_proname = prefs.getString("Key_proname", "protokoll.txt").toString()

        binding.edtName.setText(str_proname)
    }

    ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.lay_main)) { v, insets ->
        val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
        v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
        insets
    }

    //Dialog richtig
    val melde_gut = AlertDialog.Builder(this)
    melde_gut.setTitle(resources.getString(R.string.m_gut))
    melde_gut.setMessage(resources.getString(R.string.m_guttext))
    melde_gut.setIcon(ResourcesCompat.getDrawable(getResources(), R.drawable.lachen, null))
    melde_gut.setPositiveButton(resources.getString(R.string.btn_weit)) { _, _ ->
        anzeige()
    }
    //Dialog falsch
    val melde_falsch = AlertDialog.Builder(this)
    melde_falsch.setTitle(resources.getString(R.string.m_fel))
    melde_falsch.setMessage(resources.getString(R.string.m_feltext))
    melde_falsch.setIcon(ResourcesCompat.getDrawable(getResources(), R.drawable.traurig, null))
    melde_falsch.setPositiveButton(resources.getString(R.string.btn_weit)) { _, _ ->
        str_protokoll += frage + '\n'
    }

    anzeige()

    binding.btnEins.setOnClickListener {
        var button_res = binding.btnEins.text.toString()
        if (teste(button_res)) {
            zahl_richtig++
            melde_gut.show()
        } else {
            zahl_falsch++
            binding.txtAnzahl.setText(getAnzahl(zahl_richtig, zahl_falsch))
            melde_falsch.show()
        }
    }

    binding.btnZwei.setOnClickListener {
        var button_res = binding.btnZwei.text.toString()
        if (teste(button_res)) {
            zahl_richtig++
            melde_gut.show()
        } else {
            zahl_falsch++
            binding.txtAnzahl.setText(getAnzahl(zahl_richtig, zahl_falsch))
            melde_falsch.show()
        }
    }

    binding.btnDrei.setOnClickListener {
        var button_res = binding.btnDrei.text.toString()
        if (teste(button_res)) {
            zahl_richtig++
            binding.txtAnzahl.setText(getAnzahl(zahl_richtig, zahl_falsch))
            melde_gut.show()
        } else {
            zahl_falsch++
            binding.txtAnzahl.setText(getAnzahl(zahl_richtig, zahl_falsch))
            melde_falsch.show()
        }
    }

    binding.btnVier.setOnClickListener {
        var button_res = binding.btnVier.text.toString()
        if (teste(button_res)) {
            zahl_richtig++
            melde_gut.show()
        } else {
            zahl_falsch++
            binding.txtAnzahl.setText(getAnzahl(zahl_richtig, zahl_falsch))
            melde_falsch.show()
        }
    }

    binding.editTextNumber.setText(gros.toString())
    binding.seeRaum.progress = gros
    binding.seeRaum.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
        override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
            if (seekBar != null) {
                gros = seekBar.progress
                binding.editTextNumber.setText(gros.toString())
            }
        }

        override fun onStartTrackingTouch(seekBar: SeekBar?) {

        }

        override fun onStopTrackingTouch(seekBar: SeekBar?) {

        }
    })

    binding.editTextNumber.setOnEditorActionListener(object : TextView.OnEditorActionListener {
        override fun onEditorAction(view: TextView, actionId: Int, event: KeyEvent?): Boolean {
            gros = view.text.toString().toInt()
            binding.seeRaum.progress = gros
            KeyBoard().toggle(this@MainActivity)
            return true
        }
    })

    binding.chipAdd.isChecked = addi
    binding.chipAdd.setOnCheckedChangeListener { buttonView, isChecked ->
        addi = isChecked
    }

    binding.chipSub.isChecked = subi
    binding.chipSub.setOnCheckedChangeListener { buttonView, isChecked ->
        subi = isChecked
    }

    binding.chipMulti.isChecked = mult
    binding.chipMulti.setOnCheckedChangeListener { buttonView, isChecked ->
        mult = isChecked
    }

    binding.chipDiv.isChecked = divi
    binding.chipDiv.setOnCheckedChangeListener { buttonView, isChecked ->
        divi = isChecked
    }

    binding.swtNegativ.isChecked = negativ
    binding.swtNegativ.setOnCheckedChangeListener { buttonView, isChecked ->
        negativ = isChecked
    }

    binding.swiHundert.isChecked = hundert
    binding.swiHundert.setOnCheckedChangeListener { buttonView, isChecked ->
        hundert = isChecked
    }

    binding.edtName.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        }

        override fun afterTextChanged(s: Editable?) {
        }
    })

    binding.btnAnzeigen.setOnClickListener {
        //Layout aufrufen Daten übergeben und anzeigen
        val intent = Intent(ctx, Protokoll::class.java)
        b_schreib = false

        str_protokoll += getAnzahl(zahl_richtig, zahl_falsch) + '\n'

        intent.putExtra("proto", str_protokoll)
        protokollhorcher.launch(intent)
    }

    binding.btnLoeschen.setOnClickListener {
        str_protokoll = ""
        writeToFile(str_protokoll, str_proname)
        zahl_richtig = 0
        zahl_falsch = 0
        binding.txtAnzahl.setText(getAnzahl(zahl_richtig, zahl_falsch))

        val str_loesch = resources.getString(R.string.lbl_loeschen)
        Toast.makeText(ctx, str_loesch, Toast.LENGTH_LONG).show()
        //Zeitstempel schreiben
        val zeitstempel = LocalDateTime.now().format(formater)
        str_protokoll = resources.getString(R.string.lbl_start) + zeitstempel + '\n'
    }

    binding.edtName.afterTextChanged {
        //altes Protokoll Speichern
        str_protokoll += getAnzahl(zahl_richtig, zahl_falsch) + '\n'
        //Zeitstempel schreiben
        val zeitstempel = LocalDateTime.now().format(formater)
        str_protokoll += resources.getString(R.string.lbl_ende) + zeitstempel + '\n'
        writeToFile(str_protokoll, str_proname)

        //neues Protokoll anlegen
        str_proname = it.toString()
        //bisheriges Protokoll lesen
        str_protokoll = readFromFile(str_proname)
        //Zeitstempel schreiben
        str_protokoll += resources.getString(R.string.lbl_start) + zeitstempel + '\n'
        zahl_richtig = 0
        zahl_falsch = 0
        binding.txtAnzahl.setText(getAnzahl(zahl_richtig, zahl_falsch))
    }

    binding.txtAnzeige.setOnClickListener {
        //Rechnung vorlesen
        tts!!.speak(str_rechnung, TextToSpeech.QUEUE_FLUSH, null,"")
    }

    requestPermissionLauncher.launch( rechte )
}

override fun onStart() {
    super.onStart()
    //Protokoll aus Dateilesen
    val str_dat = binding.edtName.text.toString()
    str_protokoll = readFromFile( str_dat )

    if( b_schreib ) {
        //Zeitstempel schreiben
        val zeitstempel = LocalDateTime.now().format(formater)
        str_protokoll += resources.getString(R.string.lbl_start) + zeitstempel + '\n'
        // Auf null Setzen damit es bei jedem Start wieder von vorne beginnt
        zahl_richtig = 0
        zahl_falsch = 0
    }
}

override fun onStop() {
    if( b_schreib ) {
        str_protokoll += getAnzahl(zahl_richtig, zahl_falsch) + '\n'

        val zeitstempel = LocalDateTime.now().format(formater)
        str_protokoll += resources.getString(R.string.lbl_ende) + zeitstempel + '\n'
    }

    val prefs = ctx.getSharedPreferences("lustig", Context.MODE_PRIVATE)
    val prefw = prefs.edit()
    prefw.putBoolean("Key_ad", addi)
    prefw.putBoolean("Key_su", subi)
    prefw.putBoolean("Key_mu", mult)
    prefw.putBoolean("Key_di", divi)
    prefw.putInt("Key_gr", gros)
    prefw.putBoolean("Key_negativ", negativ)
    prefw.putBoolean("Key_hundert", hundert)
    prefw.putString("Key_proname", str_proname)
    prefw.apply()
    prefw.commit()

    //Protokoll in Datei speichern
    writeToFile(str_protokoll, str_proname)

    super.onStop()
}

override fun onDestroy() {
    // Shutdown TTS Sprachausgabe
    if (tts != null) {
        tts!!.stop()
        tts!!.shutdown()
    }

    super.onDestroy()
}

fun anzeige() {
    //Rechenaufgabe stellen
    var fragefrage = getString(R.string.lbl_frage)
    frage = rechnung(gros, addi, subi, mult, divi)
    fragefrage += frage
    binding.txtAnzeige.setText(fragefrage)

    binding.txtAnzahl.setText(getAnzahl(zahl_richtig, zahl_falsch))
    //Sprachausgabe
    tts!!.speak(str_rechnung, TextToSpeech.QUEUE_FLUSH, null,"")
    // Welcher Button zeigt das richtige Resultat
    val was = (1..4).random()
    when (was) {
        1 -> {
            binding.btnEins.setText(resultat.toString())
            binding.btnZwei.setText(zufallres())
            binding.btnDrei.setText(zufallres())
            binding.btnVier.setText(zufallres())
        }

        2 -> {
            binding.btnEins.setText(zufallres())
            binding.btnZwei.setText(resultat.toString())
            binding.btnDrei.setText(zufallres())
            binding.btnVier.setText(zufallres())
        }

        3 -> {
            binding.btnEins.setText(zufallres())
            binding.btnZwei.setText(zufallres())
            binding.btnDrei.setText(resultat.toString())
            binding.btnVier.setText(zufallres())
        }

        4 -> {
            binding.btnEins.setText(zufallres())
            binding.btnZwei.setText(zufallres())
            binding.btnDrei.setText(zufallres())
            binding.btnVier.setText(resultat.toString())
        }
    }
}

fun rechnung(raum: Int, ad: Boolean, su: Boolean, mu: Boolean, di: Boolean): String {
    zahl_eins = (1..raum).random()
    zahl_zwei = (1..raum).random()

    var was: Int = 0
    var res: String = ""
    val opera: Array<operator> = operator.values()
    var tun: Array<Boolean> = arrayOf(ad, su, mu, di)

    //Wahl der Operation und Prüfen ob es möglich ist
    do {
        was = (0..3).random()
    } while (!tun.get(was))

    when (opera.get(was).toString()) {
        "AD" -> {
            resultat = zahl_eins + zahl_zwei
            if(!hundert){ //Obergrenze darf nicht überschritten werden
                do{
                    zahl_zwei -= 1
                    resultat = zahl_eins + zahl_zwei
                }while (resultat > gros)
            }
            str_rechnung = zahl_eins.toString() + " plus " + zahl_zwei.toString()
            res = zahl_eins.toString() + " + " + zahl_zwei.toString()
        }

        "SU" -> {
            if (!negativ) {
                if (zahl_zwei > zahl_eins) {
                    var pool = zahl_eins
                    zahl_eins = zahl_zwei
                    zahl_zwei = pool
                }
            }
            resultat = zahl_eins - zahl_zwei
            if(!hundert){ //Obergrenze darf nicht überschritten werden
                do{
                    zahl_eins += 1
                    resultat = zahl_eins - zahl_zwei
                }while(resultat.absoluteValue > gros)
            }
            str_rechnung = zahl_eins.toString() + " minus " + zahl_zwei.toString()
            res = zahl_eins.toString() + " - " + zahl_zwei.toString()
        }

        "MU" -> {
            resultat = zahl_eins * zahl_zwei
            if (!hundert) { //Obergrenze darf nicht überschritten werden
                do {
                    zahl_zwei -= 2
                    resultat = zahl_eins * zahl_zwei
                }while (resultat > gros)
            }
            str_rechnung = zahl_eins.toString() + " mal " + zahl_zwei.toString()
            res = zahl_eins.toString() + " x " + zahl_zwei.toString()
        }

        "DI" -> {
            zahl_zwei = (1..9).random()
            resultat = zahl_eins * zahl_zwei
            if(!hundert){ //Obergrenze darf nicht überschritten werden
                do{
                    zahl_eins -= 1
                    resultat = zahl_eins * zahl_zwei
                }while(resultat > gros)
            }
            var pool = resultat
            resultat = zahl_eins
            zahl_eins = pool
            str_rechnung = zahl_eins.toString() + " durch " + zahl_zwei.toString()
            res = zahl_eins.toString() + " : " + zahl_zwei.toString()
        }

        else -> {
            resultat = zahl_eins + zahl_zwei
            if(!hundert){ //Obergrenze darf nicht überschritten werden
                do{
                    zahl_zwei -= 1
                    resultat = zahl_eins + zahl_zwei
                }while (resultat > gros)
            }
            str_rechnung = zahl_eins.toString() + " plus " + zahl_zwei.toString()
            res = zahl_eins.toString() + " + " + zahl_zwei.toString()
        }
    }

    return res
}

// Zufallsresultate erstellen
fun zufallres(): String {
    var zufallzahl : Int = 0
    if (negativ) {
        zufallzahl = ((gros * -1)..gros).random()
    } else{
        zufallzahl = (1..gros).random() //nur Positive Resultate zulassen
    }
    if( zufallzahl == resultat){
        zufallzahl + 5
    }
    return (resultat + zufallzahl).toString()
}

//Testen ob der richtige Button geklickt wurde
fun teste(s_wert : String) : Boolean{
    val but_res = s_wert.toFloat()
    var res : Float = 0F
        res = but_res - resultat
    if( abs(res) < 1 )
        return true
    else
        return false
}

private val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()){ isRecht : Map<String, Boolean> ->
    if( (isRecht.get(android.Manifest.permission.READ_EXTERNAL_STORAGE)!!) && (isRecht.get(
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE)!!)){
        str_text = getString(R.string.lbl_recht_neu)
        Toast.makeText(ctx, str_text, Toast.LENGTH_SHORT).show()
    }else{
        str_text = getString(R.string.lbl_recht_fasch)
        Toast.makeText(ctx, str_text, Toast.LENGTH_SHORT).show()
        finish()
    }
}

fun onClickRequestPermission( iew : View){
    var result : Int
    val listPermissionsNeeded : MutableList<String> = ArrayList<String>()
    for( p in rechte ){
        result = ContextCompat.checkSelfPermission(this, p)
        if(result != PackageManager.PERMISSION_GRANTED){
            listPermissionsNeeded.add(p)
        }
    }
    if( !listPermissionsNeeded.isEmpty() ){
        ActivityCompat.requestPermissions(this, (listPermissionsNeeded.toTypedArray() as Array<String?>;), MULTIPLE_PERMISSIONS)
    }
}

private fun pruefrechte(): Boolean {
    var result: Int
    val listPermissionsNeeded: MutableList<String> = ArrayList<String>()
    for (p in rechte) {
        result = ContextCompat.checkSelfPermission(this, p)
        if (result != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add((p))
        }
    }
    if (!listPermissionsNeeded.isEmpty()) {
        ActivityCompat.requestPermissions(this, (listPermissionsNeeded.toTypedArray() as Array<String?>;), MULTIPLE_PERMISSIONS)
        // keine permissions gesetzt

        return false
    }
    // alle permissions gesetzt
    return true
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    when (requestCode) {
        MULTIPLE_PERMISSIONS -> {
            if (grantResults.size > 0) {
                var permissionsDenied = ""
                for (per in permissions) {
                    if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
                        permissionsDenied += "\n" + per
                    }
                }
                // Nach dem ersten Male
            }

// return
}
}
}

companion object {
    const val MULTIPLE_PERMISSIONS = 99
}

override fun onInit(status: Int) {
    if (status == TextToSpeech.SUCCESS) {
        // set US English as language for tts
        val result = tts!!.setLanguage(Locale.GERMAN)

        if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
            val str_sprache = getString(R.string.lbl_sprache)
            Log.e("TTS","The Language specified is not supported!")
            Toast.makeText(ctx, str_sprache, Toast.LENGTH_SHORT).show()
        } else {
            //alles ist gut gegangen
        }

    } else {
        Log.e("TTS", "Initilization Failed!")
    }
}

private fun writeToFile(data: String, datname : String) {
    try { //MODE_PRIVATE Daten können nur von der App gelesen werden

// var str_pfad = ctx.applicationInfo.dataDir
// var str_file = File(str_pfad, datname).toString()
val fileOutputStream: FileOutputStream = openFileOutput(datname, MODE_PRIVATE)
fileOutputStream.write(data.toByteArray())
fileOutputStream.close()
} catch (e: Exception) {
e.printStackTrace()
}
}

private fun readFromFile(datname : String): String {
    var fileInputStream: FileInputStream? = null
    var inputStreamReader: InputStreamReader? = null
    var bufferedReader: BufferedReader? = null
    val stringBuilder = StringBuilder()

    try {
        var str_pfad = ctx.applicationInfo.dataDir
        var str_file = File(str_pfad, datname).toString()
        fileInputStream = openFileInput(datname)
        inputStreamReader = InputStreamReader(fileInputStream)
        bufferedReader = BufferedReader(inputStreamReader)

        var text: String? = bufferedReader.readLine()
        while (text != null) {
            text += '\n'
            stringBuilder.append(text)
            text = bufferedReader.readLine()
        }
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        try {
            bufferedReader?.close()
            inputStreamReader?.close()
            fileInputStream?.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    return stringBuilder.toString()
}

fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
    this.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        }

        override fun afterTextChanged(editable: Editable?) {
            afterTextChanged.invoke(editable.toString())
        }
    })
}

fun getAnzahl(n_richtig : Int, n_falsch : Int) : String{
    var str_stand : String = ""
    str_stand+= resources.getString(R.string.lbl_richtig) + n_richtig + " / "
    str_stand += resources.getString(R.string.lbl_falsch) + n_falsch

    return str_stand
}

var protokollhorcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ result ->
    if(result.resultCode == Activity.RESULT_OK){
        b_schreib = true
    }
}

}

Gruss Renato

Kommentieren
Beste Antwort
koje71
  • Forum-Beiträge: 70

20.08.2024, 22:37:51 via Website

Hallo Renato,

probiere mal den folgenden Code aus, einfach in die Activity einbauen und beim Start der App aufrufen:

fun fileIoExample(){
val fileName = "$filesDir/data.txt"
var text = ""

    try {
        text = File(fileName).readText()
    }catch(e:Exception){
    }

    text = text + "hallo\n"
    File(fileName).writeText(text)
}

Der Code liest eine Textdatei ein, fügt etwas hinzu und schreibt die Textdatei wieder zurück.

Viele Grüße

— geändert am 20.08.2024, 22:40:08

Hilfreich?
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 648

22.08.2024, 10:09:34 via Website

Ja danke so geht es.
Mit jeder Lösung wird es einfacher.

Gruss Renato

Hilfreich?
koje71
Kommentieren