Introduction
This tutorial is a brief guide on how to intergrate your Android App to Wamp Server : this could be hosted on you local machine or on a remote server.
Background
Android has an inbuilt database called SQLITE which is shipped with Android but the problem with it is that the people that developed were not thinking Objects(OOP) yet today's progamming revolves around use of Objects(OOP) therefore using MYSQL will offer you a better OOP style and abstration thus quicker response to complex queries
The other point is for security purposes ;having a database in SQL provides better security plus more storage
Using the code
Below is the the entire sample source code but before you deploy this code ensure the following;
- Set you Apache httpd.conf file to accept connections from all services/connections i.e Allow from all
- Ensure that you using WAMPSERVER 2.4 ,Apache/2.4.4 and PHP/5.4.16 that supports PHP Data Objects ( PDO)http://www.wampserver.com/en/
- For the URL please use a remote ip address i.e 192.168.0.1/jsondemo.register.php.Don't use you local address like 127.0.0.1/register.php or localhost/register.php because the application will always crush therefore ensure that you pc is connected to a network,internet so that it can attain a valid ip address
- Put the php code into your wamp www directory
- And then import the sample database into you server
Below is the xml file that collects informations about a user to be registered.Keeping all things basic
//
// ="1.0"="utf-8"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="FirstName:"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:textSize="17sp"/>
<EditText android:id="@+id/fname"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_marginBottom="15dip"
android:singleLine="true"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="LastName:"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:textSize="17sp"/>
<EditText android:id="@+id/lname"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_marginBottom="15dip"
android:singleLine="true"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Username:"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:textSize="17sp"/>
<EditText android:id="@+id/uname"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_marginBottom="15dp"
android:singleLine="true"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Password:"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:textSize="17dip"/>
<EditText android:id="@+id/pass"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_marginBottom="15dp"
android:singleLine="true"
android:inputType="textPassword"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Address"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:textSize="17sp"/>
<EditText android:id="@+id/addr"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_marginBottom="15dip"
android:singleLine="true"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Contact:"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:textSize="17sp"/>
<EditText android:id="@+id/contact"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_marginBottom="15dp"
android:singleLine="true"/>
<Button android:id="@+id/btnreg"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Submit"/>
<Button android:id="@+id/btncancel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Cancel"/>
</LinearLayout>
</ScrollView>
//
Below is the JSONParser class that sends an http request in form of a POST or GET method plus also getting the JSON data sent by the MYSQL queries
//
package com.code256.jsonmysql;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class JSONParser{
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
public JSONParser() {
}
public JSONObject makeHttpRequest(String url, String method,
List<NameValuePair> params) {
try {
if(method == "POST"){
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"){
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 {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
return jObj;
}
public JSONObject getJSONFromUrl(final String url) {
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
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();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
return jObj;
}
}
Below is a class that interacts with the our layout reg_activity.xml.Am using the AsyncTask<, , > helper class that performs background operations and publish the results in the UI thread without having to manipulate the thread or other handlers. An asynchronous task is defined by 3 generic types, called Params
, Progress
and Result
, and 4 steps, called onPreExecute
, doInBackground
, onProgressUpdate
and onPostExecute
.
package com.code256.jsonmysql;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class RegActivity extends Activity {
private ProgressDialog pDialog;
JSONParser jsonParser = new JSONParser();
EditText fname;
EditText lname;
EditText username;
EditText password;
EditText location;
EditText contact;
Button btnreg;
Button btncancel;
private static String url_new_user = "http://172.16.3.82/jsonmysqldemo/new_user.php";
private static final String TAG_SUCCESS = "success";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.reg_activity);
fname = (EditText) findViewById(R.id.fname);
lname = (EditText) findViewById(R.id.lname);
username = (EditText) findViewById(R.id.uname);
password = (EditText) findViewById(R.id.pass);
location = (EditText) findViewById(R.id.addr);
contact = (EditText) findViewById(R.id.contact);
btnreg = (Button) findViewById(R.id.btnreg);
btncancel = (Button) findViewById(R.id.btncancel);
btnreg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new CreateNewProduct().execute();
}
});
btncancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
}
});
}
class CreateNewProduct extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(RegActivity.this);
pDialog.setMessage("Registering New User..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
protected String doInBackground(String... args) {
String Firstname = fname.getText().toString();
String Lastname = lname.getText().toString();
String Username = username.getText().toString();
String Password = password.getText().toString();
String Address = location.getText().toString();
String Contact = contact.getText().toString();
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("fname", Firstname));
params.add(new BasicNameValuePair("lname", Lastname));
params.add(new BasicNameValuePair("username", Username));
params.add(new BasicNameValuePair("password", Password));
params.add(new BasicNameValuePair("location", Address));
params.add(new BasicNameValuePair("contact", Contact));
JSONObject json = jsonParser.makeHttpRequest(url_new_user,
"POST", params);
Log.d("Create Response", json.toString());
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
Intent i = new Intent(getApplicationContext(), RegActivity.class);
startActivity(i);
finish();
} else {
Log.d("failed to create user", json.toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
}
}
}
Below is the manifest xml file..all things are basic except that we need some permissions of internet because this simple app will need to access the internet
="1.0"="utf-8"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.code256.jsonmysql"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.code256.jsonmysql.RegActivity"
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>
Below is the a PDO php class that will validate all our POST and GET request so that they return well formatted JSON arrays and avoid SQL injection and Cross Site Scripting.
<?php
$username = "root";
$password = "";
$host = "localhost";
$dbname = "safari256";
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
try
{
$db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
}
catch(PDOException $ex)
{
die("Failed to connect to the database: " . $ex->getMessage());
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
{
function undo_magic_quotes_gpc(&$array)
{
foreach($array as &$value)
{
if(is_array($value))
{
undo_magic_quotes_gpc($value);
}
else
{
$value = stripslashes($value);
}
}
}
undo_magic_quotes_gpc($_POST);
undo_magic_quotes_gpc($_GET);
undo_magic_quotes_gpc($_COOKIE);
}
header('Content-Type: text/html; charset=utf-8');
session_start();
?>
Below is a php class to perform the basic MYSQL functions i.e CREATE,UPDATE,DELETE and COUNT the number of rows affected by a query
<?php
class DB_CONNECT {
function __construct() {
$this->connect();
}
function __destruct() {
$this->close();
}
function connect() {
require_once __DIR__ . '/db_config.php';
$con = mysql_connect(DB_SERVER, DB_USER, DB_PASSWORD) or die(mysql_error());
$db = mysql_select_db(DB_DATABASE) or die(mysql_error()) or die(mysql_error());
return $con;
}
function close() {
mysql_close();
}
}
?>
Below is the a php code that use create a new user and insert them into our database
<?php
$response = array();
if (isset($_POST['fname']) && isset($_POST['lname']) && isset($_POST['username']) && isset($_POST['password']) && isset($_POST['location']) && isset($_POST['contact'])) {
$fname = $_POST['fname'];
$lname = $_POST['lname'];
$username = $_POST['username'];
$password = $_POST['password'];
$location = $_POST['location'];
$contact = $_POST['contact'];
require_once __DIR__ . '/db_connect.php';
$db = new DB_CONNECT();
$result = mysql_query("INSERT INTO users( username, password,first_name, last_name, location, contact) VALUES( '$username','$password','$fname', '$lname','$location','$contact')");
if ($result) {
$response["success"] = 1;
$response["message"] = "User successfully Registered.";
echo json_encode($response);
} else {
$response["success"] = 0;
$response["message"] = "Oops! An error occurred.";
echo json_encode($response);
}
} else {
$response["success"] = 0;
$response["message"] = "Required field(s) is missing";
echo json_encode($response);
}
?>
Use the "var" button to to wrap Variable or class names in <code> tags like this
.
Points of Interest
This source code only works if your are familiar with the three technologies i.e JAVA,PHP/MYSQL
Using the emulator is slow but saves alot of time trying to have the phone and Your local computer using the same ip address.With the emulator you only have to ensure that the URL to pick JSON string from your local machine has the same address as your ip address
History
Keep a running update of any changes or improvements you've made here.