บทเรียนเบื้องต้นสำหรับผู้พัฒนาแอพพลิเคชัน Android กับการใช้งาน ListView แสดงข้อมูลจาก Web Service รูปแบบ JSON มาใช้งานสำหรับผู้เริ่มต้น บน Android Studio
เราจะทดสอบโปรเจ็คนี้โดยการเขียนภาษา PHP ร่วมกับ MySQL เพื่อ Echo ค่าของ PHP ออกมาเป็น JSON ครับ ให้เตรียมฐานข้อมูลโดยใช้ SQL Command ต่อไปนี้
CREATE TABLE IF NOT EXISTS 'movie' ( 'id' int(10) NOT NULL, 'title' varchar(255) COLLATE utf8_bin DEFAULT NULL, 'image' text COLLATE utf8_bin, 'description' text COLLATE utf8_bin ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;
เป็น Table ที่ชื่อว่า “Movie” นั่นเองครับ ให้ใส่ข้อมูลลงไปสัก 2-3 Row ครับ
รูปแบบของ Web Service ที่เราจะใช้ คือ JSON ซึ่งก็ไม่ต่างจาก XML แบบเก่าๆ หรอกครับ ลองเปรียบเทียบรูปแบบดูจะเห็นว่า JSON จะเขียนเรียกเป็น Key ง่ายกว่าแค่นั้นเอง
ต่อมาเป็นคำสั่ง PHP สำหรับ Echo ค่าในตาราง MySQL ออกมาเป็น JSON ครับให้เขียนตามนี้
<?php $objConnect = mysql_connect("localhost","root",""); $objDB = mysql_select_db("moviestore"); mysql_query("SET NAMES UTF8"); $SQLstring = "SELECT * FROM movie ORDER BY id ASC "; $objQuery = mysql_query($SQLstring); $numRows = mysql_num_fields($objQuery); $resultArray = array(); while($obResult = mysql_fetch_array($objQuery)) { $arrCol = array(); for($i=0;$i<$numRows;$i++) { $arrCol[mysql_field_name($objQuery,$i)] = $obResult[$i]; } array_push($resultArray,$arrCol); } mysql_close($objConnect); header ('Content-type: text/html; charset=utf-8'); echo json_encode($resultArray); ?>
ให้ทดสอบโดยการอัพโหลด ไฟล์นี้ไปบน Host ของเราแล้วลองเรียกดูเราจะเห็นว่า มันแสดงผลเป็น Key Value แบบ JSON เรียบร้อย
หากใช้ Chrome ลอกโหลด Add-on ที่ชื่อ JSON View ดูครับ จะแสดงผลได้ดังภาพข้างบน
https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc
เปิด Android Studio ขึ้นมาครับ แล้วนำ ListView มาวางบน Layout
ให้เราสร้างไฟล์ Layout เพิ่มมาอีกไฟล์ชื่อว่า activity_colums.xml ครับ ไว้แสดงผลของ แถวที่จะปรากฏบน ListView หลังจากนั้นให้เปิดไฟล์ activity_main.xml ขึ้นมาใส่ code ดังนี้ครับ
<RelativeLayout 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=".MainActivity"> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content"> </ListView> </RelativeLayout>
ตามด้วยเปิดไฟล์ acivity_column.xml ขึ้นมาครับ ใส่ code นี้ลงไป
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/articleID" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="0.2" android:text="ID" android:textAppearance="?android:attr/textAppearanceSmall" android:textSize="20dp" /> <TextView android:id="@+id/articleTitle" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Name" android:textAppearance="?android:attr/textAppearanceSmall" android:textSize="20dp" /> </LinearLayout>
ซึ่งจะมีค่า ID ที่ใช้งานอยู่ 2 ตัวคือ articleID ไว้เก็บ ID จาก JSON และ articleTitle ไว้เก็บค่า Title จาก JSON เช่นกันครับ
ต่อมาไปที่ โฟลเดอร์ Manifest หาไฟล์ AndroidManifest.xml ครับให้เราเพิ่ม Permission ในการต่ออินเทอร์เน็ตลงไป
ใส่ลงไปตามภาพครับ ส่วนของ uses-permission
เปิดไฟล์ MainActivity.java ขึ้นมา เพิ่ม import ส่วน Header File ดังนี้
import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.os.StrictMode; import android.annotation.SuppressLint; import android.util.Log; import android.widget.ListView; import android.widget.SimpleAdapter;
เขียนคำสั่ง JSON กับ ListView เพิ่มเข้ามา ก่อนอื่นให้สร้างเมธอดฟังก์ชันมาใหม่ชื่อ getJSON();
public String getJSON(String url,List<NameValuePair> params) { StringBuilder str = new StringBuilder(); HttpClient client = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); try { httpPost.setEntity(new UrlEncodedFormEntity(params)); HttpResponse response = client.execute(httpPost); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { HttpEntity entity = response.getEntity(); InputStream content = entity.getContent(); BufferedReader reader_buffer = new BufferedReader (new InputStreamReader(content)); String line; while ((line = reader_buffer.readLine()) != null) { str.append(line); } } else { Log.e("Log", "Failed to download file.."); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return str.toString(); }
เป็นการเรียก entity ของ key value มาเก็บไว้ในตัวแปรสำหรับแสดงค่า โดยใช้ HTTP Request มาใช้เรียก API ของ Webservices ผ่าน status_code ที่เราทราบกันดีว่า 200 คือโอเค
เสร็จแล้วก็เขียนฟังก์ชันเพิ่ม ใน onCreate();
@SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); } final ListView listViewMovies = (ListView)findViewById(R.id.listView1); String url = "http://lovedesigner.net/feed/json"; List<NameValuePair> params = new ArrayList<NameValuePair>(); try { JSONArray data = new JSONArray(getJSON(url,params)); final ArrayList<HashMap<String, String>> MyArrList = new ArrayList<HashMap<String, String>>(); HashMap<String, String> map; for(int i = 0; i < data.length(); i++){ JSONObject c = data.getJSONObject(i); map = new HashMap<String, String>(); map.put("id", c.getString("id")); map.put("title", c.getString("title")); MyArrList.add(map); } SimpleAdapter simpleAdapterData; simpleAdapterData = new SimpleAdapter(MainActivity.this, MyArrList, R.layout.activity_column, new String[] {"id", "title"}, new int[] {R.id.articleID, R.id.articleTitle}); listViewMovies.setAdapter(simpleAdapterData); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
ภาพรวมของ Source code จะเป็นดังนี้ครับ
package com.daydev.webservices; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.os.StrictMode; import android.annotation.SuppressLint; import android.util.Log; import android.widget.ListView; import android.widget.SimpleAdapter; public class MainActivity extends ActionBarActivity { @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); } final ListView listViewMovies = (ListView)findViewById(R.id.listView1); String url = "http://lovedesigner.net/feed/json"; List<NameValuePair> params = new ArrayList<NameValuePair>(); try { JSONArray data = new JSONArray(getJSON(url,params)); final ArrayList<HashMap<String, String>> MyArrList = new ArrayList<HashMap<String, String>>(); HashMap<String, String> map; for(int i = 0; i < data.length(); i++){ JSONObject c = data.getJSONObject(i); map = new HashMap<String, String>(); map.put("id", c.getString("id")); map.put("title", c.getString("title")); MyArrList.add(map); } SimpleAdapter simpleAdapterData; simpleAdapterData = new SimpleAdapter(MainActivity.this, MyArrList, R.layout.activity_column, new String[] {"id", "title"}, new int[] {R.id.articleID, R.id.articleTitle}); listViewMovies.setAdapter(simpleAdapterData); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public String getJSON(String url,List<NameValuePair> params) { StringBuilder str = new StringBuilder(); HttpClient client = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); try { httpPost.setEntity(new UrlEncodedFormEntity(params)); HttpResponse response = client.execute(httpPost); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { HttpEntity entity = response.getEntity(); InputStream content = entity.getContent(); BufferedReader reader_buffer = new BufferedReader (new InputStreamReader(content)); String line; while ((line = reader_buffer.readLine()) != null) { str.append(line); } } else { Log.e("Log", "Failed to download file.."); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return str.toString(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
ทดสอบรันตัวโปรเจ็คของเราหน่อยดีกว่า
เรียบร้อย เราสามารถใช้ JSON array ร่วมกับ Intent Activity ให้ส่งค่าเมื่อกด ListView ได้ต่อไปนะครับ ลองทดสอบทำดูครับ
บทเรียน Web Services ก็คงจบแค่นี้
One Comment