aboutsummaryrefslogtreecommitdiff
path: root/androidApp/src/main/java/mx/trackermap/TrackerMap/android/shared/FileCache.kt
blob: 16777de7a658c9c25f6a5f055dde6b59c213572d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package mx.trackermap.TrackerMap.android.shared

import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
import android.webkit.MimeTypeMap
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream

// Source: https://techenum.com/android-content-uri-how-to-get-the-file-uri/
class FileCache(
    private val context: Context
) {

    // content resolver
    private val contentResolver = context.contentResolver

    // to get the type of file
    private val mimeTypeMap = MimeTypeMap.getSingleton()

    private val mCacheLocation = File(context.cacheDir, "reports_tmp")

    fun cacheThis(uris: List<Uri>) {
        uris.forEach { uri -> copyFromSource(uri) }
    }

    /**
     * Copies the actual data from provided content provider.
     */
    private fun copyFromSource(uri: Uri) {

        val fileExtension: String = getFileExtension(uri) ?: kotlin.run {
            throw RuntimeException("Extension is null for $uri")
        }
        val fileName = queryName(uri) ?: getFileName(fileExtension)

        val inputStream = contentResolver.openInputStream(uri) ?: kotlin.run {
            throw RuntimeException("Cannot open for reading $uri")
        }
        val bufferedInputStream = BufferedInputStream(inputStream)

        // the file which will be the new cached file
        val outputFile = File(mCacheLocation, fileName)
        if (!outputFile.exists()) {
            outputFile.parentFile?.mkdirs()
        } else {
            outputFile.delete()
        }
        val bufferedOutputStream = BufferedOutputStream(FileOutputStream(outputFile))

        // this will hold the content for each iteration
        val buffer = ByteArray(DEFAULT_BUFFER_SIZE)

        var readBytes: Int // will be -1 if reached the end of file

        while (true) {
            readBytes = bufferedInputStream.read(buffer)

            // check if the read was failure
            if (readBytes == -1) {
                bufferedOutputStream.flush()
                break
            }

            bufferedOutputStream.write(buffer)
            bufferedOutputStream.flush()
        }

        // close everything
        inputStream.close()
        bufferedInputStream.close()
        bufferedOutputStream.close()

    }

    private fun getFileExtension(uri: Uri): String? {
        return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri))
    }

    /**
     * Tries to get actual name of the file being copied.
     * This might be required in some of the cases where you might want to know the file name too.
     *
     * @param uri
     *
     */
    private fun queryName(uri: Uri): String? {
        val returnCursor = contentResolver.query(uri, null, null, null, null) ?: return null
        val nameIndex: Int = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
        returnCursor.moveToFirst()
        val name: String = returnCursor.getString(nameIndex)
        returnCursor.close()
        return name
    }

    private fun getFileName(fileExtension: String): String {
        return "${System.currentTimeMillis()}.$fileExtension"
    }

    /**
     * Remove everything that we have cached.
     * You might want to invoke this method before quiting the application.
     */
    fun removeAll() {
        mCacheLocation.deleteRecursively()
    }

    companion object {

        // base buffer size
        private const val BASE_BUFFER_SIZE = 1024

        // if you want to modify size use binary multiplier 2, 4, 6, 8
        private const val DEFAULT_BUFFER_SIZE = BASE_BUFFER_SIZE * 4

    }

}