Sunday 4 September 2016

JSON Parsing - JsonArray, JsonObject



The Sample JSON
Following is the sample JSON that we are going to parse in this tutorial. This is very simple JSON which gives us list of contacts where each node contains contact information like name, email, address, gender and phone numbers.
You can get this JSON data by accessing http://api.androidhive.info/contacts/

{
    "contacts": [
        {
                "id": "c200",
                "name": "Ravi Tamada",
                "email": "ravi@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        {
                "id": "c201",
                "name": "Johnny Depp",
                "email": "johnny_depp@gmail.com",
                "address": "xx-xx-xxxx,x - street, x - country",
                "gender" : "male",
                "phone": {
                    "mobile": "+91 0000000000",
                    "home": "00 000000",
                    "office": "00 000000"
                }
        },
        .
        .
        .
        .
  ]
}


The difference between [ and { – (Square brackets and Curly brackets)

In general all the JSON nodes will start with a square bracket or with a curly bracket. The difference between [ and { is, the square bracket ([) represents starting of an JSONArray node whereas curly bracket ({) represents JSONObject. So while accessing these nodes we need to call appropriate method to access the data.

If your JSON node starts with [, then we should use getJSONArray() method. Same as if the node starts with {, then we should use getJSONObject() method.

json parsing structor


1. Creating New Project

So let’s start by creating a new android project. We’ll build a simple app which fetches the json from url, parses it and displays the contacts in a list view. Here we’ll use import java.net libraries (which are natively supported in android) to make the http call and fetch the json from url.

1. Create a new project in Android Studio from File New Project and fill out the required details.

2. As we are fetching the JSON by making HTTP calls, we need to add INTERNET permission in AndroidManifest.xml file. Open AndroidManifest.xml and add the following permission.

<uses-permission android:name="android.permission.INTERNET" />

3. Create a class named HttpHandler.java and use the below code. Here makeServiceCall() makes http call to particular url and fetches the response. In our case, we use this to get the raw json from the url.
HttpHandler.java

import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

/**
 * Created by Ravi Tamada on 01/09/16.
 * www.androidhive.info
 */
public class HttpHandler {

   
private static final String TAG = HttpHandler.class.getSimpleName();

   
public HttpHandler() {
    }

   
public String makeServiceCall(String reqUrl) {
        String response =
null;
       
try {
            URL url =
new URL(reqUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod(
"GET");
           
// read the response
           
InputStream in = new BufferedInputStream(conn.getInputStream());
            response = convertStreamToString(in);
        }
catch (MalformedURLException e) {
            Log.e(
TAG, "MalformedURLException: " + e.getMessage());
        }
catch (ProtocolException e) {
            Log.e(
TAG, "ProtocolException: " + e.getMessage());
        }
catch (IOException e) {
            Log.e(
TAG, "IOException: " + e.getMessage());
        }
catch (Exception e) {
            Log.e(
TAG, "Exception: " + e.getMessage());
        }
       
return response;
    }

   
private String convertStreamToString(InputStream is) {
        BufferedReader reader =
new BufferedReader(new InputStreamReader(is));
        StringBuilder sb =
new StringBuilder();

        String line;
       
try {
           
while ((line = reader.readLine()) != null) {
                sb.append(line).append(
'\n');
            }
        }
catch (IOException e) {
            e.printStackTrace();
        }
finally {
           
try {
                is.close();
            }
catch (IOException e) {
                e.printStackTrace();
            }
        }
       
return sb.toString();
    }
}

4. Before making the http call, let’s add a list view first in our view. Open the layout file of main activity (activity_main.xml) and add a ListView element.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    >



    <ListView

        android:id="@+id/list"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content" />

</RelativeLayout>

5. Create another layout file named list_item.xml with following content. This will be used to render single list item view.
list_item.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:orientation="vertical"

    android:padding="@dimen/activity_horizontal_margin">



    <TextView

        android:id="@+id/name"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:paddingBottom="2dip"

        android:paddingTop="6dip"

        android:textColor="@color/colorPrimaryDark"

        android:textSize="16sp"

        android:textStyle="bold" />



    <TextView

        android:id="@+id/email"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:paddingBottom="2dip"

        android:textColor="@color/colorAccent" />



    <TextView

        android:id="@+id/mobile"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:textColor="#5d5d5d"

        android:textStyle="bold" />

</LinearLayout>


1.1 Downloading & Parsing the JSON

7. As we are getting the JSON by making HTTP call, I am adding a Async class GetContacts to make http calls on background thread. Add the following method in your main activity class.

In onPreExecute() method progress dialog is shown before making the http call.

In doInBackground() method, makeServiceCall() is called to get the json from url. Once the json is fetched, it is parsed and each contact is added to array list.

In onPostExecute() method the progress dialog is dismissed and the array list data is displayed in list view using an adapter.

Also note that I have used getJSONArray() or getJSONObject() method depending on the type of node.

MainActivity.java
import android.app.ProgressDialog;

import android.os.AsyncTask;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.util.Log;

import android.widget.ListAdapter;

import android.widget.ListView;

import android.widget.SimpleAdapter;

import android.widget.Toast;



import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;



import java.util.ArrayList;

import java.util.HashMap;



public class MainActivity extends AppCompatActivity {



    private String TAG = MainActivity.class.getSimpleName();



    private ProgressDialog pDialog;

    private ListView lv;



    // URL to get contacts JSON

    private static String url = "http://api.androidhive.info/contacts/";



    ArrayList<HashMap<String, String>> contactList;



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);



        contactList = new ArrayList<>();



        lv = (ListView) findViewById(R.id.list);



        new GetContacts().execute();

    }



    /**

     * Async task class to get json by making HTTP call

     */

    private class GetContacts extends AsyncTask<Void, Void, Void> {



        @Override

        protected void onPreExecute() {

            super.onPreExecute();

            // Showing progress dialog

            pDialog = new ProgressDialog(MainActivity.this);

            pDialog.setMessage("Please wait...");

            pDialog.setCancelable(false);

            pDialog.show();



        }



        @Override

        protected Void doInBackground(Void... arg0) {

            HttpHandler sh = new HttpHandler();



            // Making a request to url and getting response

            String jsonStr = sh.makeServiceCall(url);



            Log.e(TAG, "Response from url: " + jsonStr);



            if (jsonStr != null) {

                try {

                    JSONObject jsonObj = new JSONObject(jsonStr);



                    // Getting JSON Array node

                    JSONArray contacts = jsonObj.getJSONArray("contacts");



                    // looping through All Contacts

                    for (int i = 0; i < contacts.length(); i++) {

                        JSONObject c = contacts.getJSONObject(i);



                        String id = c.getString("id");

                        String name = c.getString("name");

                        String email = c.getString("email");

                        String address = c.getString("address");

                        String gender = c.getString("gender");



                        // Phone node is JSON Object

                        JSONObject phone = c.getJSONObject("phone");

                        String mobile = phone.getString("mobile");

                        String home = phone.getString("home");

                        String office = phone.getString("office");



                        // tmp hash map for single contact

                        HashMap<String, String> contact = new HashMap<>();



                        // adding each child node to HashMap key => value

                        contact.put("id", id);

                        contact.put("name", name);

                        contact.put("email", email);

                        contact.put("mobile", mobile);



                        // adding contact to contact list

                        contactList.add(contact);

                    }

                } catch (final JSONException e) {

                    Log.e(TAG, "Json parsing error: " + e.getMessage());

                    runOnUiThread(new Runnable() {

                        @Override

                        public void run() {

                            Toast.makeText(getApplicationContext(),

                                    "Json parsing error: " + e.getMessage(),

                                    Toast.LENGTH_LONG)

                                    .show();

                        }

                    });



                }

            } else {

                Log.e(TAG, "Couldn't get json from server.");

                runOnUiThread(new Runnable() {

                    @Override

                    public void run() {

                        Toast.makeText(getApplicationContext(),

                                "Couldn't get json from server. Check LogCat for possible errors!",

                                Toast.LENGTH_LONG)

                                .show();

                    }

                });



            }



            return null;

        }



        @Override

        protected void onPostExecute(Void result) {

            super.onPostExecute(result);

            // Dismiss the progress dialog

            if (pDialog.isShowing())

                pDialog.dismiss();

            /**

             * Updating parsed JSON data into ListView

             * */

            ListAdapter adapter = new SimpleAdapter(

                    MainActivity.this, contactList,

                    R.layout.list_item, new String[]{"name", "email",

                    "mobile"}, new int[]{R.id.name,

                    R.id.email, R.id.mobile});



            lv.setAdapter(adapter);

        }



    }

}


Friday 26 August 2016

Copy Folder from Android Assets to Phone Storage with AsyncTask

Add below permission to AndroidManifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

MainActivity.java


import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;


public class MainActivity extends AppCompatActivity {

    AsyncTaskRunner taskRunner;
    Activity ctx;

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

        taskRunner = new AsyncTaskRunner(this);
        taskRunner.execute();
    }
public void gotoUpdate(View view)
{
    taskRunner = new AsyncTaskRunner(this);
    taskRunner.execute();
}
}



Create new java file

AsyncTaskRunner.java



import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.AssetManager;
import android.os.AsyncTask;
import android.os.Environment;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/** * Created by pkm1 on 8/26/2016. */public  class AsyncTaskRunner extends AsyncTask<Void,String,Void> {

    ProgressDialog progressDialog;

    private Context ctx;
    public AsyncTaskRunner(Context myContext) {
        this.ctx = myContext;
    }

    @Override    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = ProgressDialog.show(ctx,"Image Transferring",  "Wait for  seconds");
    }

    @Override    protected Void doInBackground(Void... voids) {

        publishProgress("Sleeping..."); // Calls onProgressUpdate()
        try {
            copyDirorfileFromAssetManager("imagesrc", "cms");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        // execution of result of Long time consuming operation        progressDialog.dismiss();
    }

    public String copyDirorfileFromAssetManager(String arg_assetDir, String arg_destinationDir) throws IOException {

        System.out.print(arg_assetDir);   System.out.print(arg_destinationDir);

        File sd_path = Environment.getExternalStorageDirectory();
        String dest_dir_path = sd_path + addLeadingSlash(arg_destinationDir);
        File dest_dir = new File(dest_dir_path);

        createDir(dest_dir);

        AssetManager asset_manager = ctx.getAssets();
        String[] files = asset_manager.list(arg_assetDir);

        for (int i = 0; i < files.length; i++) {

            String abs_asset_file_path = addTrailingSlash(arg_assetDir) + files[i];
            String sub_files[] = asset_manager.list(abs_asset_file_path);

            if (sub_files.length == 0) {
                // It is a file                String dest_file_path = addTrailingSlash(dest_dir_path) + files[i];
                copyAssetFile(abs_asset_file_path, dest_file_path);
            } else {
                // It is a sub directory                copyDirorfileFromAssetManager(abs_asset_file_path, addTrailingSlash(arg_destinationDir) + files[i]);
            }
        }

        return dest_dir_path;
    }


    public void copyAssetFile(String assetFilePath, String destinationFilePath) throws IOException {
        InputStream in = ctx.getAssets().open(assetFilePath);
        OutputStream out = new FileOutputStream(destinationFilePath);

        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0)
            out.write(buf, 0, len);
        in.close();
        out.close();
    }

    public String addTrailingSlash(String path) {
        if (path.charAt(path.length() - 1) != '/') {
            path += "/";
        }
        return path;
    }

    public String addLeadingSlash(String path) {
        if (path.charAt(0) != '/') {
            path = "/" + path;
        }
        return path;
    }

    public void createDir(File dir) throws IOException {
        if (dir.exists()) {
            if (!dir.isDirectory()) {
                throw new IOException("Can't create directory, a file is in the way");
            }
        } else {
            dir.mkdirs();
            if (!dir.isDirectory()) {
                throw new IOException("Unable to create directory");
            }
        }
    }


}


Copy Folder from Assets to Phone Storage



Add below permission to AndroidManifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>







import android.content.res.AssetManager;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class MainActivity extends AppCompatActivity {

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


        try {
            copyDirorfileFromAssetManager("imagesrc","cms");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public String copyDirorfileFromAssetManager(String arg_assetDir, String arg_destinationDir) throws IOException
    {
        File sd_path = Environment.getExternalStorageDirectory();
        String dest_dir_path = sd_path + addLeadingSlash(arg_destinationDir);
        File dest_dir = new File(dest_dir_path);

        createDir(dest_dir);

        AssetManager asset_manager = getApplicationContext().getAssets();
        String[] files = asset_manager.list(arg_assetDir);

        for (int i = 0; i < files.length; i++)
        {

            String abs_asset_file_path = addTrailingSlash(arg_assetDir) + files[i];
            String sub_files[] = asset_manager.list(abs_asset_file_path);

            if (sub_files.length == 0)
            {
                // It is a file                String dest_file_path = addTrailingSlash(dest_dir_path) + files[i];
                copyAssetFile(abs_asset_file_path, dest_file_path);
            } else            {
                // It is a sub directory                copyDirorfileFromAssetManager(abs_asset_file_path, addTrailingSlash(arg_destinationDir) + files[i]);
            }
        }

        return dest_dir_path;
    }


    public void copyAssetFile(String assetFilePath, String destinationFilePath) throws IOException
    {
        InputStream in = getApplicationContext().getAssets().open(assetFilePath);
        OutputStream out = new FileOutputStream(destinationFilePath);

        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0)
            out.write(buf, 0, len);
        in.close();
        out.close();
    }

    public String addTrailingSlash(String path)
    {
        if (path.charAt(path.length() - 1) != '/')
        {
            path += "/";
        }
        return path;
    }

    public String addLeadingSlash(String path)
    {
        if (path.charAt(0) != '/')
        {
            path = "/" + path;
        }
        return path;
    }

    public void createDir(File dir) throws IOException
    {
        if (dir.exists())
        {
            if (!dir.isDirectory())
            {
                throw new IOException("Can't create directory, a file is in the way");
            }
        } else        {
            dir.mkdirs();
            if (!dir.isDirectory())
            {
                throw new IOException("Unable to create directory");
            }
        }
    }
}

Thursday 25 August 2016

File transfer from Assets folder to Phone Storage with AsyncTask


Add below permission to AndroidManifest.xml


<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


MainActivity.java



import java.io.File;
import java.util.ArrayList;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.widget.Toast;
public class MainActivity extends Activity {
// this where your file will be stored in sdcard in this case in folder (YOUR_FILE)
static String BASE_FILE = Environment.getExternalStorageDirectory()+"/YOUR_FILE/";
ArrayList<String> TmpList = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// create dynamic array to add your files
ArrayList<String> MyFiles = new ArrayList<String>();
MyFiles.add("demo_voice.mp3");
MyFiles.add("demo_img.jpg");
// add your files here
// create base folder if not exists
File f = new File(BASE_FILE);
if(!f.exists())
f.mkdir();
// this loop to check if files already coped or not or any file delete
for(int i=0;i<MyFiles.size();i++){
File check = new File(BASE_FILE,MyFiles.get(i));
if(!check.exists())
TmpList.add(MyFiles.get(i)); // copy not coped items to other list
}
// now check if not all files copy or something remove
if(TmpList.size()>0)
new AsyncCopy(this, BASE_FILE, TmpList).execute("");
else
Toast.makeText(getApplicationContext(), "all files coped ",Toast.LENGTH_LONG).show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}

AsyncCopy.java


import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.widget.Toast;
public class AsyncCopy extends AsyncTask<String, String, String>{
String savePath;
Activity ctx;
private ProgressDialog pDialog;
ArrayList<String> arr;
AsyncCopy(Activity _ctx,String _savePath,ArrayList<String> Files){
this.ctx = _ctx;
this.savePath = _savePath;
this.arr = Files;
}
@Override
protected void onPreExecute() {
pDialog = new ProgressDialog(ctx);
pDialog.setMessage("Copying files from asset to sdcard");
pDialog.setIndeterminate(true);
pDialog.setCancelable(false);
pDialog.show();
super.onPreExecute();
}
@Override
protected String doInBackground(String... urls) {
File f = new File(savePath);
if(!f.exists())
f.mkdir();
for(int i=0;i<arr.size();i++)
Copy(arr.get(i));
return null;
}
@Override
protected void onPostExecute(String unused) {
Toast.makeText(ctx,"Copy Done",Toast.LENGTH_LONG).show();
pDialog.hide();
}
void Copy(String fname){
try{
int count;
InputStream input= ctx.getAssets().open(fname);
OutputStream output = new FileOutputStream(savePath+"/"+fname);
byte data[] = new byte[1024];
while ((count = input.read(data))>0) {
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
}catch(Exception e){
// error while copying
}
}
}