เขียน Android app สื่อสารกับ MySQL database

สวัสดีครับเพื่อน ๆ พอดีตอนนี้ผมกำลังทำโปรเจคแอพพลิเคชันแอนดรอยน์เพื่อควบคุมแอร์ในบ้านผ่านอินเตอร์เน็ต วางแผนกับพี่ทำงานว่าเราต้องใช้ server 2 ตัว ตัวที่ 1 เก็บข้อมูลการใช้งานของผู้ใช้ และตัวที่ 2 ใช้เป็น server สำหรับผู้ใช้งานสื่อสารกับแอร์ โดยใช้ MQTT server พอเรามามองดูตัวที่ 1 server ที่เรามีจะเหมือน server ที่แทบทุกเว็ปไซน์ใช้กันนั่นคือมีการเก็บฐานข้อมูลโดยใช้ MySQL ดังนั้น วันนี้ผมจะมาเล่าวิธีการเขียนแอพพลิเคชันแอนดรอยเพื่อสื่อสารกับ MySQL database

จากการศึกษามาหลายเว็ปไซน์พบว่าหลายคนแนะนำคือการสื่อสารกับ MySQL ผ่าน PHP script วิธีการนี้รองรับการสื่อสารจากหลายช่องทาง ไม่ว่าจะเป็น Android app หรือไม่ก็ Website แต่ก็มีวิธีการอื่นใช้สำหรับสื่อสารกับ MySQL ได้โดยไม่ผ่าน PHP script นั่นคือ ใช้ JDBC library คลิ๊กเพื่อดูตัวอย่าง แต่มีหลายคนแนะนำไม่ให้ใช้ คลิ๊กเพื่อดูเหตุผลที่นี่ ดังนั้นวันนีผมจะขอเล่าเฉพาะวิธีที่ใช้กันอย่างแพร่หลายนั่นคือ สื่อสารกับ MySQL ผ่าน PHP script

แผนผังการสื่อสารกับ MySQL database

จากรูปข้างต้นเราพบว่าจริง ๆ แล้วแอนดรอยน์แอพสื่อสารกับ PHP เท่านั้น และ
PHP ถึงสื่อสารกับ MySQL ต่อไป โดย PHP ไฟล์จะถูกเก็บไว้บน server แต่ละไฟล์แตกต่างกันไปตามหน้าที่ เช่น อ่านข้อมูล เขียนข้อมูล และลบข้อมูลจาก MySQL database เป็นต้น และเพื่อความเข้าใจผมจะยกตัวอย่าง Android app สำหรับอ่านรายชื่อ เพิ่มรายชื่อ ตรวจสอบรายชื่อ และลบรายชื่อผู้ใช้งาน ทำให้เพื่อน ๆ เข้าใจได้แบบง่าย ๆ

เตรียมเครื่องมือ

  • โปรแกรม Android Studio ผมเชื่อว่าหลายคนที่อ่านบทความนี้ ต้องมีพื้นฐานการใช้งานแน่นอน
  • โปรแกรม Text Editor ผมเลือกใช้ Visual Studio Code เพราะมีตัวช่วยในการพิมพ์โค๊ดให้ถูกต้อง
  • Server และ MySQL database ในส่วนนี้สามารถใช้โปรแกรมจำลองคอมพิวเตอร์ให้เป็น Server ได้ ดูตัวอย่างได้จากที่นี่ หรือถ้าใครมี Website เป็นของตัวเองอยู่แล้วก็สามารถใช้ Web Server ของตัวเองได้เลย สำหรับในที่นี่ผมเลือกใช้ Web Server ของผมเองเป็นตัวอย่างสำหรับสอนเพื่อน ๆ เพราะในการใช้งานผ่านอินเตอร์เน็ตเราก็ต้องอัพมันขึ้น Web Server อยู่ดี

สร้างฐานข้อมูล (database)

ให้เราเข้าไปที่ phpMyAdmin เพื่อสร้างตาราง สำหรับเก็บข้อมูลบน database ในที่นี้ผมสร้าง database ใหม่ขึ้นมาชื่อ test และตารางชื่อว่า user_login_test และมีจำนวน 3 คอลัมป์มีชื่อว่า id name และ password ตามลำดับ ดังตัวอย่างข้างล่าง

โครงสร้างตารางบน database

จากนั้นก็ลองเพิ่มข้อมูลลงไปในตารางโดยกดที่ Insert พอเพิ่มเสร็จให้คลิ๊กที่ Browse เพื่อดูข้อมูลในตาราง

ตัวอย่างข้อมูลในตาราง

PHP scripts ที่เกี่ยวข้อง

PHP script อ่านรายชื่อผู้ใช้งาน

<?php
$servername = "localhost"; //ใช้ localhost กรณี server อยู่บน online
$username = "พิมพ์ที่นี่"; //username ของ DirectAdmin/phpMyAdmin
$password = "พิมพ์ที่นี่"; //password ของ DirectAdmin/phpMyAdmin
$dbname = "test"; //ชื่อ database
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT id, name, password FROM user_login_test"; //"SELECT ชื่อคอลัมป์ 1, ชื่อคอลัมป์ 2, ชื่อคอลัมป์ 3 FROM ชื่อตาราง"
$result = $conn->query($sql);
$myArray = array();
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
array_push($myArray, $row); //Add object to array
}
}
$json_array = json_encode($myArray); //Convert array to JSON
echo $json_array;
$conn->close(); //ปิดการเชื่อมต่อ
?>

อัพโหลดไฟล์ php ขึ้นไปยัง Server (ก่อนอัพโหลดอย่าลืมแก้ไข $servername $username และ $password ให้ตรงกับ MySQL database ของเพื่อน ๆ) โดยไฟล์นี้ต้องถูกวางเอาไว้ในโฟนเดอร์ public html จากรูปผู้เขียนสร้าง my-test ขึ้นมาเพื่อเก็บไฟล์ php ทั้งหมดเกี่ยวกับบทความนี้

ตำแหน่งจัดเก็บไฟล์ php บน Web Server ต้องอยู่ใน public html เท่านั้น!

ทดสอบอ่านข้อมูลผ่าน Web browser โดยเข้าไปที่ URL: http://www.somsakelect.com/my-test/get-user-table-json.php จะได้ข้อมูลที่ตอบกลับเป็น JSON array ซึ่งก็คือข้อมูลจากตารางที่เราสร้างเอาไว้บน MySQL database นั่นเอง

ข้อมูลที่ตอบกลับจาก Web server

PHP script เพิ่มรายชื่อผู้ใช้งาน

<?php
//Thank: https://www.w3schools.com/php/php_mysql_insert.asp
$servername = "localhost"; //ใช้ localhost กรณี server อยู่บน online
$username = "พิมพ์ที่นี่"; //username ของ DirectAdmin/phpMyAdmin
$password = "พิมพ์ที่นี่"; //password ของ DirectAdmin/phpMyAdmin
$dbname = "test"; //ชื่อ database
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
//Get data from user
$name = $_POST['name'];
$pass = $_POST['password'];
if(empty($name) || empty($pass)){
die("Please enter name and password!");
}
//Add data to table
$sql = "INSERT INTO user_login_test (id, name, password) VALUES (NULL, '$name', '$pass')";
//Check result
if ($conn->query($sql) === TRUE) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close();
?>

เมื่อเราอ่านดูโค๊ดแล้วมีส่วนที่สำคัญคือ การรับข้อมูลจากภายนอกเกี่ยวกับ name และ password นั่นคือ $name = $_POST[‘name’]; และ $pass = $_POST[‘password’]; ซึงผมจะกล่าวถึงโค๊ด Android ที่เกี่ยวข้องในภายหลัง

PHP script ตรวจสอบรายชื่อผู้ใช้งาน

<?php
//Thank SQL: https://www.w3schools.com/sql/sql_where.asp
$servername = "localhost"; //ใช้ localhost กรณี server อยู่บน online
$username = "พิมพ์ที่นี่"; //username ของ DirectAdmin/phpMyAdmin
$password = "พิมพ์ที่นี่"; //password ของ DirectAdmin/phpMyAdmin
$dbname = "test"; //ชื่อ database
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
//Get data from user
$name = $_POST['name'];
$pass = $_POST['password'];
//Filter on DB
$sql = "SELECT name, password FROM user_login_test WHERE (name='$name' && password='$pass')";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
echo "Login successfully";
}else{
echo "name or password invalid!";
}
$conn->close();
?>

PHP script นี้จะถูกใช้เหมือนกับเวลาผู้ใช้งานลงชื่อเข้าสู่ระบบ ดังนั้น ต้องมีการตรวจสอบว่า name และ password ตรงกับข้อมูลในตารางในฐานข้อมูลหรือไม่

PHP script ลบรายชื่อผู้ใช้งาน

<?php
//Thank SQL: https://www.w3schools.com/sql/sql_delete.asp
// https://www.tutorialspoint.com/mysqli/mysqli_delete_query.htm
$servername = "localhost"; //ใช้ localhost กรณี server อยู่บน online
$username = "พิมพ์ที่นี่"; //username ของ DirectAdmin
$password = "พิมพ์ที่นี่"; //password ของ DirectAdmin
$dbname = "test"; //ชื่อ database
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
//Get data from app
$userId = $_POST['userId'];
//Filter on DB
$sql = "DELETE FROM user_login_test WHERE id='$userId'";
//Check result
if ($conn->query($sql) === TRUE) {
echo "Delete successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close();
?>

PHP script นี้จะรับค่า id ของผู้ใช้งานที่ต้องการจะลบจาก Android app จากนั้นถึงใช้ภาษา SQL เพิ่มลบข้อมูลในตารางในฐานข้อมูล

Android app

สำหรับการสื่อสารระหว่าง android app กับ PHP script จะเชื่อมต่อจาก URL ที่เก็บ script เอาไว้ โดยเราสามารถส่งค่าหรือไม่ส่งค่า parameter อื่น ๆ เข้าไปก็ได้ เพื่อความง่ายในการเขียนโปรแกรมผมได้เลือกใช้ไลบารี่ ion ซึ่งถูกพัฒนาโดยนักพัฒนาอิสระ แต่มีความน่าเชื่อถือได้ ตามคำแนะนำจากหนังสือพัฒนา Mobile App ฉบับ Pro Android ดังนั้น เรามาเริ่มต้นจากการเพิ่มไลบารี่ ion ลงบนโปรเจค (ผมขอข้ามการสร้างโปรเจคออกไป เพราะถือว่าเพื่อน ๆ มีพื้นฐานแล้ว) โดยเพิ่มลงไปใน build.gradle (Module: app) สำหรับเวอร์ชันล่าสุดสามารถตรวจสอบได้จากที่นี่

dependencies {
...
implementation 'com.koushikdutta.ion:ion:2.2.1'
}
dependencies { ... implementation 'com.koushikdutta.ion:ion:2.2.1' }
dependencies {
    ...
    implementation 'com.koushikdutta.ion:ion:2.2.1'
}

และอย่างลืมเพิ่ม <uses-permission android:name=”android.permission.INTERNET”/> ในไฟล์ AndroidManifest.xml ด้วย

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.somsakelect.sqltesting">
<uses-permission android:name="android.permission.INTERNET"/>
<application
...
</manifest>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.somsakelect.sqltesting"> <uses-permission android:name="android.permission.INTERNET"/> <application ... </manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.somsakelect.sqltesting">

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

    <application
        ...
</manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="18sp"
android:gravity="end"
android:layout_margin="8dp"
android:text="Name: "
app:layout_constraintBottom_toBottomOf="@+id/name_enter"
app:layout_constraintEnd_toStartOf="@+id/name_enter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/name_enter"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
android:hint="Enter name"
android:inputType="text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/pass"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="18sp"
android:gravity="end"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="Password: "
app:layout_constraintBottom_toBottomOf="@+id/pass_enter"
app:layout_constraintEnd_toStartOf="@+id/pass_enter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/pass_enter" />
<EditText
android:id="@+id/pass_enter"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
android:hint="Enter password"
android:inputType="text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/name_enter" />
<Button
android:id="@+id/login_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="Login"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/add_btn"
app:layout_constraintTop_toTopOf="@+id/add_btn" />
<Button
android:id="@+id/list_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="List"
app:layout_constraintEnd_toStartOf="@+id/add_btn"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/pass_enter" />
<Button
android:id="@+id/add_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add"
app:layout_constraintEnd_toStartOf="@+id/login_btn"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/list_btn"
app:layout_constraintTop_toTopOf="@+id/list_btn" />
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_btn" />
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top" />
</android.support.constraint.ConstraintLayout>

MainActivity.java

package com.somsakelect.sqltesting;
import android.app.ProgressDialog;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.Ion;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
//Input enter
EditText nameEnter, passEnter;
//List
private ArrayList<String> itemsID;
private ArrayList<String> items;
private ArrayAdapter<String> adapter;
//URL
private static final String USER_LIST_URL = "http://somsakelect.com/my-test/get-user-table-json.php";
private static final String ADD_USER_URL = "http://somsakelect.com/my-test/add-user.php";
private static final String USER_LOGIN_URL = "http://somsakelect.com/my-test/user-login.php";
private static final String DELETE_USER_URL = "http://somsakelect.com/my-test/delete-user.php";
//Other
private ProgressDialog dialog;
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nameEnter = findViewById(R.id.name_enter);
passEnter = findViewById(R.id.pass_enter);
ListView listView = findViewById(R.id.list_view);
items = new ArrayList<>();
itemsID = new ArrayList<>();
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, items);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Get id from list and delete user from database
deleteUser(itemsID.get(position));
}
});
findViewById(R.id.login_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Set url to php script for user login
userLoginOrAdd(USER_LOGIN_URL);
}
});
//Get current user list
findViewById(R.id.list_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showUserList();
}
});
//Add user
findViewById(R.id.add_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Set url to php script for adding user
userLoginOrAdd(ADD_USER_URL);
}
});
}
private void showUserList(){
//Show progress
showProgress();
//Connect and get data
Ion.with(this)
.load(USER_LIST_URL) //URL to PHP script for getting data
.asJsonArray()
.setCallback(new FutureCallback<JsonArray>() {
@Override
public void onCompleted(Exception e, JsonArray result) {
dialog.dismiss();
Log.w(TAG, "Error: "+e);
Log.w(TAG, "Result: "+result);
if (result!=null){
//clear previously result on item
items.clear();
itemsID.clear();
//Loop add item
for (int i=0; i<result.size(); i++){
JsonObject object = (JsonObject)result.get(i);
String id = object.get("id").getAsString();
String name = object.get("name").getAsString();
String pass = object.get("password").getAsString();
//Set detail on item
String r = "id = "+id+" name = "+name+" password = "+pass;
Log.w(TAG, r);
//Add item
items.add(r);
//Save id
itemsID.add(id);
}
//Update item on showing
adapter.notifyDataSetChanged();
//Check list
if (result.size()<1){
Toast.makeText(MainActivity.this,
"Not found data!", Toast.LENGTH_LONG).show();
}
}else {
//Show error
Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show();
}
}
});
}
private void userLoginOrAdd(@NonNull final String url){
//Get data
String name = nameEnter.getText().toString();
String pass = passEnter.getText().toString();
//Check data
if (name.isEmpty() || pass.isEmpty()){
Toast.makeText(MainActivity.this, "Please enter name and password!", Toast.LENGTH_LONG).show();
}else {
Ion.with(MainActivity.this)
.load(url)
.setBodyParameter("name", name)
.setBodyParameter("password", pass)
.asString()
.setCallback(new FutureCallback<String>() {
@Override
public void onCompleted(Exception e, String result) {
Log.e(TAG, "Network error: "+ e);
Log.w(TAG, "Result: "+result);
if(result!=null){
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
//Update list
if (url.equals(ADD_USER_URL)){ showUserList(); }
}else {
Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show();
}
}
});
}
}
private void deleteUser(String id){
Log.w(TAG, "Delete ID: "+id);
Ion.with(MainActivity.this)
.load(DELETE_USER_URL)
.setBodyParameter("userId", id)
.asString()
.setCallback(new FutureCallback<String>() {
@Override
public void onCompleted(Exception e, String result) {
Log.e(TAG, "Network error: "+ e);
Log.w(TAG, "Result: "+result);
if(result!=null){
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
//Update list
showUserList();
}else {
Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show();
}
}
});
}
private void showProgress(){
dialog = new ProgressDialog(MainActivity.this);
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setMessage("Progressing...");
dialog.setIndeterminate(true);
dialog.show();
}
}

จากโค๊ดเรามาทำความเข้าใจแต่ละส่วนดังนี้

URL สำหรับสื่อสารกับ PHP script

private static final String USER_LIST_URL = "http://somsakelect.com/my-test/get-user-table-json.php";
private static final String ADD_USER_URL = "http://somsakelect.com/my-test/add-user.php";
private static final String USER_LOGIN_URL = "http://somsakelect.com/my-test/user-login.php";
private static final String DELETE_USER_URL = "http://somsakelect.com/my-test/delete-user.php";
private static final String USER_LIST_URL = "http://somsakelect.com/my-test/get-user-table-json.php"; private static final String ADD_USER_URL = "http://somsakelect.com/my-test/add-user.php"; private static final String USER_LOGIN_URL = "http://somsakelect.com/my-test/user-login.php"; private static final String DELETE_USER_URL = "http://somsakelect.com/my-test/delete-user.php";
private static final String USER_LIST_URL = "http://somsakelect.com/my-test/get-user-table-json.php";
    private static final String ADD_USER_URL = "http://somsakelect.com/my-test/add-user.php";
    private static final String USER_LOGIN_URL = "http://somsakelect.com/my-test/user-login.php";
    private static final String DELETE_USER_URL = "http://somsakelect.com/my-test/delete-user.php";

ฟังก์ชันสำหรับอ่านรายชื่อผู้ใช้งาน

private void showUserList(){
//Show progress
showProgress();
//Connect and get data
Ion.with(this)
.load(USER_LIST_URL) //URL to PHP script for getting data
.asJsonArray()
.setCallback(new FutureCallback<JsonArray>() {
@Override
public void onCompleted(Exception e, JsonArray result) {
dialog.dismiss();
Log.w(TAG, "Error: "+e);
Log.w(TAG, "Result: "+result);
if (result!=null){
//clear previously result on item
items.clear();
itemsID.clear();
//Loop add item
for (int i=0; i<result.size(); i++){
JsonObject object = (JsonObject)result.get(i);
String id = object.get("id").getAsString();
String name = object.get("name").getAsString();
String pass = object.get("password").getAsString();
//Set detail on item
String r = "id = "+id+" name = "+name+" password = "+pass;
Log.w(TAG, r);
//Add item
items.add(r);
//Save id
itemsID.add(id);
}
//Update item on showing
adapter.notifyDataSetChanged();
//Check list
if (result.size()<1){
Toast.makeText(MainActivity.this,
"Not found data!", Toast.LENGTH_LONG).show();
}
}else {
//Show error
Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show();
}
}
});
}
private void showUserList(){ //Show progress showProgress(); //Connect and get data Ion.with(this) .load(USER_LIST_URL) //URL to PHP script for getting data .asJsonArray() .setCallback(new FutureCallback<JsonArray>() { @Override public void onCompleted(Exception e, JsonArray result) { dialog.dismiss(); Log.w(TAG, "Error: "+e); Log.w(TAG, "Result: "+result); if (result!=null){ //clear previously result on item items.clear(); itemsID.clear(); //Loop add item for (int i=0; i<result.size(); i++){ JsonObject object = (JsonObject)result.get(i); String id = object.get("id").getAsString(); String name = object.get("name").getAsString(); String pass = object.get("password").getAsString(); //Set detail on item String r = "id = "+id+" name = "+name+" password = "+pass; Log.w(TAG, r); //Add item items.add(r); //Save id itemsID.add(id); } //Update item on showing adapter.notifyDataSetChanged(); //Check list if (result.size()<1){ Toast.makeText(MainActivity.this, "Not found data!", Toast.LENGTH_LONG).show(); } }else { //Show error Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show(); } } }); }
 private void showUserList(){
        //Show progress
        showProgress();
        //Connect and get data
        Ion.with(this)
                .load(USER_LIST_URL) //URL to PHP script for getting data
                .asJsonArray()
                .setCallback(new FutureCallback<JsonArray>() {
                    @Override
                    public void onCompleted(Exception e, JsonArray result) {
                        dialog.dismiss();
                        Log.w(TAG, "Error: "+e);
                        Log.w(TAG, "Result: "+result);
                        if (result!=null){
                            //clear previously result on item
                            items.clear();
                            itemsID.clear();
                            //Loop add item
                            for (int i=0; i<result.size(); i++){
                                JsonObject object = (JsonObject)result.get(i);
                                String id = object.get("id").getAsString();
                                String name = object.get("name").getAsString();
                                String pass = object.get("password").getAsString();
                                //Set detail on item
                                String r = "id = "+id+" name = "+name+" password = "+pass;
                                Log.w(TAG, r);
                                //Add item
                                items.add(r);
                                //Save id
                                itemsID.add(id);
                            }
                            //Update item on showing
                            adapter.notifyDataSetChanged();
                            //Check list
                            if (result.size()<1){
                                Toast.makeText(MainActivity.this,
                                        "Not found data!", Toast.LENGTH_LONG).show();
                            }
                        }else {
                            //Show error
                            Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show();
                        }
                    }
                });
    }

จากฟังก์ชันมีส่วนที่สำคัญคือ การอ่านค่าจาก JSON object ซึ่งอยู่ใน JSON array เช่น String id = object.get(“id”).getAsString(); โดยที่ “id” ก็คือชื่อคอลัมป์ในตารางที่ถูกเก็บไว้ในฐานข้อมูลนั่นเอง ดังนั้น ถ้าเพื่อน ๆ มีการตั้งชื่อคอลัมป์ที่ต่างออกไปสามารถแก้ไขได้ที่นี่

ฟังก์ชันสำหรับเพิ่มหรือตรวจสอบรายชื่อผู้ใช้งาน

private void userLoginOrAdd(@NonNull final String url){
//Get data
String name = nameEnter.getText().toString();
String pass = passEnter.getText().toString();
//Check data
if (name.isEmpty() || pass.isEmpty()){
Toast.makeText(MainActivity.this, "Please enter name and password!", Toast.LENGTH_LONG).show();
}else {
Ion.with(MainActivity.this)
.load(url)
.setBodyParameter("name", name)
.setBodyParameter("password", pass)
.asString()
.setCallback(new FutureCallback<String>() {
@Override
public void onCompleted(Exception e, String result) {
Log.e(TAG, "Network error: "+ e);
Log.w(TAG, "Result: "+result);
if(result!=null){
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
//Update list
if (url.equals(ADD_USER_URL)){ showUserList(); }
}else {
Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show();
}
}
});
}
}
private void userLoginOrAdd(@NonNull final String url){ //Get data String name = nameEnter.getText().toString(); String pass = passEnter.getText().toString(); //Check data if (name.isEmpty() || pass.isEmpty()){ Toast.makeText(MainActivity.this, "Please enter name and password!", Toast.LENGTH_LONG).show(); }else { Ion.with(MainActivity.this) .load(url) .setBodyParameter("name", name) .setBodyParameter("password", pass) .asString() .setCallback(new FutureCallback<String>() { @Override public void onCompleted(Exception e, String result) { Log.e(TAG, "Network error: "+ e); Log.w(TAG, "Result: "+result); if(result!=null){ Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show(); //Update list if (url.equals(ADD_USER_URL)){ showUserList(); } }else { Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show(); } } }); } }
private void userLoginOrAdd(@NonNull final String url){
        //Get data
        String name = nameEnter.getText().toString();
        String pass = passEnter.getText().toString();
        //Check data
        if (name.isEmpty() || pass.isEmpty()){
            Toast.makeText(MainActivity.this, "Please enter name and password!", Toast.LENGTH_LONG).show();
        }else {
            Ion.with(MainActivity.this)
                    .load(url)
                    .setBodyParameter("name", name)
                    .setBodyParameter("password", pass)
                    .asString()
                    .setCallback(new FutureCallback<String>() {
                        @Override
                        public void onCompleted(Exception e, String result) {
                            Log.e(TAG, "Network error: "+ e);
                            Log.w(TAG, "Result: "+result);
                            if(result!=null){
                                Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
                                //Update list
                                if (url.equals(ADD_USER_URL)){ showUserList(); }
                            }else {
                                Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show();
                            }
                        }
                    });
        }
    }

จากฟังก์ชันมีส่วนที่สำคัญคือ การส่งค่า parameter เข้าไปใน PHP script เช่น .setBodyParameter(“name”, name) โดยที่ “name” ต้องตรงกับ $_POST[‘name’] ซึ่งถูกเขียนไว้ใน PHP script จึงจะทำให้ PHP script อ่านค่าได้ถูกต้อง

ฟังก์ชันสำหรับลบรายชื่อผู้ใช้งาน

private void deleteUser(String id){
Log.w(TAG, "Delete ID: "+id);
Ion.with(MainActivity.this)
.load(DELETE_USER_URL)
.setBodyParameter("userId", id)
.asString()
.setCallback(new FutureCallback<String>() {
@Override
public void onCompleted(Exception e, String result) {
Log.e(TAG, "Network error: "+ e);
Log.w(TAG, "Result: "+result);
if(result!=null){
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
//Update list
showUserList();
}else {
Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show();
}
}
});
}
private void deleteUser(String id){ Log.w(TAG, "Delete ID: "+id); Ion.with(MainActivity.this) .load(DELETE_USER_URL) .setBodyParameter("userId", id) .asString() .setCallback(new FutureCallback<String>() { @Override public void onCompleted(Exception e, String result) { Log.e(TAG, "Network error: "+ e); Log.w(TAG, "Result: "+result); if(result!=null){ Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show(); //Update list showUserList(); }else { Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show(); } } }); }
    private void deleteUser(String id){
        Log.w(TAG, "Delete ID: "+id);
        Ion.with(MainActivity.this)
                .load(DELETE_USER_URL)
                .setBodyParameter("userId", id)
                .asString()
                .setCallback(new FutureCallback<String>() {
                    @Override
                    public void onCompleted(Exception e, String result) {
                        Log.e(TAG, "Network error: "+ e);
                        Log.w(TAG, "Result: "+result);
                        if(result!=null){
                            Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
                            //Update list
                            showUserList();
                        }else {
                            Toast.makeText(MainActivity.this, "Error: "+e, Toast.LENGTH_LONG).show();
                        }
                    }
                });
    }

จากโค๊ดในฟังก์ชันมีการส่งค่า parameter นั่นคือ id ของผู้ใช้งาน ที่ต้องการลบไปยัง PHP script โดยบรรทัด .setBodyParameter(“userId”, id)

การทดสอบ Android app

ก็จบไปแล้วนะครับสำหรับบทความนี้ ถ้าเพื่อน ๆ สงสัยอะไรสามารถ comment ได้เลยนะครับ ผมแนะนำแหล่งความรู้ในการศึกษาเกี่ยวกับ PHP และ SQL ได้จากเว็ปไซน์ต่อไปนี้

ขอบคุณสำหรับการอ่านมาจนถึงตรงนี้ครับ ไว้ติดตามบทความหน้าครับ

Share this:

3 Comments on “เขียน Android app สื่อสารกับ MySQL database

Leave a Reply

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *