When building Android applications using Kotlin, one of the most common issues developers face is the app not writing data to the internal storage properly.
This problem can arise from incorrect file handling, missing permissions, or improper usage of Android’s storage APIs.
In this article, we will explore why this issue occurs, how to fix it, and provide a full example code to ensure your Kotlin app can successfully write and read data from internal storage.

Understanding Internal Storage in Android
Internal storage in Android is a private storage area allocated for each application.
Files stored here are not accessible by other apps and are automatically deleted when the application is uninstalled.
Unlike external storage, internal storage does not require special permissions in the AndroidManifest.xml file,
making it the preferred method for saving sensitive or app-specific data.
Common Causes of Kotlin App Not Writing to Internal Storage
- Incorrect file path: Using an invalid directory or filename can prevent writing data.
- Not closing streams: Forgetting to close FileOutputStream may result in incomplete file writing.
- Wrong mode: Using MODE_PRIVATE, MODE_APPEND, or MODE_MULTI_PROCESS incorrectly can cause unexpected behavior.
- Trying to write large data: Internal storage is limited; writing huge files may fail.
- Using external storage APIs: Mixing internal and external storage methods can lead to confusion.
How to Write Data to Internal Storage in Kotlin
The simplest way to write a text file into internal storage is by using the openFileOutput()
function.
This function creates a file in your app’s private storage directory.
fun saveToInternalStorage(filename: String, data: String, context: Context) { try { context.openFileOutput(filename, Context.MODE_PRIVATE).use { output -> output.write(data.toByteArray()) } Log.d("InternalStorage", "Data saved successfully!") } catch (e: Exception) { e.printStackTrace() } }
Reading Data Back from Internal Storage
To confirm that your Kotlin app is writing data correctly, you should be able to read the data back.
fun readFromInternalStorage(filename: String, context: Context): String? { return try { context.openFileInput(filename).bufferedReader().useLines { lines -> lines.joinToString("\n") } } catch (e: Exception) { e.printStackTrace() null } }
Complete Example: Writing and Reading Notes App
Let’s build a small demo app that writes user input to internal storage and then retrieves it.
class MainActivity : AppCompatActivity() { private lateinit var editText: EditText private lateinit var saveButton: Button private lateinit var readButton: Button private lateinit var textView: TextView private val fileName = "myNotes.txt" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) editText = findViewById(R.id.editText) saveButton = findViewById(R.id.saveButton) readButton = findViewById(R.id.readButton) textView = findViewById(R.id.textView) saveButton.setOnClickListener { val data = editText.text.toString() saveToInternalStorage(fileName, data, this) } readButton.setOnClickListener { val content = readFromInternalStorage(fileName, this) textView.text = content ?: "No data found" } } private fun saveToInternalStorage(filename: String, data: String, context: Context) { try { context.openFileOutput(filename, Context.MODE_PRIVATE).use { output -> output.write(data.toByteArray()) } Toast.makeText(context, "Data saved successfully!", Toast.LENGTH_SHORT).show() } catch (e: Exception) { e.printStackTrace() } } private fun readFromInternalStorage(filename: String, context: Context): String? { return try { context.openFileInput(filename).bufferedReader().useLines { lines -> lines.joinToString("\n") } } catch (e: Exception) { e.printStackTrace() null } } }
XML Layout Example
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Write something..." /> <Button android:id="@+id/saveButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Save Data" /> <Button android:id="@+id/readButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Read Data" /> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" android:text="No data yet" android:textSize="16sp" /> </LinearLayout>
Troubleshooting Tips
- Check Logcat for
FileNotFoundException
orIOException
. - Ensure you are not mixing internal and external storage APIs.
- Test writing small strings before saving larger data structures.
- For JSON or structured data, use
Gson
orKotlin Serialization
.
Comparison Between Internal and External Storage
Aspect | Internal Storage | External Storage |
---|---|---|
Accessibility | Private to app | Public, other apps may access |
Permission Needed | No permission required | Requires READ/WRITE permission |
Data Persistence | Deleted when app is uninstalled | Remains even after uninstall |
Best Use | App-specific data, user settings | Large media files, shared data |
Conclusion
If your Kotlin app is not writing to internal storage, double-check your code, verify file paths,
and ensure you are using the correct context and file handling methods.
By following the provided example, you should be able to save and retrieve data easily without errors.
Internal storage is reliable, secure, and simple, making it the go-to choice for app-specific data handling.
For further reading on Android file storage best practices, visit the official
Android Storage Documentation.