There are essentially two ways to do this.
First, you can use AssetManager.open and, as described by Rohith Nandakumar and iterate over the inputstream.
Second, you can use AssetManager.openFd, which allows you to use a FileChannel (which has the [transferTo](https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferTo(long, long, java.nio.channels.WritableByteChannel)) and [transferFrom](https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferFrom(java.nio.channels.ReadableByteChannel, long, long)) methods), so you don't have to loop over the input stream yourself.
I will describe the openFd method here.
First you need to ensure that the file is stored uncompressed. The packaging system may choose to compress any file with an extension that is not marked as noCompress, and compressed files cannot be memory mapped, so you will have to rely on AssetManager.open in that case.
You can add a '.mp3' extension to your file to stop it from being compressed, but the proper solution is to modify your app/build.gradle file and add the following lines (to disable compression of PDF files)
aaptOptions {
noCompress 'pdf'
}
Note that the packager can still pack multiple files into one, so you can't just read the whole file the AssetManager gives you. You need to to ask the AssetFileDescriptor which parts you need.
Once you've ensured your file is stored uncompressed, you can use the AssetManager.openFd method to obtain an AssetFileDescriptor, which can be used to obtain a FileInputStream (unlike AssetManager.open, which returns an InputStream) that contains a FileChannel. It also contains the starting offset (getStartOffset) and size (getLength), which you need to obtain the correct part of the file.
An example implementation is given below:
private void copyFileFromAssets(String in_filename, File out_file){
Log.d("copyFileFromAssets", "Copying file '"+in_filename+"' to '"+out_file.toString()+"'");
AssetManager assetManager = getApplicationContext().getAssets();
FileChannel in_chan = null, out_chan = null;
try {
AssetFileDescriptor in_afd = assetManager.openFd(in_filename);
FileInputStream in_stream = in_afd.createInputStream();
in_chan = in_stream.getChannel();
Log.d("copyFileFromAssets", "Asset space in file: start = "+in_afd.getStartOffset()+", length = "+in_afd.getLength());
FileOutputStream out_stream = new FileOutputStream(out_file);
out_chan = out_stream.getChannel();
in_chan.transferTo(in_afd.getStartOffset(), in_afd.getLength(), out_chan);
} catch (IOException ioe){
Log.w("copyFileFromAssets", "Failed to copy file '"+in_filename+"' to external storage:"+ioe.toString());
} finally {
try {
if (in_chan != null) {
in_chan.close();
}
if (out_chan != null) {
out_chan.close();
}
} catch (IOException ioe){}
}
}
This answer is based on JPM's answer.