Android

Android JSON Parsing Tutorial

JSON parsing is a key component in android application development. We can parse JSON data using different third-party libraries like loops, retrofit, and volley. In this tutorial, we will learn how to parse data from url into android using loops. We will develop a complete android JSON parsing example by using a movie JSON file. We will be following the JSON parsing get method and show output data in a custom listview.

Eample JSON data URL

JSON data can be accessed in many ways like storing a json file in raw folder or access from url. In this tutorial we will be following android JSON parsing from URL. We are placing a JSON file named movies.json in our website and access that buy a URL to parse.

we can access JSON data file from this URL: https://tutorialscache.com/movies.json

{
    "status":true,
    "total_records":10,
    "movies": [
        {
            "id":1,
            "name":"Captain America (2011)",
            "image":"https://tutorialscache.com/wp-content/uploads/2019/04/captain-america.jpeg",
            "ratting":5.0
        },
        {
            "id":2,
            "name":"Apocalypto (2006)",
            "image":"https://tutorialscache.com/wp-content/uploads/2019/04/apocalypto.png",
            "ratting":4.5
        },
        {
            "id":3,
            "name":"300 (2006)",
            "image":"https://tutorialscache.com/wp-content/uploads/2019/04/300.png",
            "ratting":4.5
        },{
            "id":4,
            "name":"Spider Man (2002)",
            "image":"https://tutorialscache.com/wp-content/uploads/2019/04/spiderman.jpg",
            "ratting":5.0
        }
    ]
}

1. Create new Android Studio Project

Create new android studio project and choose empty activity.

Screen Shot 2019-04-10 at 10.00.43 AM
Screen Shot 2019-04-10 at 10.00.53 AM
Screen Shot 2019-04-10 at 1.38.31 PM

2. strings.xml

We have added few strings to make use in the application.

<resources>
    <string name="app_name">Awesome Movies</string>
    <string name="network_error">Network not connected</string>
    <string name="retry">Retry</string> 
    <string name="no_status_false">Invalid Response</string>
    <string name="no_movies">No Movies Found</string>
</resources>

2.1 colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#d11617</color>
    <color name="colorPrimaryDark">#B31718</color>
    <color name="colorAccent">#B31718</color>
    <color name="white">#FFFFFF</color>
</resources>

3. GlobalClass.java

Create a new class GlobalClass and extend with Application. This class instance will help us to access BASE URL and also gives us application instance. It also has a function named isNetowrk() which will help us to check internet connectivity.

package com.tutorialscache.android_json_parsing;
import android.app.Application;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class GlobalClass extends Application {
    public static final String BASE_URL = "http://www.tutorialscache.com/";
    private static GlobalClass singleton;
    @Override
    public void onCreate() {
        super.onCreate();
        singleton = this;
    }
    public static GlobalClass getInstance() {
        return singleton;
    }
    public static boolean isNetowrk() {
        boolean haveConnectedWifi = false;
        boolean haveConnectedMobile = false;
        ConnectivityManager cm = (ConnectivityManager)singleton.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();
        for (NetworkInfo ni : netInfo) {
            if (ni.getTypeName().equalsIgnoreCase("WIFI"))
                if (ni.isConnected())
                    haveConnectedWifi = true;
            if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
                if (ni.isConnected())
                    haveConnectedMobile = true;
        }
        return haveConnectedWifi || haveConnectedMobile;
    }
}

To launch GlobalClass at start of the application add application name in name attribute in <application> of Android.Manifest.xml

    <application
                android:name=".GlobalClass"

4. AndroidManifest.xml INTERNET Permissions & NETWORK STATE

We need to add INTERNET & NETWORK STATE Permissions into AndroidManifest.xml file to allow movies.json file from url and to check whether our app is connected with internet or not . These permissions are necessary because we can’t access urls without internet permissions. After adding permissions our AndroidManifest.xml will look like this.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tutorialscache.android_json_parsing">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <application
        android:name=".GlobalClass"
        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">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

5. Third party libraries Loopj & Picasso.

We will use loopj to access data from url and Picasso to load images from url in build.gradle (Module: app)

    implementation 'com.loopj.android:android-async-http:1.4.9'
    implementation 'com.squareup.picasso:picasso:2.5.2'

build.gradle(Module:app) complete code

apply plugin: 'com.android.application'
android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.tutorialscache.android_json_parsing"
        minSdkVersion 14
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    implementation 'com.loopj.android:android-async-http:1.4.9'
    implementation 'com.squareup.picasso:picasso:2.5.2'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

6. WebReq.java

Create a new Application name WebReq and following code. WebReq class used to send request on server. It has GET Method to return JSON data from given url.

package com.tutorialscache.android_json_parsing;
import android.content.Context;
import android.util.Log;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.RequestParams;
import com.loopj.android.http.ResponseHandlerInterface;
public class WebReq {
    public static AsyncHttpClient client;
    static{
        //create object of loopj client
        //443 will save you from ssl exception
        client = new AsyncHttpClient(true,80,443);
    }
    // you can create post methods as well similar way
    public static void get(Context context, String url, RequestParams params, ResponseHandlerInterface responseHandler) {
        client.get(context, getAbsoluteUrl(url), params, responseHandler);
    }
    //concatenation of base url and file name
    private static String getAbsoluteUrl(String relativeUrl) {
        Log.d("response URL: ",GlobalClass.getInstance().BASE_URL + relativeUrl+" ");
        return GlobalClass.getInstance().BASE_URL + relativeUrl;
    }
}

7. activity_main.xml

Add ListView code in activity_main.xml file.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.tutorialscache.android_json_parsing.MainActivity">
    <ListView
        android:id="@+id/listView"
        android:scrollbars="none"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
    <ProgressBar
        android:id="@+id/pBr"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/retryTv"
        android:visibility="gone"
        android:textColor="@color/colorPrimary"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/pBr"
        android:text="@string/retry"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

8. Gradient Image

We need to add a gradient image to make our listview attractive. Download image and place in drawable folder.

9. custom_row.xml

Create a new layout file named custom_row.xml and add following code.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:padding="0.1dp">
    <ImageView
        android:id="@+id/movieImg"
        android:scaleType="fitXY"
        android:layout_width="match_parent"
        android:layout_height="200dp" />
    <ImageView
        android:src="@drawable/gradient"
        android:scaleType="fitXY"
        android:layout_width="match_parent"
        android:layout_height="200dp" />
    <TextView
        android:id="@+id/movieNameTv"
        android:text="300 (2006)"
        android:textSize="25dp"
        android:textColor="@color/white"
        android:layout_alignParentBottom="true"
        android:padding="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <RatingBar
        android:id="@+id/movieRating"
        style="?android:attr/ratingBarStyleSmall"
        android:numStars="5"
        android:rating="5"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:paddingBottom="10dp"
        android:layout_marginRight="5dp"
        android:stepSize="0.1"
        android:layout_marginBottom="10dp"
        android:isIndicator="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

10. MoviesModel.java

Create a new class named MoviesModel.java and add following code. If you want to learn ho to create model, getters and setters go back to Custom ListView tutorial.

package com.tutorialscache.android_json_parsing;
import android.util.Log;
public class MoviesModel {
    //variables
    int id;
    String name,image;
    public double getRatting() {
        return ratting;
    }
    public void setRatting(double ratting) {
        this.ratting = ratting;
    }
    double ratting;
    //constructor
    public MoviesModel(int id,String name,String image, double ratting){
        this.setId(id);
        this.setName(name);
        this.setImage(image);
        this.setRatting(ratting);
    }
    //getters and setters
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getImage() {
        return image;
    }
    public void setImage(String image) {
        this.image = image;
    }
    @Override
    public String toString() {
        Log.d("response MODEL: ","ID: "+this.getId()+" Movie Name: "+this.getName()+" Ratting: "+this.getRatting()+" ");
        return super.toString();
    }
}

11. MoviesJSONAdapter.java

create a new file and name it MoviesJSONAdapter. We will extend this class with BaseAdapter and implement its methods.

package com.tutorialscache.android_json_parsing;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
public class MoviesJSONAdapter extends BaseAdapter {
    MoviesModel moviesModel;
    ArrayList<MoviesModel> moviesJsonData;
    LayoutInflater layoutInflater;
    Context context;
    public MoviesJSONAdapter(Context context, ArrayList<MoviesModel> moviesJsonData) {
        this.context=context;
        this.moviesJsonData=moviesJsonData;
        layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    @Override
    public int getCount() {
        return moviesJsonData.size();
    }
    @Override
    public Object getItem(int position) {
        return moviesJsonData.get(position);
    }
    @Override
    public long getItemId(int position) {
        return moviesJsonData.get(position).getId();
    }
    @Override
    public View getView(int position, View view, ViewGroup viewGroup) {
        View convertView = view;
        if (convertView==null){
            convertView = layoutInflater.inflate(R.layout.custom_row,null);
            TextView movieNameTv = convertView.findViewById(R.id.movieNameTv);
            ImageView movieImg = convertView.findViewById(R.id.movieImg);
            RatingBar ratingBar = convertView.findViewById(R.id.movieRating);
            moviesModel = moviesJsonData.get(position);
            movieNameTv.setText(moviesModel.getName());
            //Picasso load image
            Picasso.with(context).load(moviesModel.getImage()).into(movieImg);
            //set ratting
            ratingBar.setRating((float) moviesModel.getRatting());
        }
        return convertView;
    }
}

12. MainActivity.java

package com.tutorialscache.android_json_parsing;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import com.loopj.android.http.ResponseHandlerInterface;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import cz.msebera.android.httpclient.Header;
public class MainActivity extends AppCompatActivity {
    ListView listView;
    TextView retryTv;
    MoviesJSONAdapter moviesJSONAdapter;
    ArrayList<MoviesModel> moviesJsonData;
    ProgressBar progressBar;
    Context context;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context=this;
        setContentView(R.layout.activity_main);
        initialize();
        if (GlobalClass.isNetowrk()){
            requestData();
            retryTv.setVisibility(View.GONE);
            progressBar.setVisibility(View.VISIBLE);
        }else {
            Toast.makeText(context,getString(R.string.network_error),Toast.LENGTH_SHORT).show();
            retryTv.setVisibility(View.VISIBLE);
            progressBar.setVisibility(View.INVISIBLE);
        }
    }
    private void initialize() {
        listView = findViewById(R.id.listView);
        retryTv = findViewById(R.id.retryTv);
        progressBar = findViewById(R.id.pBr);
        moviesJsonData=new ArrayList<>();
        moviesJSONAdapter = new MoviesJSONAdapter(context,moviesJsonData);
        listView.setAdapter(moviesJSONAdapter);
    }
    private void requestData() {
        RequestParams requestParams = new RequestParams();
        WebReq.get(context,"movies.json",requestParams,new MainActivity.ResponseHandler());
    }
    public class ResponseHandler extends JsonHttpResponseHandler {
        @Override
        public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
            // response failure
            super.onFailure(statusCode, headers, responseString, throwable);
        }
        @Override
        public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
            super.onSuccess(statusCode, headers, response);
            //clear all previous data if any
            moviesJsonData.clear();
            Log.d("response ",response.toString());
            //check status of the response
            try {
                if (response.getBoolean("status")){
                    // get movies array from response object
                    JSONArray movies = response.getJSONArray("movies");
                    //check whether movies array is not empty
                    if (movies.length()>0){
                        //loop through movies array and add into moviesJsonData
                        for (int i = 0; i < movies.length(); i++) {
                            //get each movie object
                            JSONObject movie = movies.getJSONObject(i);
                            //get each movie Object Data
                            MoviesModel moviesModel = new MoviesModel(movie.getInt("id"),movie.getString("name"),movie.getString("image"),movie.getDouble("ratting"));
                            moviesModel.toString();
                            //add object to moviesJsonData array
                            moviesJsonData.add(moviesModel);
                        }
                        //Now notify adapter with new data
                        moviesJSONAdapter.notifyDataSetChanged();
                    }else{
                        Toast.makeText(context,getString(R.string.no_movies),Toast.LENGTH_SHORT).show();
                        retryTv.setVisibility(View.VISIBLE);
                    }
                }else{
                    Toast.makeText(context,getString(R.string.no_status_false),Toast.LENGTH_SHORT).show();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onFinish() {
            //hide progress bar
            progressBar.setVisibility(View.GONE);
            super.onFinish();
        }
    }
}
final_app

Write A Comment