2 Farklı Şekilde Dosya Kaydetme [Kotlin]
Dosyalarımızı cache, internal ve external olarak kaydedebilirsiniz. Bunlarda public ve private olarak değişmektedir. Yani eğer kullanıcının görebilmesini istiyorsanız farklı bir işlem yapmanız gerekir. Bunun hakkında daha sonra bir makale yazacağım. Burada cache ve uygulama katmanı içerisine dosya kaydetmeyi anlatacağım. Bu iki katmana da kullanıcı ulaşamamaktadır. Ancak developer dosya yolunu tutarak veya kaydederek bunu kullanıcıya gösterebilir.
Cache Webden dosyamızı alabilmek için retrofit’i ve kotlin coroutines ile de iki extension function yazarak çok kolay bir şekilde dosya kaydetme işlemini eğer indirmemişse indirip, eğer daha önce indirmişse indirdiği yerden okuyarak çok hızlı ve tek satırda halledebilirsiniz. Fonksiyonun sonunda yer alan unit tipinde action parametresi ile de lambda olarak kaydedilen dosyamızı geri döndürerek işlem yapabiliriz.
Cache içerisine kaydedilen dosyalar android zorunlu hallerde yani hafıza gerektiği durumlarda uygulamaların cachelerini silebilmektedir. Dolayısıyla cache’e kaydetme işlemini yalnızca az kullanılan durumlarda yapmanın faydası var. Örneğin kullanıcı uygulamaya kayıt olurken gösterilen gizlilik politikaları gibi.
Şimdi geçelim kaydetme işlemlerimize…
Dosya Kaydetme metodumuzu Retrofit ile çağırma
Service.apiInterface.getFile(token, fileType).saveFile("${fileType}.pdf") { pdfView.fromFile(it).load() }
Burada retrofit ile yazmış olduğumuz interface’imize bağlanıp metodumuzu çağırıp sonrasında aşağıda yazdığımız extension fonksiyonumuz ile saveFile diyerek dosyamızı kaydetme yapabilir ve okuyabilir hale getirebiliriz.
Kotlin extension function olarak yazmış olduğumuz saveFile fonksiyonumuzun içerisinde coroutines kullanarak globalscope yöntemiyle asenkron olarak çalışmasını sağlıyoruz.
Coroutines ile Cache’e kaydetme ve okuma
External Files Dir içerisine kaydetme
Cache yerine elbette dışarıya da kaydedebilirsiniz. Ben gereksiz tekrar tekrar kullanılmayacak dosyalar için basit ve gereksiz uygulamada alan kaplamaması durumları için gerekli durumlar için cache’e dosya kaydetmeyi anlatacağım. İsterseniz 13. satır yerine
val storageDir = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.path file = File("$storageDir/$fileNameWithExt")
ile değiştirerek uygulama katmanı içerine de kaydedip kullanabilirsiniz ancak o zaman da 4. satırdaki daha önceden kayıtlı mı sorgusunu da değiştirmeniz gerekir. Kısacası şöyle olacaktır.
private fun Call<ResponseBody>.saveFile(fileNameWithExt: String, action: (file: File?) -> Unit) { GlobalScope.launch { try { val storageDir = baseContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.path val file = File("$storageDir/$fileNameWithExt") if(file.exists()){ action(file) }else{ withContext(Dispatchers.IO) { val response = [email protected]() val buffer = response.body()?.byteStream() var file: File? = null if (buffer != null) { file = File.createTempFile(fileNameWithExt, null, baseContext?.cacheDir) if (file != null) { buffer.copyStreamToFile(file) } } action(file) } } } catch (e: Exception) { Log.e("error", e.message ?: "") } } } private fun InputStream.copyStreamToFile(outputFile: File) { this.use { input -> val outputStream = FileOutputStream(outputFile) outputStream.use { output -> val buffer = ByteArray(4 * 1024) while (true) { val byteCount = input.read(buffer) if (byteCount < 0) break output.write(buffer, 0, byteCount) } output.flush() } } }