Android
File Copy
Mobile Development
Android Tutorial
File Management

How to make a copy of a file in android?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Copying a file in Android sounds simple, but the correct implementation depends on where the source file comes from and where the destination should live. Modern Android development also requires you to think about scoped storage, Uri access, and permission boundaries instead of assuming every file can be accessed through a raw filesystem path.

Prefer Uri-Based Copying in Modern Android

If a user selects a document from the system picker, you usually receive a Uri, not a traditional file path. In that case, the safest copy flow is to open an input stream from the source Uri and an output stream to the destination.

kotlin
1import android.content.ContentResolver
2import android.net.Uri
3import java.io.File
4
5fun copyUriToFile(contentResolver: ContentResolver, source: Uri, destination: File) {
6    contentResolver.openInputStream(source).use { input ->
7        requireNotNull(input) { "Cannot open source input stream" }
8        destination.outputStream().use { output ->
9            input.copyTo(output)
10        }
11    }
12}

This approach works well with files chosen through the Storage Access Framework and avoids assumptions about direct path access.

Copy a File Inside App-Private Storage

If both the source and destination are files your app owns, standard file streams are enough.

kotlin
1import java.io.File
2
3fun copyFile(source: File, destination: File) {
4    source.inputStream().use { input ->
5        destination.outputStream().use { output ->
6            input.copyTo(output)
7        }
8    }
9}

You would call it like this:

kotlin
val source = File(filesDir, "notes.txt")
val destination = File(cacheDir, "notes_backup.txt")
copyFile(source, destination)

Using use ensures streams are closed correctly even when exceptions occur.

Create the Destination Safely

Copying fails if the destination directory does not exist. Make sure the parent folder is ready before writing.

kotlin
1fun ensureParentDirectory(file: File) {
2    val parent = file.parentFile
3    if (parent != null && !parent.exists()) {
4        parent.mkdirs()
5    }
6}

Then combine it with the copy operation:

kotlin
ensureParentDirectory(destination)
copyFile(source, destination)

This is especially important when you are exporting files to a nested app-specific directory.

API-Level Considerations

Older Android examples often show direct access to external storage paths plus broad storage permissions. That pattern is increasingly fragile on newer Android versions.

A more future-proof rule is:

  • Use app-private directories when possible
  • Use the document picker for user-selected external files
  • Use ContentResolver with Uri values for shared storage

If you are copying media or documents outside your sandbox, the storage model matters more than the copy loop itself.

Error Handling Matters

A production copy operation should handle at least these cases:

  • Source does not exist
  • App lacks permission to read the source
  • Destination directory cannot be created
  • Copy is interrupted by low storage or I/O failure
kotlin
1fun safeCopy(source: File, destination: File): Boolean {
2    return try {
3        ensureParentDirectory(destination)
4        copyFile(source, destination)
5        true
6    } catch (e: Exception) {
7        false
8    }
9}

In a real app, log the exception or surface a useful error to the user instead of silently swallowing it.

Performance Notes

For normal mobile files, copyTo is usually sufficient and readable. If you are copying very large files, you may want progress reporting, cancellation support, or background execution with WorkManager or a coroutine running on Dispatchers.IO.

The actual copy API is often not the bottleneck. The bigger issue is making sure the operation runs off the main thread so the UI stays responsive.

Common Pitfalls

A common mistake is assuming a Uri can always be converted into a normal file path. On modern Android, many document providers do not expose a direct filesystem path at all.

Another mistake is doing file I/O on the main thread. Even a modest copy can freeze the app and trigger strict mode warnings.

A third mistake is focusing only on the stream logic and forgetting permissions or destination directory creation. The code may look correct but still fail immediately at runtime.

Summary

  • In modern Android, copying files often means copying from a Uri, not a raw path.
  • Use InputStream and OutputStream with use so resources close safely.
  • Ensure the destination directory exists before writing.
  • Run file copy work off the main thread for a responsive UI.
  • Respect scoped storage rules and prefer ContentResolver for shared files.

Course illustration
Course illustration

All Rights Reserved.