Open Read Share Assets Folder Files Android

Android – How to read & share file from assets folder

In most of the applications there is a need to include files like database, files, audio, images in apk.  This can be achieved by saving files either inside assets or raw folder. Both folders can be used to store files and there is a very slight difference between the two.

raw is a subfolder of resources and Android source compilation automatically generates resource ID for any file present in raw folder. So the files can easily be referenced by their generated IDs. While, files stored in asset folder are accessed by the filenames and there is no reference created for these files. Other difference is that files can be grouped in sub folders inside assets while raw folder follows a flat hierarchy.

In this post we will see how to read and share files from assets as well as raw folder.

How to read file from Assets folder

Let’s check first where to keep assets folder. In order to save files in your application first create assets folder inside your apps main directory. Create assets folder inside app/src/main/ folder. You can create subfolders and save files.

Using Apache IOUtils

Add Apache Common IOUtils dependency in app’s gradle file.

    implementation 'commons-io:commons-io:2.5'

Call IOUtils toString function to read from InputStream.

    public String loadJSONFromAssetSubfolder(Context ctx) {
        String json = null;

        try {
            InputStream inputStream = ctx.getAssets().open("subfolder/example_2.json");
            json = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

            Log.i("tag", json);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return json;
    }

Using BufferedReader

    public String readFileFromAssets(Context ctx) {
        StringBuilder strFile = new StringBuilder();
        try {
            BufferedReader reader = null;
            InputStream inputStream = ctx.getAssets().open("sampletextfile.txt");
            reader = new BufferedReader(new InputStreamReader(inputStream));
            String mLine;
            while ((mLine = reader.readLine()) != null) {
                strFile.append(mLine);
            }

        } catch (IOException ex) {
            ex.printStackTrace();
        }
        Log.i("tag", strFile.toString());

        return strFile.toString();
    }

Read file from Raw folder

Similar to assets folder inputstream can be opened for raw folder. Use openRawResource to create inputstream.

    public String readFileFromRaw(Context ctx) {
        String json = null;

        try {
            InputStream inputStream = ctx.getResources().openRawResource(R.raw.example_2);
            json = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
            Log.i("tag", json);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return json;
    }

Share files saved in Assets folder

Android do not allow and expose files stored in assets. To allow sharing of files included in assets, app has to expose these files by creating a ContentProvider. Content Provider is used to share data between applications.

Add no compress options in the gradle file inside android block to disable compression of text, json files.

    aaptOptions {
        noCompress '.json' , '.txt'
    }

This will make sure that files inside asset folder are not compressed.

Full sample of app.gradle file

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.codeexa.com.readfiles"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    aaptOptions {
        noCompress '.json' , '.txt'
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'commons-io:commons-io:2.5'
}

Now create our ContentProvider class that will handle the file sharing. In the ContentProvider we will override openAssetFile to create FileDescriptor for assets files.

Create MyContentProvider.java and paste the below content.

package com.codeexa.com.readfiles;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class MyContentProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }


    @Override
    public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
        AssetManager am = getContext().getAssets();
        String fileName = uri.getLastPathSegment();
        if(fileName == null)
            throw new FileNotFoundException();
        AssetFileDescriptor fileDescriptor = null;
        try {
            fileDescriptor = am.openFd(fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileDescriptor;
    }
}

openAssetFile is implemented by providers that need to be able to return sub-sections of files, often assets inside of their .apk.

Add ContentProvider tag in AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.codeexa.com.readfiles">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="GoogleAppIndexingWarning">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <provider
            android:name=".MyContentProvider"
            android:authorities="com.codeexa.com.readfiles"
            android:grantUriPermissions="true"
            android:exported="true" />

    </application>
</manifest>

Replace android:authorities value with your package id.

Now we are ready to share files from assets directory. In your activity class you can share file as shown in the code below.

    
    private Context mContext;
    private static final String AUTHORITY=
            "com.codeexa.com.readfiles";
    private static final Uri PROVIDER=
            Uri.parse("content://"+AUTHORITY);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mContext = this;
        //shareAssetFile("sampletextfile.txt");
        shareAssetFile("subfolder/example_2.json");
    }
    public void shareAssetFile(String fileName){
        Uri uriFile = PROVIDER
                .buildUpon()
                .appendPath(fileName)
                .build();
        Intent fileShareIntent = new Intent(Intent.ACTION_SEND);
        fileShareIntent.setType("*/*");
        fileShareIntent.putExtra(Intent.EXTRA_STREAM,uriFile);
        fileShareIntent.putExtra(Intent.EXTRA_TEXT, "#Message");
        fileShareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        startActivity(Intent.createChooser(fileShareIntent, "Share Asset"));
    }

Share files from assets folder in Android

If you have a file example_2.json inside assets/subfolder then pass the file name like the snipped shared below.

shareAssetFile("subfolder/example_2.json");

 

 

6 Comments

  1. gil August 26, 2019
    • T M August 29, 2019
  2. Han September 3, 2019
  3. Tarun Gandhi October 6, 2019
  4. Tarun Gandhi October 6, 2019
  5. tarun October 7, 2019

Leave a Reply