เขียน 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 ขึ้นไปยัง 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 เพิ่มรายชื่อผู้ใช้งาน

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

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

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

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

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'
}

และอย่างลืมเพิ่ม <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>

activity_main.xml

MainActivity.java

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

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 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();
                            }
                        }
                    });
        }
    }

จากฟังก์ชันมีส่วนที่สำคัญคือ การส่งค่า 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();
                        }
                    }
                });
    }

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

การทดสอบ Android app

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

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

Share this:

Leave a Reply

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