Bài 51: Xử Lý JSON Trong Android | Advanced Programming

Trong bài này Tui sẽ hướng dẫn các bạn cách tương tác JSON trong Android, ở đây Tui sẽ hướng dẫn 2 cách tiếp cận:

1) Sử dụng sẵn Web Service của ai đó được viết dưới định dạng JSON

2) Tự xây dựng JSON bằng .net web service (Các bạn cần biết cách tạo cũng như cách sử dụng), bạn có thể dùng bất kỳ cái gì đó để viết ra JSON cũng được, không nhất thiết phải dùng .net web service. Ở đây Tui muốn đứng trên vai người khổng lồ Microsoft để giúp các bạn tiếp cận một cách dễ dàng hơn.

Tui chụp một số hình liên quan tới định dạng JSON để các bạn dễ mường tượng, sau đó Tui sẽ giải thích kỹ về các đối tượng cũng như cách sử dụng chúng:

Đây là hình JSON facebook của Tui do Facebook Graph API tạo ra:

android_51_1Hay facebook định dạng JSON của ngài Tổng Thống Mỹ BaracObama:

android_51_2Hay định dạng JSON tỉ giá hối đoái của Ngân Hàng Đông Á:

android_51_4Hay định dạng JSON của Hoa Hậu Kỳ Duyên:

android_51_3Bạn quan sát nó có những định dạng rất giống nhau theo 1 chuẩn nào đó, có ngoặc nhọn, ngoặc vuông, dấu 2 chấm, dấu chấm phẩy …. đó chính những chuẩn viết cho dạng JSON, sau đây Tui đi vào chi tiết lý thuyết của chúng:

Khái niệm Định Dạng JSON:

JSON (JavaScript Object Notation) được định nghĩa dữ theo ngôn ngữ JavaScript, tiêu chuẩn ECMA-262 năm 1999, cấu trúc là  một định dạng  văn bản  đơn giản với các trường dữ liệu được lồng vào nhau. JSON được sử dụng để trao đổi dữ liệu giữa các thành phần của một hệ thống  tương thích với hầu hết các ngôn ngữ C, C++, C#, Java, JavaScript, Perl, Python…

JSON được xây dựng dựa trên hai cấu trúc chính:

  • Tập hợp cặp giá trị name/value, trong nhiều ngôn ngữ khác nhau cặp giá trị này có thể là object, record, struct, dictionary,  hash table, keyed list…
  • Tập hợp danh sách các giá trị, có thể là array, vector, list hay sequence.

Và tuỳ thuộc vào dữ liệu cần trao đổi, JSON có thể có nhiều dạng khác nhau, tuy nhiên có thể tống hợp ở những hai dạng chính sau:

  • Một đối tượng Object chứa  các cặp giá trị string/value không cần thứ tự, được bao trong cặp “{}”, các giá trị bên trong được định dạng “string:value” và chia cách nhau bởi dấu “,”.  Value ở đây có thể là chuỗi, số, true- false, null…Có thể xem mô tả cùng ví dụ sau:

android_51_5Ví dụ:

{ "id": "100005823642721", "first_name": "Duy Thanh", "gender": "male", "last_name": "Trần", "link": "https://www.facebook.com/duythanhcse", "locale": "en_US", "birthday": "20/12/1961", "name": "Duy Thanh Trần", "username": "duythanhcse" }
  • Một đối tượng mảng có bao gồm nhều phần tử con có thứ tự. Các phần từ con được bao trong cặp “[]” và chia cách nhau bởi dấu “,”. Mỗi phần tử con có thể là một giá trị đơn lẻ như: số, chuỗi, true-false, null hoặc một object khác, thậm chí có thể là một mảng.

android_51_6Ví dụ:

{ "Sanphams": [ {"MaSP":"sp_1xxx","TenSP":"DELL Inspiron 14NR","SoLuong":100, "DonGia":150000,"ThanhTien":0, "Hinh":"https://duythanhcse.wordpress.com/h1.png" }, {"MaSP":"sp_2yyyy","TenSP":"HP Inspiron 113","SoLuong":130, "DonGia":140000,"ThanhTien":0, "Hinh":"https://duythanhcse.wordpress.com/h2.png" } ], "MaDM":"DM1", "TenDM":"Hàng máy tính" }

Việc đọc và ghi định dạng JSON được tích hợp sẵn trong Android SDK (nó nằm trong thư viện org.json) hoặc bạn có thể sử dụng thư viện độc lập ở trên mạng Link đây nầy để viết cho java thuần túy cũng được (Tui đã test thử và chạy OK)

  • JSONObject: đối tượng quản lý JSON ở dạng một Object.
  • JSONArray: đối  tượng quản lý JSON ở dạng tập hợn các Object hoặc Array.
  • JSONStringer: đối tượng chuyển dữ liệu JSON thành dạng chuỗi.
  • JSONTokener: chuyển đổi đối tượng JSON (chuẩn RFC-4627) mã hoá chuỗi một thành đối tượng tương ứng.

Để cho dễ hiểu thì Tui sẽ hướng dẫn các bạn đọc thông tin từ service với định dạng JSON: http://graph.facebook.com/duythanhcse, Bạn quan sát trong JSON này thì chỉ có 1 đối tượng duy nhất (được đóng khung trong cặp ngoặc nhọn), với các thuộc tính : id, first_name, username…. bên trái dấu 2 chấm là thuộc tính và bên phải dấu 2 chấm là giá trị của thuộc tính. Bạn cần chú ý là phải dùng Đa Tiến Trình để tương tác dữ liệu trên Internet, dữ liệu được xử lý trong tiểu trình (lý do Tui đã giải thích ở các bài trước).

Giả sử Bạn cần phải đọc thông tin JSON và hiển thị lên giao diện như sau:

android_51_7Sau đó thử Facebook của Ngài Tổng Thống Barac Obama:

android_51_8Và cuối cùng là của Hoa Hậu Cao Kỳ Duyên:

android_51_9Bấm vào nút Xem hình để tự động đọc link hình của Hoa Hậu trong Facebook (mở 1 Activity mới và dùng 1 tiểu trình khác để đọc):

android_51_10– Để làm được như trên thì bạn tiến hành thực hiện theo các bước sau:

 Bước 1:

Tạo một Project tên là LearnJSON:

android_51_11Tiến hành cấp quyền sử dụng Internet cho ứng dụng trong AndroidManifest.xml:

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

Tiến hành thiết kế giao diện chính như sau (activity_main.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="tranduythanh.com.MainActivity" > <TextView android:id="@+id/textView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="id:" /> <TextView android:id="@+id/txtId" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="Id ở đây" android:textColor="#FF0000" /> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="first_name:" /> <TextView android:id="@+id/txtFirstName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="First Name ở đây" android:textColor="#FF0000" /> <TextView android:id="@+id/textView5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="gender:" /> <TextView android:id="@+id/txtGender" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="Gender ở đây" android:textColor="#FF0000" /> <TextView android:id="@+id/textView7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="last_name:" /> <TextView android:id="@+id/txtLastName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="Last Name ở đây" android:textColor="#FF0000" /> <TextView android:id="@+id/textView9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="link:" /> <TextView android:id="@+id/txtLink" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="link ở đây" android:textColor="#FF0000" /> <TextView android:id="@+id/textView11" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="locale:" /> <TextView android:id="@+id/txtLocale" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="locale ở đây" android:textColor="#FF0000" /> <TextView android:id="@+id/textView13" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="name:" /> <TextView android:id="@+id/txtName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="name ở đây" android:textColor="#FF0000" /> <TextView android:id="@+id/textView15" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="username:" /> <TextView android:id="@+id/txtUserName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="username ở đây" android:textColor="#FF0000" /> <Button android:id="@+id/btnShowImage" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Xem hình" /> </LinearLayout>

Giao diện của nó sẽ như sau:

android_51_13Bước 2 – Tạo lớp MyJsonReader để đọc định dạng JSON:

package tranduythanh.com; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.nio.charset.Charset; import org.json.JSONException; import org.json.JSONObject; public class MyJsonReader { public static String readAll(Reader rd) throws IOException { StringBuilder sb = new StringBuilder(); int cp; while ((cp = rd.read()) != -1) { sb.append((char) cp); } return sb.toString(); } /** * Hàm trả về JSONObject * @param url - Truyền link URL có định dạng JSON * @return - Trả về JSONOBject * @throws IOException * @throws JSONException */ public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException { InputStream is = new URL(url).openStream(); try { //đọc nội dung với Unicode: BufferedReader rd = new BufferedReader (new InputStreamReader(is, Charset.forName("UTF-8"))); String jsonText = readAll(rd); JSONObject json = new JSONObject(jsonText); return json; } finally { is.close(); } } }

Bước 3- Xử lý MainActivity:

package tranduythanh.com; import java.io.IOException; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { TextView txtId; TextView txtFirstName; TextView txtLastName; TextView txtGender; TextView txtName; TextView txtLocale; TextView txtLink; TextView txtUserName; Button btnShowImage; public TextView findTextView(int id) { return (TextView) findViewById(id); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); addControlAndEvents(); } private void addControlAndEvents() { txtId=findTextView(R.id.txtId); txtFirstName=findTextView(R.id.txtFirstName); txtLastName=findTextView(R.id.txtLastName); txtName= findTextView(R.id.txtName); txtLink= findTextView(R.id.txtLink); txtGender =findTextView(R.id.txtGender); txtLocale= findTextView(R.id.txtLocale); txtUserName=findTextView(R.id.txtUserName); btnShowImage=(Button) findTextView(R.id.btnShowImage); btnShowImage.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //Code xem hình ở đây } }); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); new MyJsonTask().execute("http://graph.facebook.com/duythanhcse"); //new MyJsonTask().execute("http://graph.facebook.com/barackobama"); //new MyJsonTask().execute("http://graph.facebook.com/kyduyenhoahau"); } //Lớp xử lý đa tiến trình: public class MyJsonTask extends AsyncTask<String, JSONObject, Void> { @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); } @Override protected Void doInBackground(String... params) { //Lấy URL truyền vào String url=params[0]; JSONObject jsonObj; try { //đọc và chuyển về JSONObject jsonObj = MyJsonReader.readJsonFromUrl(url); publishProgress(jsonObj); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override protected void onProgressUpdate(JSONObject... values) { super.onProgressUpdate(values); //ta cập nhật giao diện ở đây: JSONObject jsonObj=values[0]; try { //kiểm tra xem có tồn tại thuộc tính id hay không if(jsonObj.has("id")) txtId.setText(jsonObj.getString("id")); if(jsonObj.has("first_name")) txtFirstName.setText(jsonObj.getString("first_name")); if(jsonObj.has("gender")) txtGender.setText(jsonObj.getString("gender")); if(jsonObj.has("last_name")) txtLastName.setText(jsonObj.getString("last_name")); if(jsonObj.has("link")) txtLink.setText(jsonObj.getString("link")); if(jsonObj.has("locale")) txtLocale.setText(jsonObj.getString("locale")); if(jsonObj.has("name")) txtName.setText(jsonObj.getString("name")); if(jsonObj.has("username")) txtUserName.setText(jsonObj.getString("username")); } catch (JSONException e) { Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show(); e.printStackTrace(); } } @Override protected void onPostExecute(Void result) { // TODO Auto-generated method stub super.onPostExecute(result); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.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(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }

Bạn quan sát:

if(jsonObj.has(“id”)) –> dùng để kiểm tra thuộc tính có tồn tại hay không txtId.setText(jsonObj.getString(“id”));–> Nếu tồn tại thì lấy thông tin

jsonObj.getXXX(Thuộc_Tính) –> lấy giá trị của thuộc tính. với XXX là phương thức tương ứng với Kiểu dữ liệu được JSON trả về.

Như vậy bạn đã đọc được thông tin từ JSON lên giao diện.

Bạn cố gắng chạy thành công việc đọc dữ liệu đơn giản từ JSON, sau đó mới qua mục bên dưới:

————————————————————

– Bây giờ ta tiến hành đọc hình ảnh của Hoa Hậu Kỳ Duyên (http://graph.facebook.com/kyduyenhoahau), bạn nhớ đổi link đọc JSON qua Kỳ Duyên nhé:

android_51_14Bạn Thấy hình trên Tui chụp JSON của Kỳ Duyên, cover là thuộc tính và nó trả về 1 đối tượng JSONObject, trong đối tượng do cover trả về thì nó có thuộc tính source để lưu hình ảnh của Kỳ Duyên. Ta có thể đọc và xử lý hình ảnh như sau:

– Làm để đọc được source hình của Hoa Hậu từ JSon ở trên?

– Khi có source hình rồi thì làm sao để hiển thị lên giao diện của Android?

trước tiên ta cần bổ sung thêm lớp ImageLoadTask để tạo tiểu trình tải hình ảnh theo link bất kỳ và màn hình XemHinhActivity để hiển thị hình ảnh lên:

android_51_15Màn hình hiển thị hình ảnh đơn giản như sau (activity_xem_hinh.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="tranduythanh.com.XemHinhActivity" > <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> </LinearLayout>

– Tiến hành xử lý tải hình ảnh từ URL (ImageLoadTask.java):

package tranduythanh.com; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.widget.ImageView; public class ImageLoadTask extends AsyncTask<Void, Void, Bitmap> { //Link url hình ảnh bất kỳ private String url; //Control ImageView bất kỳ private ImageView imageView; public ImageLoadTask(String url, ImageView imageView) { this.url = url; this.imageView = imageView; } @Override protected Bitmap doInBackground(Void... params) { try { //Tiến hành tạo đối tượng URL URL urlConnection = new URL(url); //Mở kết nối HttpURLConnection connection = (HttpURLConnection) urlConnection .openConnection(); connection.setDoInput(true); connection.connect(); //Đọc dữ liệu InputStream input = connection.getInputStream(); //Tiến hành convert qua hình ảnh Bitmap myBitmap = BitmapFactory.decodeStream(input); return myBitmap; } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); //lấy kết quả hiển thị lên giao diện: imageView.setImageBitmap(result); } }

– Tiếp theo tiến hành hiển thị hình ảnh lên giao diện (XemHinhActivity), lớp này sẽ sử dụng lại ImageLoadTask:

package tranduythanh.com; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.ImageView; public class XemHinhActivity extends Activity { ImageView imgView; String urlImage=""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_xem_hinh); imgView=(ImageView) findViewById(R.id.imageView1); //Lấy Intent từ MainActivity Intent in= getIntent(); //Lấy link hình ảnh ra được truyền từ MainActivity urlImage=in.getStringExtra("URL_IMG"); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); //Tiến hành tải hình theo urlImage và hiển thị lên giao diện: new ImageLoadTask(urlImage, imgView).execute(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.xem_hinh, 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(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }

-Bạn để ý dòng 20 và dòng 22 ở trên, nó được lấy thông tin từ dòng 39 ở lớp dưới đây:

– Tiến hành sửa coding lại cho MainActivity, vì ở trên ta chưa xử lý đọc link hình ảnh truyền qua màn hình XemHinhActivity:

package tranduythanh.com; import java.io.IOException; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { String urlImage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); addControlAndEvents(); } private void addControlAndEvents() { btnShowImage=(Button) findTextView(R.id.btnShowImage); btnShowImage.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent in=new Intent (MainActivity.this, XemHinhActivity.class); in.putExtra("URL_IMG", urlImage); startActivity(in); } }); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); new MyJsonTask().execute("http://graph.facebook.com/kyduyenhoahau"); } //Lớp xử lý đa tiến trình: public class MyJsonTask extends AsyncTask<String, JSONObject, Void> { @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); } @Override protected Void doInBackground(String... params) { //Lấy URL truyền vào String url=params[0]; JSONObject jsonObj; try { //đọc và chuyển về JSONObject jsonObj = MyJsonReader.readJsonFromUrl(url); if(jsonObj.has("cover")) { JSONObject objCover= jsonObj.getJSONObject("cover"); if(objCover.has("source")) { urlImage=objCover.getString("source"); } } publishProgress(jsonObj); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override protected void onProgressUpdate(JSONObject... values) { super.onProgressUpdate(values); } @Override protected void onPostExecute(Void result) { // TODO Auto-generated method stub super.onPostExecute(result); } } }

– Tui xóa hết những code cũ, chỉ giữ lại code xử lý xem hình ảnh, quan quan sát Tui  bổ sung những lệnh sau:

+Biến urlImage để lưu được link hình ảnh của Hoa Hậu Kỳ Duyên

+ xử lý đọc hình (dòng 66 tới 72)

+ Xử lý gửi link hình qua màn hình xem hình ảnh (dòng 39)

Sau khi sửa xong và chạy phần mềm ta được kết quả như sau:

android_51_16Bạn có thể tải source code mẫu đầy đủ tại đây:

Tải Link ở đây nầy bạn!

Tương tự, nếu bạn đổi qua link của Ngài Tổng Thống Barac Obamá thì tự động bạn cũng có được hình ảnh như sau:

android_51_17Bài tiếp theo Tui sẽ hướng dẫn các bạn cách tạo JSON trong .net webservice và cách tương tác với chúng

Các bạn chú ý theo dõi!

Chúc các bạn thành công!

Chia sẻ lên:

  • Tweet
  • Print
Like Loading...

Related

Từ khóa » đọc File Json Trong Android