How to Connect Android with PHP, MySQL - Generic AsyncTask

How to Connect Android with PHP, MySQL One question: Getting Tired of Recreating AsyncTask Classes All Over Again? Before we...


How to Connect Android with PHP, MySQL

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:

Image of Android Request/Response to Web Service by kosalgeek.com


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>

Image Login PHP page by kosalgeek.com
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:

Image Login Page by kosalgeek.com

REUSABLE GENERIC CLASSES


OK. Here come the main part of this blog. There are two classes. First is the generic class and I called it PostResponseAsyncTask because it can request using post and response in one class. Another one is the interface AsyncResponse that deals with the output from a background thread. Below is a complete code of these two classes.

AsyncResponse.java

public interface AsyncResponse {
    void processFinish(String output);
}

PostResponseAsyncTask.java

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

public class PostResponseAsyncTask extends AsyncTask<String, Void, String> {

    private ProgressDialog progressDialog;

    private AsyncResponse delegate;
    private Context context;
    private HashMap<String, String> postData = 
                new HashMap<String, String>();
    private String loadingMessage = "Loading...";


    //Constructor
    public PostResponseAsyncTask(AsyncResponse delegate){
        this.delegate = delegate;
        this.context = (Context)delegate;
    }

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

        this.delegate = delegate;
        this.context = (Context)delegate;
        this.postData = postData;
    }

    public PostResponseAsyncTask(AsyncResponse delegate, String loadingMessage){
        this.delegate = delegate;
        this.context = (Context)delegate;
        this.loadingMessage = loadingMessage;
    }

    public PostResponseAsyncTask(AsyncResponse delegate, 
                 HashMap<String, String> postData, String loadingMessage){

        this.delegate = delegate;
        this.context = (Context)delegate;
        this.postData = postData;
        this.loadingMessage = loadingMessage;
    }
    //End Constructor

    @Override
    protected void onPreExecute() {
        progressDialog = new ProgressDialog(context);
        progressDialog.setMessage(loadingMessage);
        progressDialog.show();
        super.onPreExecute();
    }//onPreExecute

    @Override
    protected String doInBackground(String... urls){

        String result = "";

        for(int i = 0; i <= 0; i++){

            result = invokePost(urls[i], postData);
        }

        return result;
    }//doInBackground

    private String invokePost(String requestURL, HashMap<String, 
                String> postDataParams) {              
        URL url;
        String response = "";
        try {
            url = new URL(requestURL);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);

            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {
                String line;
                BufferedReader br = new BufferedReader(new 
                        InputStreamReader(conn.getInputStream()));
                while ((line = br.readLine()) != null) {
                    response+=line;
                }
            }
            else {
                response="";

                Log.i("PostResponseAsyncTask", responseCode + "");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return response;
    }//invokePost

    private String getPostDataString(HashMap<String, String> params) 
                    throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;

        for(Map.Entry<String, String> entry : params.entrySet()){
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }//getPostDataString

    @Override
    protected void onPostExecute(String result) {

        if(progressDialog.isShowing()){
            progressDialog.dismiss();
        }

        result = result.trim();

        delegate.processFinish(result);
    }//onPostExecute

    //Setter and Getter
    public String getLoadingMessage() {
        return loadingMessage;
    }

    public void setLoadingMessage(String loadingMessage) {
        this.loadingMessage = loadingMessage;
    }

    public HashMap<String, String> getPostData() {
        return postData;
    }

    public void setPostData(HashMap<String, String> postData) {
        this.postData = postData;
    }

    public Context getContext() {
        return context;
    }

    public AsyncResponse getDelegate() {
        return delegate;
    }

    //End Setter & Getter
}

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);
                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(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(this, postData);
        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(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(
        AsyncResponse delegate, 
        HashMap<String, 
        String> postData)
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

public PostResponseAsyncTask(AsyncResponse delegate, String loadingMessage)

public PostResponseAsyncTask(AsyncResponse delegate, String loadingMessage)
While reading data from a web server, I set a default loading message "Loading...". But if you want to say something else, you can set a message as the 2rd argument of the constructor.

Below is another constructor that lets you set postData and loadingMessage together.

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

DOWNLOAD


You can download my complete source codes at github.com/kosalgeek/generic_asynctask.
In GitHub, I also created a JAR file to make your life even easier if you don't want to copy and paste the codes.

Written By Oum SaokosalKosalGeektop12review.com


Photo Credit:

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

COMMENTS

BLOGGER: 1
Loading...
Name

Android Java for Android
false
ltr
item
Android Programming Language Step by Step | KosalGeek: How to Connect Android with PHP, MySQL - Generic AsyncTask
How to Connect Android with PHP, MySQL - Generic AsyncTask
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzcROM2vugKGh9YrXznGOfClnz2rCP7TKzNxb5V6nddUX445P55OduscHnN8A1QKaO8LQp1u_J3Wm5vOYW6NJQfzjR7KqHzR5aJnWPxrxIjm9pFTNUMosFrXMeKPsaJbGoac5-a1KJEgQ/s320/How+to+Connect+Android+with+PHP+MySQL.jpg
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzcROM2vugKGh9YrXznGOfClnz2rCP7TKzNxb5V6nddUX445P55OduscHnN8A1QKaO8LQp1u_J3Wm5vOYW6NJQfzjR7KqHzR5aJnWPxrxIjm9pFTNUMosFrXMeKPsaJbGoac5-a1KJEgQ/s72-c/How+to+Connect+Android+with+PHP+MySQL.jpg
Android Programming Language Step by Step | KosalGeek
https://kosalgeek.blogspot.com/2015/09/how-to-connect-android-with-php-mysql.html
https://kosalgeek.blogspot.com/
http://kosalgeek.blogspot.com/
http://kosalgeek.blogspot.com/2015/09/how-to-connect-android-with-php-mysql.html
true
1541123312426289231
UTF-8
Not found any posts VIEW ALL Readmore Reply Cancel reply Delete By Home PAGES POSTS View All RECOMMENDED FOR YOU LABEL ARCHIVE SEARCH ALL POSTS Not found any post match with your request Back Home Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sun Mon Tue Wed Thu Fri Sat January February March April May June July August September October November December Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec just now 1 minute ago $$1$$ minutes ago 1 hour ago $$1$$ hours ago Yesterday $$1$$ days ago $$1$$ weeks ago more than 5 weeks ago Followers Follow THIS CONTENT IS PREMIUM Please share to unlock Copy All Code Select All Code All codes were copied to your clipboard Can not copy the codes / texts, please press [CTRL]+[C] (or CMD+C with Mac) to copy