How to Make Android Apps 15

Parse XML Android ExampleIn this video I’ll take the Android Translation app I made in part 14 and now get it to parse XML data. I’m also going to add the ability to provide XML from the web service I made in part 5 of my web services tutorial.

This is an example of the techniques I use to make a professional app. We need to use multiple languages like Java, PHP and MySQL. All of the code in the video follows below. Feel free to do anything with it.

If you like videos like this, it would help if you shared on Google Plus with a click here [googleplusone]

Code From the Video

translateit.php

<?php
header('Content-Type:text/html; charset=UTF-8');

function translate($translate_to, $matching_ids, $dbc){

    	// Represents the id name in the table so for Russian it
    	// would be russian_id
    	$translate_id = $translate_to . '_id';

/* OLD QUERY THAT DELETES DUPLICATES

SELECT word FROM russian WHERE russian_id in (131,26,69)
ORDER BY CASE russian_id
WHEN 131 THEN 1
WHEN 26 THEN 2
WHEN 69 THEN 3
WHEN 26 THEN 4
END;

NEW TRANSLATE QUERY
SELECT russian.word 
FROM russian 
JOIN(
SELECT 131 AS id, 1 AS word_order
UNION ALL SELECT 26, 2
UNION ALL SELECT 26, 3
UNION ALL SELECT 69, 4) WordsToSearch ON russian.russian_id = WordsToSearch.id
ORDER BY WordsToSearch.word_order;
*/

		$translate_query = 'SELECT word FROM ' . $translate_to . ' JOIN(' . 
			'SELECT ' . $matching_ids[0] . ' AS id, 1 AS word_order'; 

		$array_size_2 = count($matching_ids);

		for ($i = 1; $i < $array_size_2; $i++) {
    		$translate_query = $translate_query . " UNION ALL SELECT '" . $matching_ids[$i] .
    		"', " . ($i + 1) . " ";
		}

		$translate_query = $translate_query . ') WordsToSearch ON ' .
			$translate_to . '.' . $translate_id . ' = WordsToSearch.id
			ORDER BY WordsToSearch.word_order;';

		// END OF NEW TRANSLATE QUERY

    	// Issue the query to the database
    	$translate_response = mysqli_query($dbc, $translate_query);

    	if($translate_response){

        		while($row = mysqli_fetch_array($translate_response)){

        				$translated_text = $translated_text . ' ' . $row['word'];

        		}

    	}

    	return $translated_text;

} // Close function translate

function get_translation($translate_to, $english_words){

		// Trim white space from the name and store the name
        $english_words = trim($english_words);

        $english_array = array();

        // Break the words into an array
        $english_array = explode(" ", $english_words);

        // Get a connection to the database
		include('../mysqli_connect_language.php');

		// Set character set in PHP to get proper characters
		$dbc->set_charset("utf8");

/*
OLD QUERY THAT DELETES DUPLICATES

select english_id, word from english where word in ("Here", "are", "are", "dogs")
order by CASE word
WHEN "here" then 1
WHEN "are" then 2
WHEN "are" then 3
WHEN "dogs" then 4
END;

BEGINNING OF THE NEW QUERY -------------

UNION ALL combines the result set of multiple SELECT statements
which makes sure we receive all rows even if there are 
duplicates

SELECT english.word
FROM english
JOIN (
SELECT 'A' AS word, 1 AS word_order
UNION ALL SELECT 'dog', 2
UNION ALL SELECT 'a', 3
UNION ALL SELECT 'cat', 4) WordsToSearch ON english.word = WordsToSearch.word
ORDER BY WordsToSearch.word_order;
*/

		$query = "SELECT english_id, english.word FROM english JOIN(
		SELECT '" . $english_array[0] . "' AS word, 1 AS word_order";

		// Get the size of the array
		$array_size = count($english_array);

		for ($i = 1; $i < $array_size; $i++) {
    		$query = $query . " UNION ALL SELECT '" . $english_array[$i] .
    		"', " . ($i + 1) . " ";
		}

		$query = $query . ") WordsToSearch ON english.word = WordsToSearch.word
ORDER BY WordsToSearch.word_order;";

		// END OF THE NEW QUERY -------------------

        // Issue the query to the database
        $response = @mysqli_query($dbc, $query);

        // Array that contains the matching ids in order
        $matching_ids = array();

        if($response){

        	while($row = mysqli_fetch_array($response)){

        		$matching_ids[] = $row['english_id'];

        		// Holds the array after the select
        		$array_after_query[] = $row['word'];

        	}

        } // Close if($response)

        return translate($translate_to, $matching_ids, $dbc);

}

function get_all_translations($english_words){

	$language_array = array("arabic", "chinese", "danish", "dutch",
							"french", "german", "italian", "portuguese",
							"russian", "spanish");

	$translations_array = array();

	foreach($language_array as $language){

		$translations_array[] = get_translation($language,
												$english_words);

	}

	$all_translations = '{"translations": [';

	$index = 0;

	foreach($language_array as $language){

		$all_translations = $all_translations . '{"' . $language .
			'":"' . $translations_array[$index] . '"},';

		$index++;

	}

	$all_translations = rtrim($all_translations, ",");

	$all_translations = $all_translations . ']}';

	return $all_translations;

}

// ---------------------- NEW STUFF ----------------------
function get_xml_translations($english_words){

	// Used as the tag names that will surround each translation
	$language_array = array("arabic", "chinese", "danish", "dutch",
							"french", "german", "italian", "portuguese",
							"russian", "spanish");

	// Will hold all translations
	$translations_array = array();

	foreach($language_array as $language){

		$translations_array[] = get_translation($language,
												$english_words);

	}

	// Define that all data will be between 2 translations tags
	$xml = new SimpleXMLElement("<translations />");

	// Index for $language_array
	$lang_index = 0;

	// Take each translation and put it between the correct
	// language tag
	foreach($translations_array as $translation){

		$xml->addChild($language_array[$lang_index], $translation);

		$lang_index++;

	}

	// Generate a DOM document we can style
	// A DOM Document represents an entire XML document
	$dom = dom_import_simplexml($xml)->ownerDocument;

	// State we want the data to be indented
	$dom->formatOutput = true;

	// saveXML converts the XML into a string to print
	return $dom->saveXML();	

}
// ---------------------- NEW STUFF ----------------------

if(isset($_GET["action"])){

	switch($_GET["action"]){

		case "translate":
			$translate_to = $_GET["language"];
			$english_words = urldecode($_GET["english_words"]);
			$translate_text = get_translation($translate_to,
											  $english_words);
			break;

		case "translations":
			$english_words = urldecode($_GET["english_words"]);
			$translated_text = get_all_translations($english_words);
			header('Content-Type:application/json; charset=UTF-8');
			break;

		// ---------------------- NEW STUFF ----------------------
		case "xmltranslations":
			$english_words = urldecode($_GET["english_words"]);
			$translated_text = get_xml_translations($english_words);
			header('Content-Type:text/xml; charset=UTF-8');
			break;

		// ---------------------- NEW STUFF ----------------------

	}

}

echo $translated_text;

?>

MyActivity.java

package com.newthinktank.derekbanas.xmltranslates;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;


public class MyActivity extends Activity {

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

    }

    // Calls for the AsyncTask to execute when the translate button is clicked
    public void onTranslateText(View view) {

        EditText translateEditText = (EditText) findViewById(R.id.words_edit_text);

        // If the user entered words to translate then get the JSON data
        if(!isEmpty(translateEditText)){

            Toast.makeText(this, "Getting Translations",
                    Toast.LENGTH_LONG).show();

			// ---------------------- NEW STUFF ----------------------
			
            // Calls for the method doInBackground to execute
            new GetXMLData().execute();
            
            // ---------------------- NEW STUFF ----------------------

        } else {

            // Post an error message if they didn't enter words
            Toast.makeText(this, "Enter Words to Translate",
                    Toast.LENGTH_SHORT).show();

        }

    }

    // Check if the user entered words to translate
    // Returns false if not empty
    protected boolean isEmpty(EditText editText){

        // Get the text in the EditText convert it into a string, delete whitespace
        // and check length
        return editText.getText().toString().trim().length() == 0;

    }

	// ---------------------- NEW STUFF ----------------------
	
    // Allows you to perform background operations without locking up the user interface
    // until they are finished
    // The void part is stating that it doesn't receive parameters, it doesn't monitor progress
    // and it won't pass a result to onPostExecute
    class GetXMLData extends AsyncTask<Void, Void, Void>{

        // Will hold the final string to display
        String stringToPrint = "";

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

            // Holds the xml String that is retrieved from the web service
            String xmlString = "";

            // Holds the words the user wants to translate
            String wordsToTranslate = "";

            // Where the user enters the words to translate
            EditText translateEditText = (EditText) findViewById(R.id.words_edit_text);

            // Get the words the user entered in the EditText box
            wordsToTranslate = translateEditText.getText().toString();

            // Replace spaces with plus so they can be passed in the URL to the web service
            wordsToTranslate = wordsToTranslate.replace(" ", "+");

            // Client used to grab data from a provided URL
            DefaultHttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());

            // Provide the URL for the post request
            HttpPost httpPost = new HttpPost("http://newjustin.com/translateit.php?action=xmltranslations&english_words=" + wordsToTranslate);

            // Define that the data expected is in JSON format
            httpPost.setHeader("Content-type", "text/xml");

            // Allows you to input a stream of bytes from the URL
            InputStream inputStream = null;

            try {

                // The client calls for the post request to execute and sends the results back
                HttpResponse response = httpClient.execute(httpPost);

                // Holds the message sent by the response
                HttpEntity entity = response.getEntity();

                // Get the content sent
                inputStream = entity.getContent();

                // A BufferedReader is used because it is efficient
                // The InputStreamReader converts the bytes into characters
                // My JSON data is UTF-8 so I read that encoding
                // 8 defines the input buffer size
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);

                // Storing each line of data in a StringBuilder
                StringBuilder sb = new StringBuilder();

                String line = null;

                // readLine reads all characters up to a \n and then stores them
                while((line = reader.readLine()) != null){

                    sb.append(line);

                }

                // Save the results to a String
                xmlString = sb.toString();

                // Generates an XML parser
                XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

                // The XML parser that is generated will support XML namespaces
                factory.setNamespaceAware(true);

                // Gathers XML data and provides information on that data
                XmlPullParser xpp = factory.newPullParser();

                // Input the XML data for parsing
                xpp.setInput(new StringReader(xmlString));

                // The event type is either START_DOCUMENT, END_DOCUMENT, START_TAG,
                // END_TAG, TEXT
                int eventType = xpp.getEventType();

                // Cycle through the XML document until the document ends
                while (eventType != XmlPullParser.END_DOCUMENT) {

                    // Each time you find a new opening tag the event type will be START_TAG
                    // We want to skip the first tag with the name translations
                    if ((eventType == XmlPullParser.START_TAG) && (!xpp.getName().equals("translations"))) {

                        // getName returns the name for the current element with focus
                        stringToPrint = stringToPrint + xpp.getName() + " : ";

                        // getText returns the text for the current event
                    } else if (eventType == XmlPullParser.TEXT) {
                        stringToPrint = stringToPrint + xpp.getText() + "\n";
                    }
                    // next puts focus on the next element in the XML doc
                    eventType = xpp.next();
                }

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

            return null;
        }
        
        // ---------------------- NEW STUFF ----------------------

        @Override
        protected void onPostExecute(Void aVoid) {

            TextView translateTextView = (TextView) findViewById(R.id.translate_text_view);

            translateTextView.setText(stringToPrint);

        }
    }


}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.newthinktank.derekbanas.xmltranslates" >

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MyActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

activity_my.xml

<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"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MyActivity">

    <EditText
        android:id="@+id/words_edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/translate_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/words_edit_text"
        android:layout_alignParentLeft="true"
        android:layout_marginTop="15dp"
        android:text="@string/translate_button"
        android:onClick="onTranslateText"/>

    <TextView
        android:id="@+id/translate_text_view"
        android:text="@string/translate_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/words_edit_text"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="65dp" />

</RelativeLayout>

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">XML Translates</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="translate_text_view">Enter the words to translate above</string>
    <string name="translate_button">Translate</string>

</resources>

2 thoughts on “How to Make Android Apps 15”

  1. Hi Derek:

    I’m Gokulraj 32 from India. I am physics graduate and work as a medical transcriptionist.

    I don’t have any CS background and want to move to programming. I have begun teaching myself by reading stuff on the Web here and there.

    Can you help me chart out definite plan for teaching myself. Where to begin, which books to read, etc.

    Your guidance would be of immense help.

    Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *