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.
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(); } } }