Tải hình ảnh lên bằng API phát hành dịch vụ trò chơi của Play

Với Play Games Services Publishing API (API Phát hành dịch vụ trò chơi của Play), bạn có thể tải một hình ảnh lên cho một tài nguyên trò chơi.

Tùy chọn tải lên

API phát hành dịch vụ trò chơi của Play cho phép bạn tải lên một số loại dữ liệu nhị phân hoặc nội dung đa phương tiện nhất định. Các đặc tính cụ thể của dữ liệu mà bạn có thể tải được chỉ định trên trang tham chiếu cho bất kỳ phương pháp nào hỗ trợ tải nội dung đa phương tiện:

  • Kích thước tối đa của tệp tải lên: là dung lượng dữ liệu tối đa mà bạn có thể lưu trữ qua phương thức này.

  • Các loại MIME nội dung đa phương tiện được chấp nhận: là các loại dữ liệu nhị phân bạn có thể lưu trữ bằng phương thức này.

Bạn có thể gửi yêu cầu tải lên theo bất kỳ cách nào sau đây. Chỉ định phương thức bạn đang sử dụng với tham số tải lên theo yêu cầu uploadType.

  • Tải lên đơn giản: uploadType=media. Để chuyển nhanh các tệp nhỏ, chẳng hạn như các tệp có dung lượng từ 5 MB trở xuống.

  • Tải nhiều phần lên: uploadType=multipart. Để chuyển nhanh các tệp nhỏ và siêu dữ liệu; chuyển tệp cùng với siêu dữ liệu mô tả tệp trong một yêu cầu duy nhất.

  • Tải lên tiếp nối: uploadType=resumable. Để chuyển dữ liệu một cách đáng tin cậy, đặc biệt là với các tệp lớn. Bạn hãy sử dụng yêu cầu khởi tạo phiên đối với những phương thức này, tùy chọn có thể bao gồm siêu dữ liệu. Đây là chiến lược hay để sử dụng cho hầu hết các ứng dụng, vì nó cũng phù hợp với các tệp nhỏ hơn và chỉ phải tốn thêm một yêu cầu HTTP bổ sung cho mỗi lần tải lên.

Khi tải lên một nội dung đa phương tiện, bạn cần sử dụng URI đặc biệt. Trên thực tế, các phương thức hỗ trợ tải nội dung đa phương tiện lên có hai điểm cuối URI:

  • /upload URI, cho nội dung đa phương tiện. Định dạng của điểm cuối tải lên là URI tài nguyên chuẩn có tiền tố “/upload”. Sử dụng URI này khi chuyển dữ liệu của nội dung đa phương tiện.

    Chẳng hạn như POST /upload/games/v1configuration/images/resourceId/imageType/imageType

  • URI tài nguyên chuẩn, cho siêu dữ liệu. Nếu tài nguyên chứa bất kỳ trường dữ liệu nào, các trường đó sẽ được dùng để lưu trữ siêu dữ liệu mô tả tệp đã tải lên. Bạn có thể sử dụng URI này khi tạo hoặc cập nhật giá trị siêu dữ liệu.

    Chẳng hạn như POST /games/v1configuration/images/resourceId/imageType/imageType

Tải lên đơn giản

Phương thức dễ dàng nhất để tải tệp là tạo một yêu cầu tải lên đơn giản. Bạn nên chọn tùy chọn này khi đáp ứng một trong các điều kiện sau:

  • Dung lượng tệp nhỏ vừa đủ để tải lại nếu bất ngờ bị mất kết nối.

  • Không bao gồm siêu dữ liệu. Đây là cách phù hợp nếu bạn có ý định gửi siêu dữ liệu cho tài nguyên này trong một yêu cầu riêng, hoặc nếu không siêu dữ liệu nào được hỗ trợ hay có sẵn. Để sử dụng hình thức tải lên đơn giản, hãy thực hiện yêu cầu POST hoặc PUT đến URI /upload của phương thức, đồng thời thêm tham số truy vấn uploadType=media. Ví dụ:

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=media

Các tiêu đề HTTP cần sử dụng khi tạo một yêu cầu tải lên đơn giản bao gồm:

  • Content-Type. Đặt thành một trong các loại dữ liệu nội dung đa phương tiện tải lên được chấp nhận của phương thức, đã chỉ định trong tệp tham chiếu của API xuất bản.

  • Content-Length. Đặt thành số byte tương ứng mà bạn đang tải lên. Không bắt buộc nếu bạn sử dụng mã hóa chuyển dữ liệu chia nhỏ.

Ví dụ: Tải lên đơn giản

Ví dụ sau minh họa cách sử dụng một yêu cầu tải lên đơn giản cho API Phát hành dịch vụ trò chơi của Play.

POST /upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=media HTTP/1.1
Host: www.googleapis.com
Content-Type: image/png
Content-Length: number_of_bytes_in_file
Authorization: Bearer your_auth_token

PNG data

Nếu yêu cầu thành công, máy chủ sẽ trả về mã trạng thái HTTP 200 OK cùng với bất kỳ siêu dữ liệu nào. Ví dụ:

HTTP/1.1 200
Content-Type: application/json

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

Tải nhiều phần lên

Nếu bạn muốn tải dữ liệu lên cùng với siêu dữ liệu, bạn có thể thực hiện một yêu cầu multipart/related. Đây là lựa chọn phù hợp nếu dữ liệu bạn gửi khá nhỏ để tải lên lại toàn bộ nếu kết nối bị ngắt.

Để sử dụng tính năng tải lên nhiều phần, hãy tạo yêu cầu POST hoặc PUT đến URI /upload của phương thức và thêm tham số truy vấn uploadType=multipart. Ví dụ:

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=multipart

Tiêu đề HTTP cấp cao nhất cần thực hiện khi tạo một yêu cầu tải lên nhiều phần bao gồm:

Content-Type. Đặt thành nhiều phần/liên quan và chứa chuỗi ranh giới mà bạn sử dụng để xác định các phần của yêu cầu.

Content-Length. Đặt thành tổng số byte trong nội dung của yêu cầu. Dung lượng nội dung phương tiện của yêu cầu phải nhỏ hơn kích thước tệp tối đa được chỉ định cho phương pháp này.

Nội dung của yêu cầu được định dạng dưới dạng loại nội dung nhiều phần/có liên quan RFC2387 và chứa đúng hai phần. Mỗi phần được xác định bằng một chuỗi ranh giới, và theo sau chuỗi ranh giới cuối cùng là hai dấu gạch nối.

Mỗi phần của yêu cầu nhiều phần cần bổ sung tiêu đề Loại nội dung:

  • Phần siêu dữ liệu: phải đứng trước, và Loại nội dung phải khớp với một trong các định dạng siêu dữ liệu được chấp nhận.

  • Phần nội dung đa phương tiện: Phải đứng sau, và Loại nội dung phải khớp với một loại MIME nội dung đa phương tiện được chấp nhận.

Vui lòng xem qua tài liệu tham khảo về API phát hành cho mỗi phương thức để biết danh sách các loại MIME nội dung đa phương tiện được chấp nhận và dung lượng giới hạn cho các tệp đã tải lên.

Ví dụ: Tải lên nhiều phần

Ví dụ dưới đây minh họa về yêu cầu tải lên nhiều phần cho API phát hành dịch vụ trò chơi của Play.

POST /upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Type: multipart/related; boundary=foo_bar_baz
Content-Length: number_of_bytes_in_entire_request_body

--foo_bar_baz
Content-Type: application/json; charset=UTF-8

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

--foo_bar_baz
Content-Type: image/png

PNG data
--foo_bar_baz--

Nếu yêu cầu thành công, máy chủ sẽ trả về mã trạng thái HTTP 200 OK cùng với bất kỳ siêu dữ liệu nào:

HTTP/1.1 200
Content-Type: application/json

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

Tải lên tiếp nối

Để tải các tệp dữ liệu lên một cách đáng tin cậy, bạn có thể sử dụng giao thức tải lên tiếp nối. Giao thức này cho phép bạn tiếp tục hoạt động tải lên sau khi lỗi giao tiếp làm gián đoạn luồng dữ liệu. Tính năng này đặc biệt hữu ích nếu bạn đang chuyển tệp lớn và có nhiều khả năng bị gián đoạn mạng hoặc một số lỗi truyền khác, chẳng hạn như khi tải lên từ ứng dụng khách di động. Tính năng này cũng có thể làm giảm mức sử dụng băng thông trong trường hợp mạng bị lỗi vì bạn không phải bắt đầu lại quá trình tải tệp lớn lên từ đầu.

Các bước để sử dụng tính năng tải lên tiếp nối:

  1. Bắt đầu một phiên hoạt động có thể tiếp tục. Tạo một yêu cầu khởi tạo cho URI tải lên chứa siêu dữ liệu, nếu có.

  2. Lưu URI phiên có thể tiếp tục. Lưu URI của phiên đã trả về trong phản hồi của yêu cầu khởi tạo; bạn sẽ sử dụng giá trị này cho các yêu cầu còn lại trong phiên hoạt động. Tải tệp lên.

  3. Gửi tệp nội dung đa phương tiện đến URI của phiên có thể tiếp nối.

Ngoài ra, ứng dụng sử dụng tính năng tải lên tiếp nối cần có mã để tiếp tục quá trình tải lên bị gián đoạn. Nếu quá trình tải lên bị gián đoạn, hãy tìm hiểu lượng dữ liệu đã nhận được, sau đó tiếp tục tải lên tại thời điểm bị gián đoạn đó.

Bắt đầu một phiên hoạt động có thể tiếp tục

Để bắt đầu tải lên có thể tiếp nối, hãy tạo một yêu cầu POST hoặc PUT cho URI /upload của phương thức, sau đó thêm tham số truy vấn uploadType=resumable. Ví dụ:

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable

Đối với yêu cầu khởi tạo này, nội dung phải để trống hoặc chỉ chứa siêu dữ liệu; bạn sẽ chuyển nội dung thực tế của tệp bạn muốn tải lên trong các yêu cầu tiếp theo.

Sử dụng các tiêu đề HTTP dưới đây với yêu cầu khởi tạo:

  • X-Upload-Content-Type. Đặt thành loại MIME nội dung đa phương tiện của dữ liệu tải lên sẽ được truyền trong các yêu cầu tiếp theo.

  • X-Upload-Content-Length. Đặt thành số byte tương ứng của dữ liệu tải lên sẽ được truyền trong các yêu cầu tiếp theo. Nếu không nắm rõ được độ dài tại thời điểm tạo yêu cầu này, bạn có thể bỏ qua tiêu đề này.

  • Nếu có chứa siêu dữ liệu: Content-Type. Đặt theo loại dữ liệu của siêu dữ liệu.

  • Content-Length. Đặt thành số byte tương ứng có trong nội dung của yêu cầu khởi tạo này. Không bắt buộc nếu bạn sử dụng mã hóa chuyển dữ liệu chia nhỏ.

Vui lòng xem tài liệu tham khảo về API phát hành để biết danh sách các loại MIME nội dung đa phương tiện được chấp nhận và dung lượng giới hạn cho các tệp đã tải lên của từng phương thức.

Ví dụ: Yêu cầu khởi tạo phiên có thể tiếp tục

Ví dụ sau đây minh hoạ cách bắt đầu một phiên có thể tiếp tục cho API Phát hành dịch vụ trò chơi của Play.

POST /upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: image/png
X-Upload-Content-Length: 2000000

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

Phần tiếp theo sẽ mô tả cách xử lý các yêu cầu này.

Lưu URI phiên có thể tiếp tục

Nếu yêu cầu khởi tạo phiên thành công, máy chủ API sẽ phản hồi bằng mã trạng thái HTTP 200 OK. Ngoài ra còn cung cấp tiêu đề Location chỉ định URI phiên hoạt động tiếp theo của bạn. Tiêu đề Location hiển thị trong ví dụ bên dưới, bao gồm phần tham số truy vấn upload_id cung cấp mã tải lên duy nhất để sử dụng cho phiên này.

Ví dụ: Phản hồi khởi tạo phiên có thể tiếp tục

Dưới đây là phản hồi cho yêu cầu ở Bước 1:

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable&upload_id=xa298sd_sdlkj2
Content-Length: 0

Giá trị của tiêu đề Location như hiển thị trong phản hồi mẫu ở trên là URI phiên mà bạn sẽ sử dụng làm điểm cuối HTTP để tải tệp thực tế lên, hoặc truy vấn trạng thái tải lên.

Sao chép và lưu URI phiên để bạn có thể sử dụng cho các yêu cầu tiếp theo.

Tải tệp lên

Để tải tệp lên, hãy gửi yêu cầu PUT đến URI tải lên mà bạn nhận được ở bước trước đó. Định dạng của yêu cầu tải lên sẽ là:

PUT session_uri

Những tiêu đề HTTP cần sử dụng khi tạo các yêu cầu tiếp tục tải tệp lên bao gồm Content-Length. Đặt thành số byte tương ứng mà bạn đang tải lên trong yêu cầu này, thường là kích thước tệp tải lên.

Ví dụ: Yêu cầu tải tệp có thể tiếp nối lên

Đây là yêu cầu có thể tiếp tục tải lên toàn bộ tệp có định dạng PNG 2.000.000 byte cho ví dụ hiện tại.

PUT https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable&upload_id=xa298sd_sdlkj2 HTTP/1.1
Content-Length: 2000000
Content-Type: image/png

bytes 0-1999999

Nếu yêu cầu thành công, máy chủ sẽ phản hồi bằng HTTP 201 Created, cùng với bất kỳ siêu dữ liệu nào được liên kết với tài nguyên này. Nếu yêu cầu khởi tạo của phiên hoạt động có thể tiếp tục là PUT, thì để cập nhật tài nguyên hiện có, phản hồi thành công sẽ là 200 OK, cùng với bất kỳ siêu dữ liệu nào được liên kết với tài nguyên này.

Nếu yêu cầu tải lên bị gián đoạn hoặc nếu bạn nhận được HTTP 503 Service Unavailable hoặc bất kỳ phản hồi 5xx nào khác từ máy chủ, hãy làm theo quy trình đã nêu trong phần tiếp tục quá trình tải lên bị gián đoạn.

Tải tệp lên theo từng phần

Với tính năng tải lên tiếp nối, bạn có thể chia một tệp thành nhiều phần và gửi một loạt yêu cầu để tải lên từng phần theo trình tự. Đây không phải là phương pháp tối ưu do chi phí hiệu suất liên quan đến các yêu cầu bổ sung, và điều này thường không cần thiết. Tuy nhiên, bạn có thể cần phải sử dụng tính năng phân dữ liệu để giảm dung lượng truyền vào trong bất kỳ yêu cầu riêng lẻ nào. Điều này rất hữu ích khi có giới hạn thời gian cố định cho từng yêu cầu riêng lẻ, cũng như đối với một số yêu cầu nhất định của Google App Engine. Tùy chọn này cũng cho phép bạn thực hiện một số việc như cung cấp chỉ báo tiến trình tải lên cho những trình duyệt cũ không hỗ trợ tiến trình tải lên theo mặc định.

Nếu tải dữ liệu lên từng phần, bạn cũng cần phải có tiêu đề Phạm vi nội dung, cùng với tiêu đề Độ dài nội dung cần thiết để tải toàn bộ tệp lên:

  • Content-Length. Đặt thành kích thước phân đoạn hoặc có thể nhỏ hơn, vì đây có thể là trường hợp yêu cầu cuối cùng.

  • Content-Range. Đặt để hiển thị số byte trong tệp bạn đang tải lên. Ví dụ: Content-Range: bytes 0-524287/2000000 cho thấy bạn đang cung cấp 524.288 byte đầu tiên (256 x 1024 x 2) trong tệp chứa 2.000.000 byte.

Tiếp tục quá trình tải lên bị gián đoạn

Nếu yêu cầu tải lên bị chấm dứt trước khi nhận được phản hồi, hoặc nếu bạn nhận được phản hồi HTTP 503 Service Unavailable từ máy chủ, thì bạn cần tiếp tục quá trình tải lên bị gián đoạn. Để tiếp tục quá trình tải lên bị gián đoạn, hãy làm như sau:

  1. Yêu cầu trạng thái. Truy vấn trạng thái hiện tại của quá trình tải lên bằng cách đưa ra một yêu cầu PUT trống cho URI tải lên. Đối với yêu cầu này, tiêu đề HTTP phải bao gồm tiêu đề Content-Range cho biết vị trí hiện tại trong tệp là không xác định. Ví dụ: hãy đặt Content-Range thành */2000000 nếu tổng chiều dài tệp của bạn là 2.000.000. Nếu bạn không biết kích thước đầy đủ của tệp, hãy đặt Phạm vi nội dung thành */*.

  2. Nhận số byte đã tải lên. Xử lý phản hồi trong truy vấn trạng thái. Máy chủ sử dụng tiêu đề Range trong phản hồi để chỉ định số byte đã nhận được cho đến hiện tại. Ví dụ: tiêu đề Range của 0-299999 cho biết 300.000 byte đầu tiên của tệp đã được nhận.

  3. Tải dữ liệu còn lại lên. Giờ thì bạn đã biết vị trí để tiếp tục yêu cầu, gửi dữ liệu còn lại hoặc phần hiện tại. Vui lòng lưu ý rằng bạn cần xem dữ liệu còn lại là một phần riêng biệt trong cả hai trường hợp, do đó, bạn phải gửi tiêu đề Content-Range khi tiếp tục tải lên.

Ví dụ: Tiếp tục quá trình tải lên bị gián đoạn

  1. Yêu cầu trạng thái tải lên. Yêu cầu sau đây sử dụng tiêu đề Phạm vi nội dung để cho biết vị trí hiện tại trong tệp 2.000.000 byte là không xác định.

    PUT {session_uri} HTTP/1.1
    Content-Length: 0
    Content-Range: bytes */2000000
    
  2. Trích xuất số byte có trong phản hồi đã tải lên tính đến thời điểm hiện tại. Phản hồi của máy chủ sử dụng tiêu đề Range để cho biết đã nhận được 43 byte đầu tiên của tệp tính đến hiện tại. Sử dụng giá trị trên của tiêu đề Phạm vi để xác định vị trí bắt đầu quá trình tải lên tiếp nối.

    HTTP/1.1 308 Resume Incomplete
    Content-Length: 0
    Range: 0-42
    
  3. Tiếp tục tải lên từ điểm đã dừng lại. Yêu cầu sau đây sẽ tiếp tục quá trình tải lên bằng cách gửi các byte còn lại của tệp, bắt đầu từ byte 43.

    PUT {session_uri} HTTP/1.1
    Content-Length: 1999957
    Content-Range: bytes 43-1999999/2000000
    
    bytes 43-1999999
    

Xử lý lỗi

Khi tải nội dung nghe nhìn lên, bạn nên nắm một số phương pháp hay liên quan đến việc xử lý lỗi.

  • Tiếp tục hoặc thử tải lại các lần tải không thành công do gián đoạn kết nối hoặc bất kỳ lỗi 5xx nào, bao gồm:

    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Sử dụng chiến lược thời gian đợi luỹ thừa nếu có bất kỳ lỗi máy chủ 5xx nào bị trả về khi tiếp tục hoặc thử lại các yêu cầu tải lên. Những lỗi này có thể xảy ra nếu máy chủ bị quá tải. Thuật toán thời gian đợi lũy thừa có thể giúp giảm bớt các sự cố dạng này trong giai đoạn có khối lượng lớn các yêu cầu hoặc lưu lượng truy cập mạng lớn.

  • Các loại yêu cầu khác không được xử lý bằng thuật toán thời gian đợi lũy thừa, nhưng bạn vẫn có thể thử lại một số yêu cầu trong số đó. Khi thử lại các yêu cầu này, hãy giới hạn số lần thử lại. Ví dụ: mã của bạn có thể giới hạn mười lần thử lại, hoặc ít hơn trước khi báo cáo một lỗi.

  • Xử lý các lỗi 404 Not Found410 Gone khi thực hiện quá trình tải lên có thể tiếp tục, bằng cách khởi động lại toàn bộ quá trình tải lên từ đầu.

Thuật toán thời gian đợi luỹ thừa

Thuật toán thời gian đợi luỹ thừa là một chiến lược xử lý sai số chuẩn cho các ứng dụng mạng, trong đó ứng dụng thực hiện hoạt động thử lại định kỳ đối với một yêu cầu không thành công trong khoảng thời gian tăng dần. Nếu một lượng lớn các yêu cầu hoặc lưu lượng truy cập mạng lớn khiến máy chủ trả về lỗi, thì thuật toán thời gian đợi lũy thừa là một chiến lược tối ưu để xử lý những lỗi đó. Ngược lại, nó không phải là một chiến lược hữu ích khi cần xử lý các lỗi không liên quan đến lưu lượng truy cập mạng hoặc thời gian phản hồi, chẳng hạn như lỗi thông tin ủy quyền không hợp lệ hoặc lỗi không tìm thấy tệp.

Việc sử dụng thuật toán thời gian đợi lũy thừa đúng cách giúp tăng hiệu quả sử dụng băng thông, giảm số lượng yêu cầu cần thiết để có được phản hồi thành công, đồng thời tối đa hóa thông lượng yêu cầu trong các môi trường cùng lúc.

Quy trình triển khai thuật toán thời gian đợi lũy thừa đơn giản như sau:

  1. Tạo một yêu cầu đối với API.
  2. Nhận phản hồi HTTP 503, cho biết bạn nên thử lại yêu cầu.
  3. Đợi 1 giây + random_number_milliseconds rồi thử lại yêu cầu.
  4. Nhận phản hồi HTTP 503, cho biết bạn nên thử lại yêu cầu.
  5. Đợi 2 giây + random_number_milliseconds rồi thử lại yêu cầu.
  6. Nhận phản hồi HTTP 503, cho biết bạn nên thử lại yêu cầu.
  7. Đợi 4 giây + random_number_milliseconds rồi thử lại yêu cầu.
  8. Nhận HTTP 503 response, cho biết bạn nên thử lại yêu cầu.
  9. Đợi 8 giây + random_number_milliseconds rồi thử lại yêu cầu.
  10. Nhận HTTP 503 response, cho biết bạn nên thử lại yêu cầu.
  11. Đợi 16 giây + random_number_milliseconds rồi thử lại yêu cầu.
  12. Dừng. Báo cáo hoặc ghi lại một lỗi.

Trong danh sách trên, random_number_milliseconds là một số mili giây ngẫu nhiên nhỏ hơn hoặc bằng 1.000. Điều này cần thiết cho việc triển khai thời gian chờ ngắn ngẫu nhiên, giúp phân phối tải đồng đều hơn và tránh khả năng làm hỏng máy chủ. Giá trị của random_number_milliseconds phải được xác định lại sau mỗi lần chờ.

Thuật toán sẽ được đặt để kết thúc khi n là 5. Mức trần này ngăn ứng dụng thử lại vô hạn, dẫn đến việc tổng độ trễ khoảng 32 giây trước khi một yêu cầu được coi là "lỗi không thể khôi phục". Bạn có thể thử lại nhiều lần nhất có thể, đặc biệt khi quá trình tải trong thời gian dài đang diễn ra ; chỉ cần đảm bảo giới hạn độ trễ thử lại ở mức hợp lý, chẳng hạn như dưới một phút.

Hướng dẫn về thư viện ứng dụng API