[Khóa học lập trình Android] Bài 07 Thao tác với JSON trong Android

Đây là khóa học lập trình Android miễn phí với nội dung các bài học mạch lạc và dễ hiểu với những bài hướng dẫn lập trình ứng dụng Android cơ bản nhất. Nội dung phần hướng dẫn này trình bày thao tác với JSON trong Android.

Nếu như ở phần hướng dẫn trước mình đã trình bày về phân tích dữ liệu JSON thì tiếp theo là phần hướng dẫn thao tác với JSON trong Android. Làm sao để có thể đọc được dữ liệu JSON hoặc XML trong ứng dụng Android?

Phần trước mình làm ví dụ tra cứu tỷ giá ngoại tệ từ API do Team Việt Dev cung cấp, chuỗi JSON trả về như sau:

[
  {
    "id": "4033",
    "kind": "Vietcombank",
    "serial": "AUD",
    "name": "AUST.DOLLAR",
    "buy": "16940.54",
    "transfer": "17042.8",
    "sell": "17240.02",
    "datetime": "7/28/2018 10:53:42 AM"
  },
  {
    "id": "4034",
    "kind": "Vietcombank",
    "serial": "CAD",
    "name": "CANADIAN DOLLAR",
    "buy": "17520.82",
    "transfer": "17679.94",
    "sell": "17884.54",
    "datetime": "7/28/2018 10:53:42 AM"
  },
  {
    "id": "4035",
    "kind": "Vietcombank",
    "serial": "CHF",
    "name": "SWISS FRANCE",
    "buy": "23012.32",
    "transfer": "23174.54",
    "sell": "23489.66",
    "datetime": "7/28/2018 10:53:42 AM"
  }
]

Để xử lý JSON trong Android bạn cần thêm thư viện Gson vào dự án, thư viện Gson giúp dễ dàng chuyển đổi định dạng JSON nhanh và tiện lợi hơn. Bạn mở tập tin build.gradle (Module:app) và thêm đoạn mã sau vào và nhấn vào Sync Now ở góc phải bên trên màn hình:

implementation 'com.google.code.gson:gson:2.6.2'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

Retrofit là một trong những thư viện Rest-Client được sử dụng phổ biến trong việc giao tiếp giữa client – server trở lên dễ dàng và thuận tiện hơn, mình sẽ sử dụng thư viện Retrofit trong Android để gọi đến Web Service.

Bây giờ mình sẽ thiết kế các lớp tương ứng với cấu trúc JSON mà Web Service trả về, mình sẽ tạo lớp Currency.java nằm trong gói (package) model như sau:

package com.teamvietdev.tctt.model;
 
import com.google.gson.annotations.SerializedName;
 
import java.util.List;
 
public class Currency {
 
    @SerializedName("id")
    private intid;
    @SerializedName("kind")
    private String kind;
    @SerializedName("serial")
    private String serial;
    @SerializedName("name")
    private String name;
    @SerializedName("buy") 
    private String buy; 
    @SerializedName("transfer") 
    private String transfer; 
    @SerializedName("sell") 
    private String sell;
    @SerializedName("datetime") 
    private String datetime;
 
    // getter & setter
 
}

Bây giờ mới đến phần quan trọng nhất để lấy dữ liệu, để làm được điều này bạn sẽ phải sử dụng đến lớp Retrofit Builder và xác định rõ đường dẫn (URL) dịch vụ.

Tạo lớp API.java như sau:

package com.teamvietdev.tctt.retrofit;

import com.teamvietdev.tctt.model.Currency;

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface API {

    @FormUrlEncoded
    @POST("list_currency.php")
    Call<Currency> getListCurrency(@Field("token") String token);

}

Tạo lớp ApiClient.java như sau:

package com.teamvietdev.tctt.retrofit;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiClient {

    private static String URL = "https://teamvietdev.com/tracuuthitruong/";
    private API api = null;

    public API getClient() {
        try {
            if (api == null) {
                Gson gson = new GsonBuilder().setLenient().create();
                final OkHttpClient okHttpClient = new OkHttpClient.Builder()
                        .sslSocketFactory(new TLSSocketFactory())
                        .readTimeout(30, TimeUnit.SECONDS)
                        .connectTimeout(15, TimeUnit.SECONDS)
                        .build();
                api = new Retrofit.Builder()
                        .baseUrl(URL)
                        .client(okHttpClient)
                        .addConverterFactory(GsonConverterFactory.create(gson))
                        .build().create(API.class);
            }
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return api;
    }

    public class TLSSocketFactory extends SSLSocketFactory {

        private SSLSocketFactory delegate;

        public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, null, null);
            delegate = context.getSocketFactory();
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return delegate.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            return delegate.getSupportedCipherSuites();
        }

        @Override
        public Socket createSocket() throws IOException {
            return enableTLSOnSocket(delegate.createSocket());
        }

        @Override
        public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
            return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
        }

        @Override
        public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
            return enableTLSOnSocket(delegate.createSocket(host, port));
        }

        @Override
        public Socket createSocket(String host, int port, InetAddress  localHost, int localPort) throws IOException, UnknownHostException {
            return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
        }

        @Override
        public Socket createSocket(InetAddress host, int port) throws IOException {
            return enableTLSOnSocket(delegate.createSocket(host, port));
        }

        @Override
        public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
            return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
        }

        private Socket enableTLSOnSocket(Socket socket) {
            if (socket != null && (socket instanceof SSLSocket)) {
                ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"});
            }
            return socket;
        }

    }

}

Bạn nhớ phải cấp quyền truy cập Internet trong tập tin AndroidManifest.xml bằng cách thêm đoạn mã:

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

Tiếp theo bạn tao lớp DataPresenter.java và DataPresenterImpl.java sử dụng để xử lý các yêu cầu từ phía View, truy vấn dữ liệu từ Model và sau đó đẩy dữ liệu cho View hiển thị.

Lớp MyViewInterface.java như sau:

package com.teamvietdev.tctt.helper;

public interface MyViewInterface {

    public void onComplete(String kind, Object obj);

    public void onFailed(String msg);

}

Lớp DataPresenter.java như sau:

package com.teamvietdev.tctt.presenter;

public interface DataPresenter {

    public void getListCurrency(String token);

}

Lớp DataPresenterImpl.java như sau:

package com.teamvietdev.tctt.presenter;

import com.teamvietdev.tctt.helper.MyViewInterface;
import com.teamvietdev.tctt.model.Currency;
import com.teamvietdev.tctt.service.ApiClient;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class DataPresenterImpl implements DataPresenter {

    private MyViewInterface myViewInterface = null;
    private ApiClient apiClient;

    public DataPresenterImpl(MyViewInterface myViewInterface) {
        this.myViewInterface = myViewInterface;
        this.apiClient = new ApiClient();
    }

    @Override
    public void getListCurrency(String token) {
        Call<List<Currency>> call = apiClient.getClient().getListCurrency(token);
        call.enqueue(new Callback<List<Currency>>() {
            @Override
            public void onResponse(Call<List<Currency>> call, Response<List<Currency>> response) {
                if (response.body() != null) {
                    myViewInterface.onComplete("currency", response.body());
                } else {
                    myViewInterface.onFailed("null");
                }
            }

            @Override
            public void onFailure(Call<List<Currency>> call, Throwable t) {
                myViewInterface.onFailed(t.getMessage().toString());
            }
        });
    }

}

Khởi tạo Activity đặt tên CurrencyActivity.java, sau đó chúng ta sẽ lấy dữ liệu về ứng dụng.

package com.teamvietdev.tctt.view;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;

import com.teamvietdev.tctt.R;
import com.teamvietdev.tctt.helper.MyViewInterface;
import com.teamvietdev.tctt.presenter.DataPresenter;
import com.teamvietdev.tctt.presenter.DataPresenterImpl;

public class CurrencyActivity extends AppCompatActivity implements MyViewInterface {

    private DataPresenter dataPresenter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_curren);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        dataPresenter = new DataPresenterImpl(this);
        dataPresenter.getListCurrency("teamvietdev.com");

    }

    @Override
    public void onComplete(String kind, Object obj) {
        Log.d("onComplete", obj.toString());
    }

    @Override
    public void onFailed(String msg) {
        Log.d("onFailed", msg);
    }

}

Bạn mở MainActivity.java sau đó xử lý sự kiện khi nhấn vào CardView sẽ chuyển qua CurrencyActivity.java

CardView cvCurrency = (CardView) findViewById(R.id.cvCurrency);
cvCurrency.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
              Intent intent = new Intent(MainActivity.this, CurrencyActivity.class);
              startActivity(intent);
       }
});

Trong Android bạn sử dụng đối tượng Intent sau đó gọi phương thức startActivity() để mở một Activity khác trong ứng dụng.

Bây giờ bạn khởi chạy ứng dụng Android sau đó kiểm tra xem Log có kết quả trả về hay không, nếu có kết quả trả về có nghĩa là thao tác với JSON trong Android lấy dữ liệu từ WebService về thành công.

Kết quả sau khi mình lấy dữ liệu chẳng hạn như sau:

08-04 15:51:04.926 26942-26942/com.teamvietdev.tctt D/onComplete: 
[Currency{id=7028, kind='Vietcombank', serial='AUD', name='AUST.DOLLAR', buy='16975.47', transfer='17077.94', sell='17264.38', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7029, kind='Vietcombank', serial='CAD', name='CANADIAN DOLLAR', buy='17654.67', transfer='17815.01', sell='18009.5', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7030, kind='Vietcombank', serial='CHF', name='SWISS FRANCE', buy='23095.59', transfer='23258.4', sell='23559.4', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7031, kind='Vietcombank', serial='DKK', name='DANISH KRONE', buy='0', transfer='3569.32', sell='3681.19', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7032, kind='Vietcombank', serial='EUR', name='EURO', buy='26805.61', transfer='26886.27', sell='27125.49', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7033, kind='Vietcombank', serial='GBP', name='BRITISH POUND', buy='29990.4', transfer='30201.81', sell='30470.53', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7034, kind='Vietcombank', serial='HKD', name='HONGKONG DOLLAR', buy='2926.52', transfer='2947.15', sell='2991.27', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7035, kind='Vietcombank', serial='INR', name='INDIAN RUPEE', buy='0', transfer='338.16', sell='351.43', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7036, kind='Vietcombank', serial='JPY', name='JAPANESE YEN', buy='204.47', transfer='206.54', sell='210.89', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7037, kind='Vietcombank', serial='KRW', name='SOUTH KOREAN WON', buy='19.05', transfer='20.05', sell='21.31', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7038, kind='Vietcombank', serial='KWD', name='KUWAITI DINAR', buy='0', transfer='76854.56', sell='79869.82', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7039, kind='Vietcombank', serial='MYR', name='MALAYSIAN RINGGIT', buy='0', transfer='5675.51', sell='5748.95', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7040, kind='Vietcombank', serial='NOK', name='NORWEGIAN KRONER', buy='0', transfer='2786.4', sell='2873.73', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7041, kind='Vietcombank', serial='RUB', name='RUSSIAN RUBLE', buy='0', transfer='367.49', sell='409.49', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7042, kind='Vietcombank', serial='SAR', name='SAUDI RIAL', buy='0', transfer='6199.1', sell='6442.32', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7043, kind='Vietcombank', serial='SEK', name='SWEDISH KRONA', buy='0', transfer='2590.83', sell='2656.05', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7044, kind='Vietcombank', serial='SGD', name='SINGAPORE DOLLAR', buy='16822.72', transfer='16941.31', sell='17126.27', datetime='8/4/2018 1:58:43 PM'}, 
Currency{id=7045, kind='Vietcombank', serial='THB', name='THAI BAHT', buy='685.22', transfer='685.22', sell='713.8', datetime='8/4/2018 1:58:43 PM'},
Currency{id=7046, kind='Vietcombank', serial='USD', name='US DOLLAR', buy='23260', transfer='23260', sell='23340', datetime='8/4/2018 1:58:43 PM'}]

Xem nội dung chi tiết hướng dẫn trên Youtube:

Lời kết: Như vậy khóa học lập trình Android miễn phí được chia sẻ bởi Team Việt Dev hy vọng giúp bạn có thêm nhiều kiến thức cơ bản để tự xây dựng cho riêng mình một ứng dụng Android.

(Tác giả: Team Việt Dev)

Bình luận