Internal and External Storage in Android Development


In Android development, storage is an essential part of saving and retrieving data. Android provides two main types of storage: Internal Storage and External Storage. Both have their own use cases and access restrictions. Let’s explore both options, and how to use them in Android with Kotlin.

1. Internal Storage

Internal Storage refers to the storage space on the device that is private to the application. Each app has its own private storage area on the device. Files stored in internal storage are private and cannot be accessed by other applications.

Writing to Internal Storage

To write to internal storage, you use the openFileOutput method to open or create a file and then write data to it.

Example 1: Writing Data to a File in Internal Storage

    class MainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)

            val filename = "myfile.txt"
            val fileContents = "This is a sample text saved in internal storage."

            // Writing to internal storage
            try {
                openFileOutput(filename, Context.MODE_PRIVATE).use {
                    it.write(fileContents.toByteArray())
                }
                Toast.makeText(this, "File saved to internal storage", Toast.LENGTH_SHORT).show()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }
        

In this example:

  • openFileOutput(filename, Context.MODE_PRIVATE) opens or creates a file in the internal storage. The MODE_PRIVATE flag ensures that the file is private to the app.
  • it.write(fileContents.toByteArray()) writes the content into the file.

Reading from Internal Storage

To read from internal storage, you use the openFileInput method.

Example 2: Reading Data from a File in Internal Storage

    class MainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)

            val filename = "myfile.txt"

            // Reading from internal storage
            try {
                val fileInputStream = openFileInput(filename)
                val inputStreamReader = InputStreamReader(fileInputStream)
                val bufferedReader = BufferedReader(inputStreamReader)
                val fileContents = bufferedReader.readLine()

                Toast.makeText(this, "Read from file: $fileContents", Toast.LENGTH_LONG).show()
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
            }
        }
    }
        

In this example:

  • openFileInput(filename) opens the file in internal storage for reading.
  • BufferedReader.readLine() reads the file content line by line.

2. External Storage

External Storage refers to storage that is available to all apps on the device and can be accessed by the user. External storage includes both removable storage like SD cards and non-removable storage that is part of the device. Files stored in external storage are not private and can be accessed by other apps.

Note: Starting from Android 10 (API level 29), direct access to external storage is restricted for apps, and developers are encouraged to use Scoped Storage.

Writing to External Storage

Before writing to external storage, you need to request the necessary permissions. You can write to public directories (like pictures or downloads) using getExternalStoragePublicDirectory.

Example 3: Writing Data to External Storage

    class MainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)

            val filename = "example.txt"
            val fileContents = "This is a sample text saved in external storage."

            // Check if permission is granted
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), filename)
                try {
                    file.writeText(fileContents)
                    Toast.makeText(this, "File saved to external storage", Toast.LENGTH_SHORT).show()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            } else {
                // Request permission
                ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1)
            }
        }
    }
        

In this example:

  • Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) gets a public directory on the external storage to store the file.
  • file.writeText(fileContents) writes text content to the file.

Reading from External Storage

You can also read from external storage similarly using FileInputStream.

Example 4: Reading Data from External Storage

    class MainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)

            val filename = "example.txt"

            // Check if permission is granted
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), filename)
                try {
                    val fileContents = file.readText()
                    Toast.makeText(this, "Read from file: $fileContents", Toast.LENGTH_LONG).show()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            } else {
                // Request permission
                ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)
            }
        }
    }
        

In this example:

  • file.readText() reads the text content of the file stored on external storage.

3. Scoped Storage (Android 10 and Above)

For devices running Android 10 (API level 29) or higher, direct access to the entire external storage is restricted. Android encourages the use of Scoped Storage, which gives apps access to only their app-specific directories or media collections like photos, music, etc.

Example 5: Using Scoped Storage

    val contentResolver: ContentResolver = applicationContext.contentResolver
    val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    val values = ContentValues()
    values.put(MediaStore.Images.Media.TITLE, "Sample Image")
    values.put(MediaStore.Images.Media.DESCRIPTION, "Sample Image Description")

    val imageUri: Uri? = contentResolver.insert(uri, values)
    Toast.makeText(this, "Scoped storage file saved", Toast.LENGTH_SHORT).show()
        

This example shows how to use the MediaStore to save files using scoped storage. Apps can access only specific directories (like images) and must request permission accordingly.

4. Conclusion

Both internal and external storage have their uses in Android development. Internal storage is perfect for app-specific data, while external storage can be used for sharing data with other apps. Starting with Android 10, it’s important to use Scoped Storage for better data security and app compatibility.





Advertisement