Designing the App screens

One of the most important features in an app is displaying the data correctly and professionally. Parsing the data from the database is a significant feature of an app which needs to be handled, but still, showing the correct data to the users is utterly significant to develop a successfull app.

The newest version of most Android apps published by Google have started featuring cards. Many other apps being designed since late 2014, are also following this trend. A card is nothing more than a layout or a view with a background drawable. And that drawable can be defined in XML as a layer drawable.

The app will have the following screens:

  • Home
  • Event
  • Facebook
  • Map
  • Forum

Just like the screens in the login, registration and forget password ones are defined by a the minimalistic card layout an orange background, as required by the customer.

The reason for using a fragment instead of an activity, is because one activity (which is the main activity) can contain several fragments which interchange. A Fragment represents a behavior or a portion of user interface in an Activity. Multiple fragments can be combined in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running.

public boolean onCreateOptionsMenu(Menu menu) {
    if (!mNavigationDrawerFragment.isDrawerOpen()) {
        getMenuInflater().inflate(R.menu.main, menu);
        restoreActionBar();
        return true;
    }
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

public static class PlaceholderFragment extends Fragment {

    private static final String ARG_SECTION_NUMBER = "section_number";

    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);
        return rootView;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        ((MainActivity) activity).onSectionAttached(getArguments().getInt(ARG_SECTION_NUMBER));
    }
}

A fragment must always be embedded in an activity and the fragment’s lifecycle is directly affected by the host activity’s lifecycle. For example, when the activity is paused, so are all fragments in it, and when the activity is destroyed, so are all fragments. However, while an activity is running, you can manipulate each fragment independently, such as add or remove them. When you perform such a fragment transaction, you can also add it to a back stack that’s managed by the activity—each back stack entry in the activity is a record of the fragment transaction that occurred.

HomeFragment

The Home Fragment contains a daily quotation which changes each time the app is started. Following are the xml and java code which build this fragment:

<?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:id="@+id/RelativeLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#F38121">

    <ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="wrap_content"
        android:layout_height="350dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center_horizontal"
            android:orientation="vertical"
            android:layout_margin="15dp"
            android:padding="15dp"
            android:background="@drawable/card_background"
            android:weightSum="1">>

            <TextView
                android:id="@+id/Quote"
                android:layout_width="match_parent"
                android:layout_height="250dp"
                android:gravity="center_horizontal"
                android:scrollY="@dimen/activity_vertical_margin"
                android:scrollbarAlwaysDrawVerticalTrack="true"
                android:scrollbarStyle="insideOverlay"
                android:scrollbars="vertical"
                android:textColor="#878787"
                android:textSize="25sp"
                android:typeface="serif"
                android:layout_weight="1" />

            <TextView
                android:id="@+id/Author"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:gravity="end"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="#878787"
                android:textStyle="italic" />
        </LinearLayout>
    </ScrollView>

    <ScrollView
        android:id="@+id/scrollView2"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_below="@id/scrollView1"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical"
            android:layout_margin="15dp"
            android:padding="15dp"
            android:background="@drawable/card_background">

            <TextView
                android:id="@+id/info"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center_horizontal"
                android:gravity="center|center_horizontal"
                android:text="Chaplaincy \n G.F. Abela Junior College \n Ġużè Debono Square \n Msida MSD 1252 \n \n email: chaplaincy.jc@um.edu.mt \n Chaplain: Rev. Marco Portelli"
                android:singleLine="false"
                android:textAppearance="?android:attr/textAppearanceMedium" />

        </LinearLayout>
    </ScrollView>

</RelativeLayout>
package com.chaplaincy.jc.tibiapp;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.method.ScrollingMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created by Michele La Ferla on 21/02/2015.
 */
public class HomeFragment extends Fragment {

    public static String name, author, conCat;
    private ProgressDialog pDialog;

    JSONParser jParser = new JSONParser();

    ArrayList<HashMap<String, String>> InspireList;
    private static final String url_quote_details = "http://tibi.scienceontheweb.net/qt_handler.php";

    private static final String CONNECTION_STATUS = "success";
    private static final String TABLE_QUOTE = "Quote";
    private static final String COL_DESC = "Quote_Desc";
    private static final String COL_AUTHOR = "Quote_Author";

    JSONArray Inspiration = null;

    TextView quote, writer;

    public static final String ARG_SECTION_NUMBER = "section_number";

    public HomeFragment() {

    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

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

        View HomeView = inflater.inflate(R.layout.fragment_home, container,
                false);

        return HomeView;
    }

    public void onStart() {
        super.onStart();

        InspireList = new ArrayList<HashMap<String, String>>();
        new LoadQuote().execute();
    }

    class LoadQuote extends AsyncTask<String, String, String> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(getActivity());
            pDialog.setMessage("Just a moment...");
            pDialog.setIndeterminate(true);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        protected String doInBackground(String... args) {
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            JSONObject json = jParser.getJSONFromUrl(url_quote_details,"GET", params);

            try {
                int success = json.getInt(CONNECTION_STATUS);

                if (success == 1) {
                    Inspiration = json.getJSONArray(TABLE_QUOTE);
                    for (int i = 0; i < Inspiration.length(); i++) {
                        JSONObject insp = Inspiration.getJSONObject(i);

                        name = insp.getString(COL_DESC);
                        author = insp.getString(COL_AUTHOR);

                        conCat = name + "_" + author;

                    }
                } else {
                    pDialog.dismiss();
                }
            } catch (JSONException e) {
                pDialog.dismiss();
                e.printStackTrace();
            }
            return conCat;
        }

        protected void onPostExecute(final String result) {
            pDialog.dismiss();
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    String[] divorce = result.split("_");
                    divorce[0] = name;
                    divorce[1] = author;

                    quote = (TextView) getView().findViewById(R.id.Quote);
                    quote.setMovementMethod(new ScrollingMovementMethod( ));
                    writer = (TextView) getView().findViewById(R.id.Author);

                    quote.setText(name);
                    writer.setText(author);
                }
            });
        }
    }
}

Event Fragment

The events fragment contains details for each event including its location. This location is then displayed on the map fragment. This is the xml code for the event fragment:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="15dp"
    android:paddingRight="15dp"
    android:descendantFocusability="beforeDescendants">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="15dp"
        android:paddingTop="15dp"
        android:paddingBottom="15dp"
        android:paddingRight="15dp"
        android:background="@drawable/card_selector"
        android:descendantFocusability="afterDescendants">

        <TextView
            android:id="@+id/text1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:id="@+id/text2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:id="@+id/text3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</FrameLayout>
package com.chaplaincy.jc.tibiapp;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created by mlaferla on 27/01/2015.
 */

public class EventFragment extends ListFragment {

    ArrayList<HashMap<String, String>> eventList;
    private String url_all_events = "http://tibi.scienceontheweb.net/evt_handler.php";
    private ProgressDialog pDialog;
    static String id;
    static String name;
    static String date;
    static String time;

    JSONParser jParser = new JSONParser();

    // JSON Node names
    private static final String CONNECTION_STATUS = "success";
    private static final String TABLE_EVENT = "Event";
    private static final String pid = "evtID";
    private static final String COL_NAME = "evtName";
    private static final String COL_DATE = "evtDate";
    private static final String COL_TIME = "evtTime";

    public final static String DATE = COL_DATE;
    public final static String TIME = COL_TIME;

    JSONArray Events = null;

    public static final String ARG_SECTION_NUMBER = "section_number";

    public EventFragment() {
    }

    public void onStart() {
        super.onStart();

        eventList = new ArrayList<HashMap<String, String>>();

        ListView lv = getListView();
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_events, container, false);

        Intent intent = new Intent(getActivity(), MainActivity.class);

        intent.putExtra(DATE, date);
        intent.putExtra(TIME, time);
        startActivity(intent);

        return rootView;
    }

    public class LoadAllEvents extends AsyncTask<String, String, String> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(getActivity());
            pDialog.setMessage("Just a moment...");
            pDialog.setIndeterminate(true);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        protected String doInBackground(String... args) {
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            JSONObject json = jParser.getJSONFromUrl(url_all_events, "GET", params);

            try {
                // Checking for SUCCESS TAG
                int success = json.getInt(CONNECTION_STATUS);

                if (success == 1) {
                    Events = json.getJSONArray(TABLE_EVENT);
                    for (int i = 0; i < Events.length(); i++) {
                        JSONObject evt = Events.getJSONObject(i);

                        id = evt.getString(pid);
                        name = evt.getString(COL_NAME);
                        date = evt.getString(COL_DATE);
                        time = evt.getString(COL_TIME);

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

                        hmap.put(pid, id);
                        hmap.put(COL_NAME, name);
                        hmap.put(COL_DATE, date);
                        hmap.put(COL_TIME, time);

                        eventList.add(hmap);
                    }
                } else {
                    // Options are not available or server is down.
                    // Dismiss the loading dialog and display an alert
                    // onPostExecute
                    pDialog.dismiss();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }

        protected void onPostExecute(String file_url) {
            pDialog.dismiss();
            getActivity().runOnUiThread(new Runnable() {
                public void run() {
                    ListAdapter adapter = new SimpleAdapter(getActivity(),
                            eventList, R.layout.test_card, new String[] {
                            pid, COL_NAME, COL_DATE, COL_TIME },
                            new int[] { R.id.pid, R.id.evtType, R.id.evtDate, R.id.evtTime});

                    setListAdapter(adapter);
                }
            });
        }
    }
}

Facebook Fragment

This fragment contains a link to the official Facebook page of the client, to be able to view posts, updates and information about the organisation.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:background="@drawable/card_background"
    android:layout_height="match_parent">

    <WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/webView"
        android:padding="15dp"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/card_background" />
</LinearLayout>
package com.chaplaincy.jc.tibiapp;

/**
 * Created by mlaferla on 27/01/2015.
 */
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;

public class FacebookFragment extends Fragment {

    public static final String ARG_SECTION_NUMBER = "section_number";

    public FacebookFragment() {

    }

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

        View mainView = inflater.inflate(R.layout.fragment_facebook, container, false);
        WebView webView = (WebView) mainView.findViewById(R.id.webView);

        webView.setWebViewClient(new MyWebViewClient());
        webView.getSettings().setSupportZoom(false);
        webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        webView.getSettings().setAllowFileAccess(true);
        webView.getSettings().setDomStorageEnabled(true);
        webView.loadUrl("https://www.facebook.com/TiBiGroup");

        return mainView;
    }
}

Map Fragment

The map contains the details of the events and according to the longitude and latitude values for each event. Below is the design code for this fragment:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#F38121" >

    <fragment
        android:id="@+id/mapView"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="15dp"
        android:padding="15dp" />

</RelativeLayout>

The actual code which changes the location of each event will be discussed in a later blog post.

Forum Fragment

The forum fragment will be available to all those using the app to use the forum to communicate with each other. Since the app will be distributed to a small number of people, which is closed to a small community of the group members. Below is the code for the design of the forum fragment:

<LinearLayout 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"
    android:background="@drawable/tile_bg"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/list_view_messages"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@null"
        android:divider="@null"
        android:transcriptMode="alwaysScroll"
        android:stackFromBottom="true">
    </ListView>

    <LinearLayout
        android:id="@+id/llMsgCompose"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:orientation="horizontal"
        android:weightSum="3" >

        <EditText
            android:id="@+id/inputMsg"
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="2"
            android:background="@color/bg_msg_input"
            android:textColor="@color/text_msg_input"
            android:paddingLeft="6dp"
            android:paddingRight="6dp"/>

        <Button
            android:id="@+id/btnSend"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@color/bg_btn_join"
            android:textColor="@color/white"
            android:text="Send" />
    </LinearLayout>

</LinearLayout>

User Registration and Handling

In the app which is being designed, one of the main features which are needed is user creation and management. Particularly, the app will need to handle the following:

  • Creation of a new user.
  • Forgetting a password.
  • Checking if a user exists.
  • Keeping the user logged into his/her account when the user returns to the app (using SharedPreferences).

To interact with MySQL database we need to build an API first. API job is to get the request from client, interact with database and finally give the response back to client. So we’ll create a simple PHP, MySQL API first. The Android Volley does the below jobs.

  1. Accepts requests in GET/POST methods.
  2. Interact with database by inserting / fetching data.
  3. Finally will give response back in JSON format.

Android Volley will be discussed in the next blog post, but for the time being we will be only discussing parsing through JSON.

Creation of a new User

Below is the creation of a new user screen on the application client tier. The fields in the screen accept values as required to be entered into the database.

Full name          String with capitalisation on first letters of new words

Email Address   String which must be entered in email format

Password           A masked string

Below is how the registration would look like:

registration

The data is then parsed and uploaded through the app through the following method:

public JSONObject getJSONFromUrl(String url, String method, List<NameValuePair> params) {

        // Making HTTP request
        try {

            // check for request method
            if (method == "POST") {
                // request method is POST
                // defaultHttpClient
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(url);
                httpPost.setEntity(new UrlEncodedFormEntity(params));

                HttpResponse httpResponse = httpClient.execute(httpPost);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();

            } else if (method == "GET") {
                // request method is GET
                DefaultHttpClient httpClient = new DefaultHttpClient();
                String paramString = URLEncodedUtils.format(params, "utf-8");
                url += "?" + paramString;
                HttpGet httpGet = new HttpGet(url);

                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();
            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            json = sb.toString();
        } catch (Exception e) {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }

        // try parse the string to a JSON object
        try {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }

        // return JSON String
        return jObj;

}

This then adds a new record to the database through the following PHP code:

public function saveUser($name, $password) {
 $usrID = uniqid('', true);
 $hash = $this->hashSSHA($password);
 $encrypted_password = $hash["encrypted"];
 $salt = $hash["salt"];
 $result = $con->query("INSERT INTO User (userID, fullName, userEmail, password, salt, dateCreated, dateModified) VALUES('NULL', '$usrName', '$usrEmail', '$encrypted_password', '$hash' CURRENT_TIMESTAMP, NOW())");
 
 if ($result) {
 $uid = mysqli_insert_id();
 $result = $con->query("SELECT * FROM User WHERE userID = '$usrID'");
 
 return mysqli_fetch_array($result, MYSQL_ASSOC);
 } else {
 return false;
 }
 }

This inserts a new record into the database.

Forgetting a Password

When a user forgets a password, the app has the facility of entering a new password through the following screen:

forget

The code behind this screen calls a PHP function which updates the record of the user with a new password. The scripting for this function has already been discussed in an earlier tutorial.

Checking if the User Exists

One of the most important steps in the handling of users is the validation of the correct username and password. This is done through the following scripts:

 public function getUser($usrEmail, $password) {
 
 $usrEmail = mysqli_real_escape_string($userEmail);
 $password = mysqli_real_escape_string($password);
 $query = "SELECT userEmail, password FROM User WHERE userEmail = '$usrEmail'";
 
 $result = mysqli_query($con, $query)or die(mysqli_error());
 
 $rowNum = mysqli_num_rows($result);
 
 if ($rowNum == 1) {
 $result = mysqli_fetch_array($result, MYSQL_ASSOC);
 $salt = $result['salt'];
 $encrypted_password = $result['encrypted_password'];
 $hash = $this->checkhashSSHA($salt, $password);
 
 if ($encrypted_password == $hash) {
 return $result;
 }
 } else {
 return false;
 }
 }
 
 public function isExisting($email) {
 $result = $con->query("SELECT userEmail from User WHERE userEmail = '$usrEmail'");
 $rowNum = mysqli_num_rows($result);
 
 if ($rowNum > 0) {
 return true;
 } else {
 return false;
 }
 }

Using Shared Preferences

With the usage of Shared Preferences a users’ details can easily pass data from one screen to another in an Android app. If you have a relatively small collection of key-values that you’d like to save, you should use the SharedPreferences APIs. A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them. Each SharedPreferences file is managed by the framework and can be private or shared.

This is particularly important when using the chat screen in the app, to identify the user name. Below is the code for this:

public class SessionManager {

        SharedPreferences pref;
        Editor editor;
        Context _context;
        int PRIVATE_MODE = 0;

        private static final String PREF_NAME = "usrLogin";
        private static final String IS_LOGIN = "IsLoggedIn";
        public static final String KEY_EMAIL = "email";

        public SessionManager(Context context){
            this._context = context;
            pref = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);
            editor = pref.edit();
        }

        public void createLoginSession(String email){
            editor.putBoolean(IS_LOGIN, true);
            editor.putString(KEY_EMAIL, email);
            editor.commit();
        }

        public void checkLogin(){
            if(!this.isLoggedIn()){
                // user is not logged in redirect him to Login Activity
                Intent i = new Intent(_context, LoginActivity.class);

                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                // Staring Login Activity
                _context.startActivity(i);
            }

        }

        public HashMap<String, String> getUserDetails(){
            HashMap<String, String> user = new HashMap<String, String>();
            // user user email
            user.put(KEY_EMAIL, pref.getString(KEY_EMAIL, null));

            // return user
            return user;
        }

        public void logoutUser(){
            editor.clear();
            editor.commit();

            Intent i = new Intent(_context, LoginActivity.class);
            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            _context.startActivity(i);
        }

        public boolean isLoggedIn(){
            return pref.getBoolean(IS_LOGIN, false);
        }
}

Parsing the data to the App

After scripting the database through PHP, the next step would be to parse the data from the database to be viewable to the app. This can be through two main methods; either by parsing the data through XML, or else through JSON. Below I will be discussing the the pros and cons of both methods, and then give reasons why I chose to parse the data through JSON over XML.

XML Parsing

XML parsing in android is done using the DOM parser. The parser class mainly deals the following operations:

  • Getting XML content by making HTTP request.
  • Parsing XML content and getting DOM element of xml.
  • Get each xml child element value by passing element node name.

The xml document is parsed by making http requests through Android code. A typical http request would be the following:

public String getXmlFromUrl(String url) {
String xml = null;
        try {
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);
            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            xml = EntityUtils.toString(httpEntity);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // return XML
        return xml;
}
After getting the XML content, the next would be to get the DOM element of the XML file. Finally the data elements need to be getting each xml child element value by passing element node name. The code in the app would then call the DOM file to update the data.
One of the main advantages of XML parsing is that it is visually more readable.
On the other hand, it is more difficult to code-wise to parse the data through xml.
JSON Parsing 
JSON is very light weight, structured, easy to parse and much human readable. JSON is best alternative to XML when the android app needs to interchange data and get information from the server. The following code will parse the data from the data with regards to the daily random quotations, from the following URL: http://tibi.scienceontheweb.net/qt_handler.php
{
 "Quote": [
 {
 "quoteID": "1",
 "quoteName": "For God so loved the world that he gave his one and only Son, that whoever believes in him shall not perish but have eternal life.",
 "quoteAuthor": "John 3:16"
 }
 ],
 "success": 1
}

The above is the data parsed from the Quote table in the database.

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.

The following is the code for parsing the data using the JSONParser class in Android:

public JSONObject getJSONFromUrl(String url, List<NameValuePair> params) {
    try {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new UrlEncodedFormEntity(params));

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "iso-8859-1"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
        Log.e("JSON", json);
    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    // try parse the string to a JSON object
    try {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

    // return JSON String
    return jObj;
}

Finally, the app will show the data in the following doInBackground method:

protected String doInBackground(String... args) {
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    JSONObject json = jParser.getJSONFromUrl(url_quote_details,"GET", params);

    try {
        int success = json.getInt(CONNECTION_STATUS);

        if (success == 1) {
            Inspiration = json.getJSONArray(TABLE_QUOTE);
            for (int i = 0; i < Inspiration.length(); i++) {
                JSONObject insp = Inspiration.getJSONObject(i);

                name = insp.getString(COL_DESC);
                author = insp.getString(COL_AUTHOR);

                conCat = name + "_" + author;

            }
        } else {
            pDialog.dismiss();
        }
    } catch (JSONException e) {
        pDialog.dismiss();
        e.printStackTrace();
    }
    return conCat;
}

The app shows the data in the following method:

protected String doInBackground(String... args) {
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    JSONObject json = jParser.getJSONFromUrl(url_quote_details,"GET", params);

    try {
        int success = json.getInt(CONNECTION_STATUS);

        if (success == 1) {
            Inspiration = json.getJSONArray(TABLE_QUOTE);
            for (int i = 0; i < Inspiration.length(); i++) {
                JSONObject insp = Inspiration.getJSONObject(i);

                name = insp.getString(COL_DESC);
                author = insp.getString(COL_AUTHOR);

                conCat = name + "_" + author;

            }
        } else {
            pDialog.dismiss();
        }
    } catch (JSONException e) {
        pDialog.dismiss();
        e.printStackTrace();
    }
    return conCat;
}

Below is how the parsed text would look in the App:

Capture