How to connect android php mysql – generic asynctask

[updated on September 27, 2017]

One question: Getting Tired of Recreating AsyncTask Classes All Over Again?

Before we get started, let me say welcome to KosalGeek. I am glad you came!

OK, I get it. You came because you are like me; you are tired of creating tons of classes (mostly private classes) of the AsyncTask class all over an over again.

If you already know the basic and want to grab the code, you can jump to Reusable Generic Classes.

(You can watch video at about How to Connect Android with PHP, MySQL on YouTube, or you just watch it down below)

MOTIVATION

If you don’t know what I am talking, let me explain a bit. Basically, in Android when you want to connect to an external source, you use AsyncTask. Since Android 3.0 API 11 (Honeycombs), you are no longer allowed to use the main thread to do a long process; instead, you need the AsyncTask to work in a background thread. You can use Handler but it is a different approach which is not covered in this page.

Here, we use it to connect to a web service to retrieve data in a JSON or XML format (the latter is not common) from a database server (e.g. MySQL), and to send data (HttpPost, HttpGet) to a web service. For example, if you want to let your client log in from your Android app, then there are data sending back and forth. See the illustration below of how it works:

kosalgeek asynctask diagram

For a Website, this would look very simple because it is a nature of a Web. You do not need to do anything to make it work. However, for a mobile app, not just for only Android app, this process would make you a half day. Why? A request call from a client and a response back can be one private class extending AsyncTask. You might need to make another AsyncTask class to read the data back later on. Let me write some codes to show you. In this tutorial, I use a Login example from Android to PHP to MySQL. It is not limited to PHP and MySQL, you can use your favorite language and database server.

Let’s Create a Generic Class

Why? DRY (Don’t Repeat Yourself). We don’t want to waste our time to recreate 100 of private classes of AsyncTask. We are going to create a reusable generic class.

But before we create that class, let’s start from the basic. I am gonna show the whole process from creating MySQL database, PHP, to Android.

Create a Database in MySQL

First, let’s create a database db_client and a table tbl_client with 4 attributes (id, name, username, password).

CREATE DATABASE db_client;
USE db_client;

CREATE TABLE tbl_client
(id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
name VARCHAR(50) NOT NULL,
username VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL
);
INSERT INTO tbl_client(name, username, password) 
VALUES('Kosal Geek', 'kosalgeek', 'xyz'); 
INSERT INTO tbl_client(name, username, password) 
VALUES('abc', 'abc', '123'); 
INSERT INTO tbl_client(name, username, password) 
VALUES('Test', 'test', 'test');

Create a Login Page in PHP

connection.php

Below is the connection file:

<?php
$servername = "localhost"; //replace it with your database server name
$username = "root";  //replace it with your database username
$password = "";  //replace it with your database password
$dbname = "db_client";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}
?>

login.php

Make sure you place the login.php page in the same folder of connection.php. In this case, I place these 2 files in a folder client:

<?PHP 
    include_once("connection.php"); 
    if( isset($_POST['txtUsername']) && isset($_POST['txtPassword']) ) { 
        $username = $_POST['txtUsername'];
        $password = $_POST['txtPassword'];
        
        $query = "SELECT username, password FROM tbl_client ". 
        " WHERE username = '$username' AND password = '$password'"; 
        
        $result = mysqli_query($conn, $query);
        
        if($result->num_rows > 0){
            if(isset($_POST['mobile']) && $_POST['mobile'] == "android"){ 
                echo "success"; 
                exit; 
            } 
            header("location: index.php"); //replace index.php with your url
        } else{ 
            echo "Login Failed <br/>"; 
        } 
    } 
?>
<html>
<head><title>Login|KosalGeek</title></head>
    <body>
        <h1>Login Example|<a href=”http://www.kosalgeek.com”>KosalGeek</a></h1>
        <form action="<?PHP $_PHP_SELF ?>" method="post">
            Username <input type="text" name="txtUsername" value="" /><br/>
            Password <input type="password" name="txtPassword" value="" /><br/>
            <input type="submit" name="btnSubmit" value="Login"/>
        </form>
    </body>
</html>
kosalgeek image
Screenshot of login.php Page

Create a Project in Android Studio

Please note that I use Android Studio 1.3.2 (Updated September 2015) which uses AppCompactActivity. Make sure you added the Gradle below in your dependencies.

compile 'com.android.support:appcompat-v7:22.2.1'

XML for User Interface

activity_login.xml

<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: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=".LoginActivity"
android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Username"
        android:id="@+id/textView2" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textEmailAddress"
        android:ems="10"
        android:id="@+id/etUsername" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Password"
        android:id="@+id/textView" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword"
        android:ems="10"
        android:id="@+id/etPassword" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Login"
        android:id="@+id/btnLogin" />
</LinearLayout>

The look of the layout should be like this:

kosalgeek image 2

 

REUSABLE GENERIC CLASSES

[Updated on September 27, 2017] Because I have changed the code many times to fix bugs and to support newer Android API, I decided not to include the source code of this library in here. Instead, you can always download the latest version from here, the my kosalgeek github. After you download the GenAsync.jar, you can include it in your library to use it.

Test The Codes

LoginActivity.java

Let’s test our classes with a login page. But make sure you create the LoginActivity inside the same package of the above classes.

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import java.util.HashMap;


public class LoginActivity extends AppCompatActivity implements AsyncResponse {

    EditText etUsername, etPassword;
    Button btnLogin;

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

        etUsername = (EditText)findViewById(R.id.etUsername);
        etPassword = (EditText)findViewById(R.id.etPassword);
        btnLogin = (Button)findViewById(R.id.btnLogin);

        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                HashMap postData = new HashMap();
                postData.put("btnLogin", "Login");
                postData.put("mobile", "android");
                postData.put("txtUsername", etUsername.getText().toString());
                postData.put("txtPassword", etPassword.getText().toString() );

                PostResponseAsyncTask loginTask = 
                        new PostResponseAsyncTask(LoginActivity.this, postData, 
                                                    LoginActivity.this);
                loginTask.execute("http://10.0.3.2/client/login.php");
            }
        });
    }

    @Override
    public void processFinish(String output) {
        if(output.equals("success")){
            Toast.makeText(this, "Login Successfully", 
                    Toast.LENGTH_LONG).show();
        }
    }
}

Internet Permission in Android Manifest

As you know, in order to make your app able to connect to the Web, not strictly to the Internet, you must add the Internet permission in the AndroidManifest.xml. You can locate your AndroidManifest.xml in app/manifest folder. Below is the Internet permission.

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

And your whole codes of AndroidManifest.xml should look like this:

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

    <uses-permission android:name="android.permission.INTERNET" />
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".LoginActivity"
            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>

That’s it. Now you can reuse the code above in your 1000+ projects without recreating the AsyncTask all over again.

Below is the detailed documentation of the classes.

DOCUMENTATION

Read Data

public class ReadDataActivity extends AppCompatActivity implements AsyncResponse {

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

        PostResponseAsyncTask readData = new PostResponseAsyncTask(ReadDataActivity.this, 
                                                   ReadDataActivity.this);
        readData.execute("http://yoursite.com/readdata.php");
    }

    @Override
    public void processFinish(String output) {
        //you can get 'output' from here.
    }
}

POST and Get Result

public class PostDataActivity extends AppCompatActivity implements AsyncResponse {

    EditText etUsername, etPassword;
    Button btnLogin;

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

        HashMap postData = new HashMap();
        postData.put("key1", "value1");
        postData.put("key2", "value2");
        
        //You pass postData as the 2nd argument of the constructor
        PostResponseAsyncTask loginTask = 
            new PostResponseAsyncTask(PostDataActivity.this, postData, PostDataActivity.this);
        loginTask.execute("http://yoursite.com/post.php");
    }

    @Override
    public void processFinish(String output) {
        //you can get 'output' from here
    }

}

Class PostResponseAsyncTask

Constuctor

PostResponseAsyncTask(AsyncResponse delegate)

public PostResponseAsyncTask(Context context, AsyncResponse delegate)

At least, you have to call this constructor and pass in an argument of the AsyncResponse object. To pass in the argument, usually you have your activity class implement the AsyncResponse. This class is used to get data back from response. Because it is async-ed, you can get the data through the AsyncResponse’s method called processFinish(string output). In the method, you get the data via the ‘output’ String variable.

PostResponseAsyncTask(AsyncResponse delegate, HashMap<String, String> postData)

public PostResponseAsyncTask(
        Context context, 
        HashMap<String, String> postData,
        AsyncResponse delegate
)

This constructor is used for sending POST data into a web server. This constructor can get a second argument as HashMap<String, String>.

 

Additional Constructors & Methods

Please refer to the KosalGeek Github.

DOWNLOAD SOURCE CODE

DOWNLOAD

 

Written By Oum Saokosal

 

Photo Credit:

Samsung Galaxy S4 – dual view by Kārlis Dambrāns / CC BY

Comments

comments