223

I'm currently developing a physics app that is supposed to show a list of formulas and even solve some of them (the only problem is the ListView)

This is my main layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:measureWithLargestChild="false"
    android:orientation="vertical"
    tools:context=".CatList">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/titlebar">

        <TextView
            android:id="@+id/Title1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:text="@string/app_name"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="#ff1c00"
            android:textIsSelectable="false" />

    </RelativeLayout>

    <ListView
        android:id="@+id/listFormulas"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </ListView>

</LinearLayout>

And this is my main activity

package com.wildsushii.quickphysics;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONException;
import org.json.JSONObject;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.view.Menu;
import android.widget.ListView;

public class CatList extends Activity {

    public static String AssetJSONFile(String filename, Context context) throws IOException {
        AssetManager manager = context.getAssets();
        InputStream file = manager.open(filename);
        byte[] formArray = new byte[file.available()];
        file.read(formArray);
        file.close();

        return new String(formArray);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cat_list);
        ListView categoriesL = (ListView) findViewById(R.id.listFormulas);

        ArrayList<HashMap<String, String>> formList = new ArrayList<HashMap<String, String>>();
        Context context = null;
        try {
            String jsonLocation = AssetJSONFile("formules.json", context);
            JSONObject formArray = (new JSONObject()).getJSONObject("formules");
            String formule = formArray.getString("formule");
            String url = formArray.getString("url");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        //My problem is here!!
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.cat_list, menu);
        return true;
    }
}

I actually know I can make this without using JSON but I need more practice parsing JSON. By the way, this is the JSON

{
    "formules": [
    {
      "formule": "Linear Motion",
      "url": "qp1"
    },
    {
      "formule": "Constant Acceleration Motion",
      "url": "qp2"
    },
    {
      "formule": "Projectile Motion",
      "url": "qp3"
    },
    {
      "formule": "Force",
      "url": "qp4"
    },
    {
      "formule": "Work, Power, Energy",
      "url": "qp5"
    },
    {
      "formule": "Rotary Motion",
      "url": "qp6"
    },
    {
      "formule": "Harmonic Motion",
      "url": "qp7"
    },
    {
      "formule": "Gravity",
      "url": "qp8"
    },
    {
      "formule": "Lateral and Longitudinal Waves",
      "url": "qp9"
    },
    {
      "formule": "Sound Waves",
      "url": "qp10"
    },
    {
      "formule": "Electrostatics",
      "url": "qp11"
    },
    {
      "formule": "Direct Current",
      "url": "qp12"
    },
    {
      "formule": "Magnetic Field",
      "url": "qp13"
    },
    {
      "formule": "Alternating Current",
      "url": "qp14"
    },
    {
      "formule": "Thermodynamics",
      "url": "qp15"
    },
    {
      "formule": "Hydrogen Atom",
      "url": "qp16"
    },
    {
      "formule": "Optics",
      "url": "qp17"
    },
    {
      "formule": "Modern Physics",
      "url": "qp18"
    },
    {
      "formule": "Hydrostatics",
      "url": "qp19"
    },
    {
      "formule": "Astronomy",
      "url": "qp20"
    }
  ]
}

I have tried a lot of things and even delete the entire project to make a new one :(

Ramesh R
  • 7,009
  • 4
  • 25
  • 38
theWildSushii
  • 2,233
  • 2
  • 12
  • 6

9 Answers9

395

As Faizan describes in their answer here:

First of all read the Json File from your assests file using below code.

and then you can simply read this string return by this function as

public String loadJSONFromAsset() {
    String json = null;
    try {
        InputStream is = getActivity().getAssets().open("yourfilename.json");
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        json = new String(buffer, "UTF-8");
    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    }
    return json;
}

and use this method like that

    try {
        JSONObject obj = new JSONObject(loadJSONFromAsset());
        JSONArray m_jArry = obj.getJSONArray("formules");
        ArrayList<HashMap<String, String>> formList = new ArrayList<HashMap<String, String>>();
        HashMap<String, String> m_li;

        for (int i = 0; i < m_jArry.length(); i++) {
            JSONObject jo_inside = m_jArry.getJSONObject(i);
            Log.d("Details-->", jo_inside.getString("formule"));
            String formula_value = jo_inside.getString("formule");
            String url_value = jo_inside.getString("url");

            //Add your values in your `ArrayList` as below:
            m_li = new HashMap<String, String>();
            m_li.put("formule", formula_value);
            m_li.put("url", url_value);

            formList.add(m_li);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }

For further details regarding JSON Read HERE

Amr Alaa
  • 1,156
  • 11
  • 16
GrIsHu
  • 29,068
  • 10
  • 64
  • 102
  • op's reading from assests folder is fine he is passing null as the context. also `m_li.put("formula", formula);` should be `m_li.put("formula", formula_value);` and should be using `Log` instead of System.out.println – Raghunandan Nov 13 '13 at 05:05
  • m_li.put("url", url); too, it should be m_li.put("url", url_value); I almost cried until I noticed this. – theWildSushii Nov 13 '13 at 05:14
  • @GrlsHu I have a problem in this line: JSONObject obj = new JSONObject(json_return_by_the_function); Do I have to replace "json_return_by_the_function" with something? I'm kinda new to Java :( – theWildSushii Nov 13 '13 at 05:22
  • Just replace `json_return_by_the_function` with `JSONObject obj = new JSONObject(loadJSONFromAsset());` like this. – GrIsHu Nov 13 '13 at 05:23
  • Do I have to surround it with a try-catch statement right? When I replaced "json_return_by_the_function" with "loadJSONFromAsset()" everything screw up and surrounding it with a try-catch solved it – theWildSushii Nov 13 '13 at 05:33
  • @GrIsHu no need to create arraylist in for loop. – Raghunandan Nov 13 '13 at 06:18
  • @GrlsHu I have a problem, when I run the app it crashes and I don't know what's the problem, Eclipse doesn't notify me any syntax error or any problem – theWildSushii Nov 13 '13 at 18:45
  • @WildSushii Can you tell me where exactly you are getting error? Try to debug your code. – GrIsHu Nov 14 '13 at 04:18
  • @GrisHu thx for your snippet. It works but when I try to log my json string that's printing not the entire file content. Size seems correct. Do you have an idea ? – Pierre Jan 09 '14 at 14:44
  • It's obvious that this was mostly copied from Faizan's answer: http://stackoverflow.com/questions/13814503/reading-a-json-file-in-android/13814551#13814551 . You *must* provide proper attribution when you do this, or we will remove your answers. – Brad Larson Aug 14 '14 at 02:40
  • 1
    Allocating the buffer based on the result returned by available() is incorrect as per the Java docs: http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#available() "Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream." – Andrew Nov 04 '15 at 22:51
  • Downvoting this answer because of the known issues with available() as mentioned in Andrew's comment. The major issue is that this works most of the time instead of failing consistently and makes it very tricky to debug when dealing with encrypted files – Raghav Nov 18 '19 at 22:28
  • 1
    Even though this is an old question, since this is the top answer @GrIsHu could you please consider updating your answer ? – Raghav Nov 18 '19 at 22:30
  • 1
    I know this is an old thread, but has anyone found a viable solution without using InputStream.available()? Every solution I have found incorporates it. – snowcap420 Jun 27 '21 at 15:25
25

With Kotlin have this extension function to read the file return as string.

fun AssetManager.readAssetsFile(fileName : String): String = open(fileName).bufferedReader().use{it.readText()}

Parse the output string using any JSON parser.

Libin
  • 16,967
  • 7
  • 61
  • 83
17
{ // json object node
    "formules": [ // json array formules
    { // json object 
      "formule": "Linear Motion", // string
      "url": "qp1"
    }

What you are doing

  Context context = null; // context is null 
    try {
        String jsonLocation = AssetJSONFile("formules.json", context);

So change to

   try {
        String jsonLocation = AssetJSONFile("formules.json", CatList.this);

To parse

I believe you get the string from the assests folder.

try
{
String jsonLocation = AssetJSONFile("formules.json", context);
JSONObject jsonobject = new JSONObject(jsonLocation);
JSONArray jarray = (JSONArray) jsonobject.getJSONArray("formules");
for(int i=0;i<jarray.length();i++)
{
JSONObject jb =(JSONObject) jarray.get(i);
String formula = jb.getString("formule");
String url = jb.getString("url");
}
} catch (IOException e) {
        e.printStackTrace();
} catch (JSONException e) {
        e.printStackTrace();
}
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
13

Just summarising @libing's answer with a sample that worked for me.

enter image description here

val gson = Gson()
val todoItem: TodoItem = gson.fromJson(this.assets.readAssetsFile("versus.json"), TodoItem::class.java)

private fun AssetManager.readAssetsFile(fileName : String): String = open(fileName).bufferedReader().use{it.readText()}

Without this extension function the same can be achieved by using BufferedReader and InputStreamReader this way:

val i: InputStream = this.assets.open("versus.json")
val br = BufferedReader(InputStreamReader(i))
val todoItem: TodoItem = gson.fromJson(br, TodoItem::class.java)
Francislainy Campos
  • 3,462
  • 4
  • 33
  • 81
9

Method to read JSON file from Assets folder and return as a string object.

public static String getAssetJsonData(Context context) {
            String json = null;
            try {
                InputStream is = context.getAssets().open("myJson.json");
                int size = is.available();
                byte[] buffer = new byte[size];
                is.read(buffer);
                is.close();
                json = new String(buffer, "UTF-8");
            } catch (IOException ex) {
                ex.printStackTrace();
                return null;
            }

            Log.e("data", json);
            return json;

        }

Now for parsing data in your activity:-

String data = getAssetJsonData(getApplicationContext());
        Type type = new TypeToken<Your Data model>() {
        }.getType();
  <Your Data model> modelObject = new Gson().fromJson(data, type);
Anil Singhania
  • 785
  • 10
  • 9
  • Hi, may you prefer adding the import libraries because it warns three different about your code. – Bay Sep 17 '19 at 20:42
7

Using OKIO

implementation("com.squareup.okio:okio:3.0.0-alpha.4")

With Java:

public static String readJsonFromAssets(Context context, String filePath) {
        
            try {
                InputStream input = context.getAssets().open(filePath);
                BufferedSource source = Okio.buffer(Okio.source(input));
                return source.readByteString().string(Charset.forName("utf-8"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        
            return null;
    }

With Kotlin:

fun readJsonFromAssets(context: Context, filePath: String): String? {
    try {
        val source = context.assets.open(filePath).source().buffer()
        return source.readByteString().string(Charset.forName("utf-8"))
            
     } catch (e: IOException) {
            e.printStackTrace()
     }
     return null
}

and then...

String data = readJsonFromAssets(context, "json/some.json"); //here is my file inside the folder assets/json/some.json

Type reviewType = new TypeToken<List<Object>>() {}.getType();

if (data != null) {
    Object object = new Gson().fromJson(data, reviewType);
}
Williaan Lopes
  • 1,177
  • 15
  • 11
  • 1
    It works but there is a correction return source.readByteString(source.available()).string(Charset.forName("utf-8")) – Milan Sheth Jul 27 '21 at 12:44
7

If you are using Kotlin in android then you can create Extension function.
Extension Functions are defined outside of any class - yet they reference the class name and can use this. In our case we use applicationContext.
So in Utility class you can define all extension functions.


Utility.kt

fun Context.loadJSONFromAssets(fileName: String): String {
    return applicationContext.assets.open(fileName).bufferedReader().use { reader ->
        reader.readText()
    }
}

MainActivity.kt

You can define private function for load JSON data from assert like this:

 lateinit var facilityModelList: ArrayList<FacilityModel>
 private fun bindJSONDataInFacilityList() {
    facilityModelList = ArrayList<FacilityModel>()
    val facilityJsonArray = JSONArray(loadJSONFromAsserts("NDoH_facility_list.json")) // Extension Function call here
    for (i in 0 until facilityJsonArray.length()){
        val facilityModel = FacilityModel()
        val facilityJSONObject = facilityJsonArray.getJSONObject(i)
        facilityModel.Facility = facilityJSONObject.getString("Facility")
        facilityModel.District = facilityJSONObject.getString("District")
        facilityModel.Province = facilityJSONObject.getString("Province")
        facilityModel.Subdistrict = facilityJSONObject.getString("Facility")
        facilityModel.code = facilityJSONObject.getInt("code")
        facilityModel.gps_latitude = facilityJSONObject.getDouble("gps_latitude")
        facilityModel.gps_longitude = facilityJSONObject.getDouble("gps_longitude")

        facilityModelList.add(facilityModel)
    }
}

You have to pass facilityModelList in your ListView


FacilityModel.kt

class FacilityModel: Serializable {
    var District: String = ""
    var Facility: String = ""
    var Province: String = ""
    var Subdistrict: String = ""
    var code: Int = 0
    var gps_latitude: Double= 0.0
    var gps_longitude: Double= 0.0
}

In my case JSON response start with JSONArray

[
  {
    "code": 875933,
    "Province": "Eastern Cape",
    "District": "Amathole DM",
    "Subdistrict": "Amahlathi LM",
    "Facility": "Amabele Clinic",
    "gps_latitude": -32.6634,
    "gps_longitude": 27.5239
  },

  {
    "code": 455242,
    "Province": "Eastern Cape",
    "District": "Amathole DM",
    "Subdistrict": "Amahlathi LM",
    "Facility": "Burnshill Clinic",
    "gps_latitude": -32.7686,
    "gps_longitude": 27.055
  }
]
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Shreeya Chhatrala
  • 1,441
  • 18
  • 33
4

Source code How to fetch Local Json from Assets folder

https://drive.google.com/open?id=1NG1amTVWPNViim_caBr8eeB4zczTDK2p

    {
        "responseCode": "200",
        "responseMessage": "Recode Fetch Successfully!",
        "responseTime": "10:22",
        "employeesList": [
            {
                "empId": "1",
                "empName": "Keshav",
                "empFatherName": "Mr Ramesh Chand Gera",
                "empSalary": "9654267338",
                "empDesignation": "Sr. Java Developer",
                "leaveBalance": "3",
                "pfBalance": "60,000",
                "pfAccountNo.": "12345678"
            },
            {
                "empId": "2",
                "empName": "Ram",
                "empFatherName": "Mr Dasrath ji",
                "empSalary": "9999999999",
                "empDesignation": "Sr. Java Developer",
                "leaveBalance": "3",
                "pfBalance": "60,000",
                "pfAccountNo.": "12345678"
            },
            {
                "empId": "3",
                "empName": "Manisha",
                "empFatherName": "Mr Ramesh Chand Gera",
                "empSalary": "8826420999",
                "empDesignation": "BusinessMan",
                "leaveBalance": "3",
                "pfBalance": "60,000",
                "pfAccountNo.": "12345678"
            },
            {
                "empId": "4",
                "empName": "Happy",
                "empFatherName": "Mr Ramesh Chand Gera",
                "empSalary": "9582401701",
                "empDesignation": "Two Wheeler",
                "leaveBalance": "3",
                "pfBalance": "60,000",
                "pfAccountNo.": "12345678"
            },
            {
                "empId": "5",
                "empName": "Ritu",
                "empFatherName": "Mr Keshav Gera",
                "empSalary": "8888888888",
                "empDesignation": "Sararat Vibhag",
                "leaveBalance": "3",
                "pfBalance": "60,000",
                "pfAccountNo.": "12345678"
            }
        ]
    }


 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_employee);


        emp_recycler_view = (RecyclerView) findViewById(R.id.emp_recycler_view);

        emp_recycler_view.setLayoutManager(new LinearLayoutManager(EmployeeActivity.this, 
        LinearLayoutManager.VERTICAL, false));
        emp_recycler_view.setItemAnimator(new DefaultItemAnimator());

        employeeAdapter = new EmployeeAdapter(EmployeeActivity.this , employeeModelArrayList);

        emp_recycler_view.setAdapter(employeeAdapter);

        getJsonFileFromLocally();
    }



    public String loadJSONFromAsset() {
        String json = null;
        try {
            InputStream is = EmployeeActivity.this.getAssets().open("employees.json");       //TODO Json File  name from assets folder
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
            json = new String(buffer, "UTF-8");
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        }
        return json;
    }

    private void getJsonFileFromLocally() {
        try {

            JSONObject jsonObject = new JSONObject(loadJSONFromAsset());
            String responseCode = jsonObject.getString("responseCode");
            String responseMessage = jsonObject.getString("responseMessage");
            String responseTime = jsonObject.getString("responseTime");

            Log.e("keshav", "responseCode -->" + responseCode);
            Log.e("keshav", "responseMessage -->" + responseMessage);
            Log.e("keshav", "responseTime -->" + responseTime);


            if(responseCode.equals("200")){

            }else{
                Toast.makeText(this, "No Receord Found ", Toast.LENGTH_SHORT).show();
            }

            JSONArray jsonArray = jsonObject.getJSONArray("employeesList");                  //TODO pass array object name
            Log.e("keshav", "m_jArry -->" + jsonArray.length());


            for (int i = 0; i < jsonArray.length(); i++)
            {
                EmployeeModel employeeModel = new EmployeeModel();

                JSONObject jsonObjectEmployee = jsonArray.getJSONObject(i);


                String empId = jsonObjectEmployee.getString("empId");
                String empName = jsonObjectEmployee.getString("empName");
                String empDesignation = jsonObjectEmployee.getString("empDesignation");
                String empSalary = jsonObjectEmployee.getString("empSalary");
                String empFatherName = jsonObjectEmployee.getString("empFatherName");

                employeeModel.setEmpId(""+empId);
                employeeModel.setEmpName(""+empName);
                employeeModel.setEmpDesignation(""+empDesignation);
                employeeModel.setEmpSalary(""+empSalary);
                employeeModel.setEmpFatherNamer(""+empFatherName);

                employeeModelArrayList.add(employeeModel);

            }       // for

            if(employeeModelArrayList!=null) {
                employeeAdapter.dataChanged(employeeModelArrayList);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
Keshav Gera
  • 10,807
  • 1
  • 75
  • 53
4
You have to write a function to read the Json File from your assests folder.

public String loadJSONFile() {
    String json = null;
    try {
        InputStream inputStream = getAssets().open("yourfilename.json");
        int size = inputStream.available();
        byte[] byteArray = new byte[size];
        inputStream.read(byteArray);
        inputStream.close();
        json = new String(byteArray, "UTF-8");
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
    return json;
}
Anil Singhania
  • 785
  • 10
  • 9
  • This function returns JSON file into a string. After that parse it into JSONObject, Like:- JSONObject object = new JSONObject(loadJSONFile); Now access data acording to your json format. – Anil Singhania Aug 25 '21 at 13:21