Toggle Solar Noon and current time using Json in Android Studio

Objective:
To toggle current time and solar noon time using Json

Function:
When the toggle is pressed, small pop up will be displayed to inform the status of network connectivity. Once network is established, Json data will be retrieved and display it on TextView.

IDE:
Android Studio 1.0.2

Source Code:
The project can be downloaded from here.

Result:




















Explanation:

1. As usual, we need to add permission to AndroidManifest.xml





2. Then we need to commit the Fragment in MainActivity.java.

/*way of adding fragment with java*/
        //FragmentOne is the class which inflate the fragment_one.xml and return the view
        FragmentOne myFragment = new FragmentOne();
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        //'container' is android id in activity_main.xml
        //add android:id="@+id/container" in activity_main.xml
        transaction.add(R.id.container, myFragment, "main_layout_container");
        transaction.commit();

3. In FragmentOne.java, we first setup toggle on/off switch to display
//create Switch 'switchTime' and link with Switch id from fragment_one.xml
        final Switch switchTime = (Switch) view.findViewById(R.id.switchTime);
        //default set as true;
        switchTime.setChecked(true);
        //set Text inside switch toggle name
        switchTime.setTextOn("Solar Noon Time");
        switchTime.setTextOff("Current Time");
        //set Text for switch name
        switchTime.setText("Time");

4. In FragmentOne.java, we implement setOnCheckedChangedListener to detect the toggle.
Also take note that Object of JsonHelperClass is created with Context which will be used in HttpURLConnection.

switchTime.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            //need to pass context to JsonHelperClass
            JsonHelperClass jsonHelperClass = new JsonHelperClass(context);
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    //get solar noon time for today and display on textView
                    textViewPress.setText(jsonHelperClass.getResult(SOLAR_NOON));

                } else {
                    //get current time and display on textView
                    textViewPress.setText(jsonHelperClass.getResult(CURRENT_TIME));
                }
            }
        });

5. In JsonHelperClass.java, more interesting stuff are happening here. The context passed from FragmentOne.java is first used in constructor.
//JsonHelperClass Constructor
    public JsonHelperClass(Context context) {
       // context is passed from FragmentOne.java; to be used in JsonHelperClass
        this.context = context;
    }

6. In JsonHelperClass.java, we first check the network connectivity. If the network is connected, then we will proceed with json parsing.
private boolean isConnectedToNetwork() {
        boolean connection;
        //ConnectivityManager required context
        //context is passed from FragmentOne.java
        ConnectivityManager connMgr = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            // small popup to show the status of network connection
            Toast.makeText(context, "Internet is connected",
                    Toast.LENGTH_SHORT).show();
            connection = true;
        } else {
            Toast.makeText(context, "Internet is not connected",
                    Toast.LENGTH_SHORT).show();
            connection = false;
        }
        return connection;
    }
7. In JsonHelperClass.java, before we parse the json, we need to establish http connection to retrieve data from api provided by respective website. Take note that there is no running thread in background. Therefore, it might be some delay processing the connection. This is just for the simplicity. More should be done with Async Task. Once http connection is estiblished, we need to get stream data to pass to json parsing function.
private void fetchMeJson() {

        //Ref website
        // http://stackoverflow.com/questions/8706464/defaulthttpclient-to-androidhttpclient
        //this is just for the simplicity
        //it is always recommended to move network operation off the UI thread, for example, using AsyncTask.
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
        try {
            String urlLink;
            switch (exampleNumber) {
                case 1:
                    urlLink = "http://api.sunrise-sunset.org/json?lat=1.352083&lng=103.819836";
                    break;
                case 2:
                    urlLink = "http://date.jsontest.com";
                    break;
               /* case 3:
                //just extra example
                    urlLink = "http://api.openweathermap.org/data/2.5/weather?q=Antarctica";
                    break;
                */
                default:
                    urlLink = "http://api.sunrise-sunset.org/json?lat=1.352083&lng=103.819836";
            }
            //Ref from http://www.tutorialspoint.com/android/android_json_parser.htm
            URL url = new URL(urlLink);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(10000 /* milliseconds */);
            conn.setConnectTimeout(15000 /* milliseconds */);
            //below two line are default themselves; no need to set for getting data
            //but need to set explicitly if we want to post data
            conn.setRequestMethod("GET");
            conn.setDoInput(true);
            // Starts the query
            conn.connect();
            InputStream stream = conn.getInputStream();

            String data = convertStreamToString(stream);

            readAndParseJSON(data);
            stream.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

8. In JsonHelperClass.java, we will parse the data stream and get appropriate data. Two example are provided to be more familiar with Json parsing. The resultant data will be pass it back to String of 'result' in class.
private void readAndParseJSON(String in) {
        try {
            JSONObject reader = new JSONObject(in);

            switch (exampleNumber) {
                case 1:
                    //time is expressed using the GMT time zone.
                    JSONObject solarNoon = reader.getJSONObject("results");
                    result = solarNoon.getString("solar_noon");
                    break;
                case 2:
                    //time is expressed using the GMT time zone.
                    result = reader.getString("time");
                    break;
          /*      case 3:
                    //just extra example
                    JSONObject main = reader.getJSONObject("main");
                    result = main.getString("temp");
                    break;*/
                default:

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
9. In JsonHelperClass.java, finally overall picture of getting result can be seen on this following function.
public String getResult(int exampleNumber) {
        this.exampleNumber = exampleNumber;
        //only fetch json if there is network connection
        if (isConnectedToNetwork()) {
            fetchMeJson();
        }
        return result;
    }


Complete Code:


Content of MainActivity.java
package com.example.osdevlab.simpletutorial;

import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;


public class MainActivity extends ActionBarActivity {

    public static Context context;


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

        /*way of adding fragment with java*/
        //FragmentOne is the class which inflate the fragment_one.xml and return the view
        FragmentOne myFragment = new FragmentOne();
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        //'container' is android id in activity_main.xml
        //add android:id="@+id/container" in activity_main.xml
        transaction.add(R.id.container, myFragment, "main_layout_container");
        transaction.commit();
    }


}

Content of FragmentOne.java
package com.example.osdevlab.simpletutorial;


import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;

/**
 * Created by osdevlab on 12/29/14.
 */
public class FragmentOne extends Fragment {
    static final int SOLAR_NOON = 1;
    static final int CURRENT_TIME = 2;


    Context context;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // Inflate the layout with fragment_one.xml
        View view = inflater.inflate(R.layout.fragment_one, container, false);

        //create TextView 'textViewPress' and link with texView id from fragment_one.xml
        final TextView textViewPress = (TextView) view.findViewById(R.id.textView);


        //returns the Activity the Fragment is currently associated with
        //In Fragment, this step requires to pass context to other class.
        context = getActivity();

        //create Switch 'switchTime' and link with Switch id from fragment_one.xml
        final Switch switchTime = (Switch) view.findViewById(R.id.switchTime);
        //default set as true;
        switchTime.setChecked(true);
        //set Text inside switch toggle name
        switchTime.setTextOn("Solar Noon Time");
        switchTime.setTextOff("Current Time");
        //set Text for switch name
        switchTime.setText("Time");

        switchTime.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            //need to pass context to JsonHelperClass
            JsonHelperClass jsonHelperClass = new JsonHelperClass(context);
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    //get solar noon time for today and display on textView
                    textViewPress.setText(jsonHelperClass.getResult(SOLAR_NOON));

                } else {
                    //get current time and display on textView
                    textViewPress.setText(jsonHelperClass.getResult(CURRENT_TIME));
                }
            }
        });
        return view;
    }
}

Content of JasonHelperClass.java
package com.example.osdevlab.simpletutorial;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.StrictMode;
import android.widget.Toast;
import org.json.JSONObject;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by osdevlab on 12/30/14.
 */


public class JsonHelperClass {
    Context context;
    private String result = "default result";
    private int exampleNumber = 1;

    //JsonHelperClass Constructor
    public JsonHelperClass(Context context) {
       // context is passed from FragmentOne.java; to be used in JsonHelperClass
        this.context = context;
    }

    static String convertStreamToString(java.io.InputStream is) {
        java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }

    public String getResult(int exampleNumber) {
        this.exampleNumber = exampleNumber;
        //only fetch json if there is network connection
        if (isConnectedToNetwork()) {
            fetchMeJson();
        }
        return result;
    }

    private boolean isConnectedToNetwork() {
        boolean connection;
        //ConnectivityManager required context
        //context is passed from FragmentOne.java
        ConnectivityManager connMgr = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            // small popup to show the status of network connection
            Toast.makeText(context, "Internet is connected",
                    Toast.LENGTH_SHORT).show();
            connection = true;
        } else {
            Toast.makeText(context, "Internet is not connected",
                    Toast.LENGTH_SHORT).show();
            connection = false;
        }
        return connection;
    }

    private void fetchMeJson() {

        //Ref website
        // http://stackoverflow.com/questions/8706464/defaulthttpclient-to-androidhttpclient
        //this is just for the simplicity
        //it is always recommended to move network operation off the UI thread, for example, using AsyncTask.
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
        try {
            String urlLink;
            switch (exampleNumber) {
                case 1:
                    urlLink = "http://api.sunrise-sunset.org/json?lat=1.352083&lng=103.819836";
                    break;
                case 2:
                    urlLink = "http://date.jsontest.com";
                    break;
               /* case 3:
                //just extra example
                    urlLink = "http://api.openweathermap.org/data/2.5/weather?q=Antarctica";
                    break;*/
                default:
                    urlLink = "http://api.sunrise-sunset.org/json?lat=1.352083&lng=103.819836";
            }
            //Ref from http://www.tutorialspoint.com/android/android_json_parser.htm
            URL url = new URL(urlLink);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(10000 /* milliseconds */);
            conn.setConnectTimeout(15000 /* milliseconds */);
            //below two line are default themselves; no need to set for getting data
            //but need to set explicitly if we want to post data
            conn.setRequestMethod("GET");
            conn.setDoInput(true);
            // Starts the query
            conn.connect();
            InputStream stream = conn.getInputStream();

            String data = convertStreamToString(stream);

            readAndParseJSON(data);
            stream.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void readAndParseJSON(String in) {
        try {
            JSONObject reader = new JSONObject(in);

            switch (exampleNumber) {
                case 1:
                    //time is expressed using the GMT time zone.
                    JSONObject solarNoon = reader.getJSONObject("results");
                    result = solarNoon.getString("solar_noon");
                    break;
                case 2:
                    //time is expressed using the GMT time zone.
                    result = reader.getString("time");
                    break;
          /*      case 3:
                    //just extra example
                    JSONObject main = reader.getJSONObject("main");
                    result = main.getString("temp");
                    break;*/
                default:

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

No comments:

Post a Comment