E21 lỗi quạt ngăn đá tủ lạnh Samsung side by side https://appongtho.vn/nguyen-nhan-tu-lanh-samsung-bao-loi-e21 Lỗi E21 trên tủ lạnh Samsung thường là một trong những lỗi phổ biến mà người sử dụng...
Tệp mở rộng APK | Android Developers
Google Play nhu yếu tệp APK nén mà người dùng tải xuống không được có size trên 100 MB. Đối với hầu hết ứng dụng, kích cỡ này thừa đủ để chứa hàng loạt mã và gia tài của ứng dụng. Tuy nhiên, một số ít ứng dụng cần thêm khoảng trống cho tệp nội dung nghe nhìn, hình ảnh có độ chân thực cao, hoặc gia tài lớn khác. Trước đây, nếu kích cỡ tải xuống đã nén của ứng dụng vượt quá 100 MB, thì bạn phải tự lưu trữ và tải những tài nguyên bổ trợ xuống khi người dùng mở ứng dụng. Việc lưu trữ và phân phát những tệp thừa hoàn toàn có thể tốn ngân sách, và thưởng thức người dùng thường không được lý tưởng. Để giúp bạn thuận tiện thực thi quy trình này và người dùng có thưởng thức dễ chịu và thoải mái hơn, Google Play được cho phép bạn đính kèm 2 tệp mở rộng lớn bổ trợ cho tệp APK .
Google Play lưu trữ những tệp lan rộng ra cho ứng dụng và phân phối những tệp đó đến thiết bị mà không tính phí. Các tệp lan rộng ra được lưu vào vị trí bộ nhớ san sẻ của thiết bị ( thẻ SD hoặc phân vùng hoàn toàn có thể liên kết qua cổng USB ; còn gọi là bộ nhớ ” ngoài ” ) mà ứng dụng của bạn hoàn toàn có thể truy vấn. Trên hầu hết thiết bị, Google Play tải tệp lan rộng ra xuống cùng thời gian tải tệp APK xuống, để ứng dụng có mọi thông tin thiết yếu khi người dùng mở ứng dụng lần tiên phong. Tuy nhiên, trong 1 số ít trường hợp, ứng dụng phải tải tệp từ Google Play xuống khi ứng dụng khởi động .
Nếu muốn tránh sử dụng tệp lan rộng ra và size tải xuống đã nén của ứng dụng lớn hơn 100 MB, thì bạn nên tải ứng dụng lên bằng Android App Bundle ( được cho phép size tải xuống đã nén lên đến 150 MB ). Ngoài ra, do hoạt động giải trí sử dụng gói ứng dụng trì hoãn hoạt động giải trí việc tạo tệp APK và đăng nhập vào Google Play, nên người dùng chỉ tải những tệp APK được tối ưu hoá xuống trải qua mã và tài nguyên mà họ cần để chạy ứng dụng. Bạn không cần thiết kế xây dựng, ký và quản trị nhiều tệp APK hoặc tệp lan rộng ra, còn người dùng sẽ hoàn toàn có thể tải những tệp nhỏ hơn và được tối ưu hoá hơn xuống .
Tổng quan
Mỗi lần tải tệp APK lên bằng Google Play Console, bạn có thể thêm một hoặc hai tệp mở rộng vào tệp APK. Mỗi tệp có thể có dung lượng tối đa là 2 GB và có thể là bất kỳ định dạng nào bạn chọn, nhưng bạn nên sử dụng một tệp nén để tiết kiệm băng thông trong khi tải xuống.
Về mặt lý thuyết, mỗi tệp mở rộng đều đóng một vai trò riêng:
Bạn đang đọc: Tệp mở rộng APK | Android Developers
- Tệp mở rộng chính là dành cho các tài nguyên bổ sung mà ứng dụng của bạn yêu cầu.
- Tệp bản vá mở rộng là không bắt buộc và dành cho các bản cập nhật nhỏ trong tệp mở rộng chính.
Mặc dù bạn hoàn toàn có thể sử dụng hai tệp lan rộng ra này theo bất kể cách nào bạn muốn, nhưng tệp lan rộng ra chính nên phân phối gia tài chính và nên ít được update ; tệp bản vá lan rộng ra phải nhỏ hơn và đóng vai trò là ” trình cung ứng bản vá “, đồng thời được update sau mỗi bản phát hành chính hoặc nếu cần .
Tuy nhiên, ngay cả khi bản cập nhật ứng dụng chỉ yêu cầu tệp bản vá mở rộng mới, bạn vẫn phải tải một tệp APK mới có versionCode
đã cập nhật lên trong tệp kê khai. (Play Console không cho phép bạn tải tệp mở rộng lên một tệp APK hiện có.)
Lưu ý: Tệp bản vá mở rộng giống với tệp mở rộng chính về mặt ngữ nghĩa, bạn có thể sử dụng mỗi tệp theo bất kỳ cách nào mà bạn muốn.
Định dạng tên tệp
Mỗi tệp lan rộng ra bạn tải lên hoàn toàn có thể ở định dạng bất kể do bạn chọn ( ZIP, PDF, MP4, v.v. ). Bạn cũng hoàn toàn có thể sử dụng công cụ JOBB để đóng gói và mã hoá một tập hợp tệp tài nguyên và bản vá tiếp nối cho tập hợp đó. Bất kể loại tệp là gì, Google Play đều coi chúng là tệp opaque binary blob và đổi tên tệp bằng lược đồ sau :
[main|patch].. .obb
Có ba thành phần cho lược đồ này :
main
hoặcpatch
- Chỉ định tệp đó là tệp mở rộng chính hay tệp bản vá mở rộng. Mỗi tệp APK chỉ có thể có duy nhất một tệp chính và một tệp bản vá.
- Đây là một số nguyên khớp với mã phiên bản của tệp APK mà bản mở rộng được liên kết lần đầu tiên (số nguyên này khớp với giá trị
android:versionCode
của ứng dụng).
” Lần tiên phong ” được nhấn mạnh vấn đề vì mặc dầu Play Console được cho phép bạn sử dụng lại tệp lan rộng ra được tải lên bằng một tệp APK mới, nhưng tên của tệp lan rộng ra đó sẽ không đổi khác. Play Console giữ lại phiên bản được vận dụng vào lần tiên phong bạn tải tệp đó lên . - Tên gói kiểu Java của ứng dụng.
Ví dụ : giả sử phiên bản APK là 314159 và tên gói là com.example.app. Nếu bạn tải tệp lan rộng ra chính lên, tệp đó sẽ được đổi tên thành :
main.314159.com.example.app.obb
Vị trí bộ nhớ
Khi tải tệp lan rộng ra xuống thiết bị, Google Play sẽ lưu những tệp đó vào vị trí bộ nhớ dùng chung của mạng lưới hệ thống. Để bảo vệ hoạt động giải trí thông thường, bạn không được xoá, vận động và di chuyển hoặc đổi tên tệp lan rộng ra. Trong trường hợp ứng dụng phải tự tải xuống qua Google Play, bạn phải lưu những tệp vào đúng vị trí đó .
Phương thức getObbDir()
trả về vị trí cụ thể cho các tệp mở rộng ở dạng sau:
/Android/obb/ /
là đường dẫn đến không gian lưu trữ dùng chung, lấy từgetExternalStorageDirectory()
.
là tên gói kiểu Java của ứng dụng, lấy từgetPackageName()
.
Đối với mỗi ứng dụng, thư mục này không bao giờ có nhiều hơn hai tệp mở rộng.
Một tệp mở rộng chính và một tệp bản vá mở rộng (nếu cần). Các phiên bản trước đó sẽ bị ghi đè khi bạn cập nhật ứng dụng bằng các tệp mở rộng mới. Kể từ Android 4.4 (API cấp 19), ứng dụng có thể đọc tệp mở rộng OBB
mà không cần quyền truy cập vào bộ nhớ ngoài. Tuy nhiên, một số quy trình triển khai Android 6.0 (API cấp 23) trở lên vẫn yêu cầu quyền nên bạn cần khai báo quyền READ_EXTERNAL_STORAGE
trong tệp kê khai ứng dụng và yêu cầu quyền trong thời gian chạy như sau:
Đối với Android phiên bản 6 trở lên, bạn cần nhu yếu quyền truy vấn vào bộ nhớ ngoài trong thời hạn chạy. Tuy nhiên, 1 số ít quy trình tiến độ tiến hành của Android không nhu yếu quyền đọc tệp OBB. Đoạn mã sau đây cho biết cách kiểm tra quyền đọc trước khi nhu yếu quyền truy vấn vào bộ nhớ ngoài :
Kotlin
val obb = File(obb_filename) var open_failed = false try { BufferedReader(FileReader(obb)).also { br -> ReadObbFile(br) } } catch (e: IOException) { open_failed = true } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission() }
Java
File obb = new File(obb_filename); boolean open_failed = false; try { BufferedReader br = new BufferedReader(new FileReader(obb)); open_failed = false; ReadObbFile(br); } catch (IOException e) { open_failed = true; } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission(); }
Nếu bạn phải giải nén nội dung của các tệp mở rộng, đừng xoá các tệp mở rộng OBB
sau đó và đừng lưu dữ liệu đã giải nén trong cùng một thư mục. Bạn nên lưu các tệp đã giải nén vào thư mục do getExternalFilesDir()
chỉ định. Tuy nhiên, nếu có thể, tốt nhất bạn nên sử dụng định dạng tệp mở rộng cho phép bạn đọc tệp trực tiếp thay vì yêu cầu bạn giải nén dữ liệu. Ví dụ: chúng tôi đã cung cấp một dự án thư viện tên là Thư viện zip tệp mở rộng APK. Thư viện này đọc dữ liệu trực tiếp trên tệp ZIP.
Thận trọng: Không giống như tệp APK, người dùng và các ứng dụng khác có thể đọc mọi tệp đã lưu trong vị trí bộ nhớ dùng chung.
Mẹo: Nếu đang đóng gói các tệp nội dung nghe nhìn vào một tệp ZIP thì bạn có thể sử dụng lệnh gọi playback (phát) nội dung nghe nhìn trên các tệp đó kèm theo các tuỳ chọn điều khiển độ lệch và thời lượng (chẳng hạn như MediaPlayer.setDataSource()
và SoundPool.load()
) mà không cần giải nén tệp ZIP. Để làm được việc này, bạn không được nén các tệp nội dung nghe nhìn thêm một lần nữa khi tạo các gói ZIP. Ví dụ: khi sử dụng công cụ zip
, bạn nên sử dụng tuỳ chọn -n
để chỉ định hậu tố tệp không nên nén:
zip -n .mp4;.ogg main_expansion media_files
Quá trình tải xuống
Trong hầu hết những trường hợp, Google Play tải và lưu những tệp lan rộng ra ở cùng thời gian tải tệp APK xuống thiết bị. Tuy nhiên, trong một số ít trường hợp, Google Play không tải được tệp lan rộng ra xuống hoặc người dùng hoàn toàn có thể đã xoá tệp lan rộng ra đã tải xuống trước đó. Để giải quyết và xử lý những trường hợp này, ứng dụng phải có năng lực tự tải tệp xuống khi hoạt động giải trí chính mở màn, bằng cách sử dụng URL do Google Play cung ứng .
Quá trình tải xuống từ cấp cao sẽ diễn ra như sau :
- Người dùng chọn cài đặt ứng dụng của bạn qua Google Play.
- Nếu có thể tải các tệp mở rộng xuống (trường hợp này xảy ra đối với hầu hết các thiết bị) thì Google Play sẽ tải chúng xuống cùng với APK.
Nếu không hề tải những tệp lan rộng ra xuống thì Google Play sẽ chỉ tải tệp APK xuống . - Khi người dùng chạy ứng dụng của bạn, ứng dụng phải kiểm tra xem tệp mở rộng đã được lưu trên thiết bị hay chưa.
- Nếu rồi thì ứng dụng đã sẵn sàng hoạt động.
- Nếu chưa thì ứng dụng phải tải các tệp mở rộng xuống qua HTTP trên Google Play. Ứng dụng phải gửi yêu cầu đến ứng dụng Google Play qua dịch vụ Cấp phép cho ứng dụng của Google Play. Dịch vụ này trả về tên, kích thước tệp và URL của từng tệp mở rộng. Với thông tin này, bạn sẽ tải các tệp xuống và lưu vào vị trí bộ nhớ thích hợp.
Thận trọng: Điều quan trọng là bạn phải bao gồm mã cần thiết để tải tệp mở rộng xuống từ Google Play trong trường hợp tệp chưa có trên thiết bị khi ứng dụng khởi động. Như đã thảo luận trong phần sau đây về việc Tải tệp mở rộng xuống, chúng tôi cung cấp một thư viện giúp bạn đơn giản hoá quá trình này và thực hiện tải xuống qua một dịch vụ bằng lượng mã tối thiểu.
Danh sách kiểm thử quá trình phát triển
Sau đây là phần tóm tắt về những việc bạn nên làm để sử dụng tệp lan rộng ra trên ứng dụng của mình :
- Trước tiên, hãy xác định xem kích thước tải xuống đã nén của ứng dụng có lớn hơn 100 MB hay không.
Không gian lưu trữ rất quý giá và bạn nên giữ cho tổng kích thước tải xuống càng nhỏ càng tốt. Nếu ứng dụng sử dụng hơn 100 MB để cung cấp nhiều phiên bản thành phần đồ hoạ cho nhiều mật độ màn hình, hãy cân nhắc phát hành nhiều APK, trong đó mỗi APK chỉ chứa các thành phần cần thiết cho màn hình mà ứng dụng nhắm mục tiêu. Để có kết quả phù hợp nhất khi phát hành trên Google Play, hãy tải Android App Bundle lên, trong đó có tất cả tài nguyên và mã đã biên dịch của ứng dụng, nhưng trì hoãn quá trình tạo APK và đăng nhập vào Google Play. - Xác định tài nguyên ứng dụng nào cần tách khỏi tệp APK và đóng gói chúng trong một tệp để sử dụng làm tệp mở rộng chính.
Thường thì bạn chỉ nên sử dụng tệp bản vá lan rộng ra thứ hai khi triển khai update cho tệp lan rộng ra chính. Tuy nhiên, nếu tài nguyên vượt quá số lượng giới hạn 2 GB cho tệp lan rộng ra chính, thì bạn hoàn toàn có thể sử dụng tệp bản vá cho những gia tài còn lại . - Phát triển ứng dụng để ứng dụng đó sử dụng các tài nguyên trên tệp mở rộng trong vị trí bộ nhớ dùng chung của thiết bị.
Đừng quên rằng bạn không được xoá, chuyển dời hoặc đổi tên tệp lan rộng ra .
Nếu ứng dụng của bạn không nhu yếu định dạng đơn cử, bạn nên tạo tệp ZIP cho những tệp lan rộng ra, sau đó đọc những tệp này bằng Thư viện zip lan rộng ra APK . - Thêm logic vào hoạt động chính của ứng dụng để kiểm tra xem các tệp mở rộng có ở trên thiết bị khi khởi động hay không. Nếu các tệp không có trên thiết bị, hãy sử dụng dịch vụ Cấp phép ứng dụng của Google Play để yêu cầu URL cho các tệp mở rộng, sau đó tải xuống và lưu lại các tệp đó.
Để giảm lượng lớn những mã cần viết và bảo vệ mang lại thưởng thức tốt cho người dùng trong quy trình tải xuống, bạn nên sử dụng Thư viện trình tải xuống để thực thi hoạt động giải trí tải xuống .
Nếu tự kiến thiết xây dựng dịch vụ tải xuống thay vì sử dụng thư viện, hãy chú ý quan tâm rằng bạn không được biến hóa tên của những tệp lan rộng ra và phải lưu chúng vào vị trí bộ nhớ tương thích .
Sau khi bạn hoàn tất quy trình tăng trưởng ứng dụng, hãy làm theo hướng dẫn để Kiểm thử tệp lan rộng ra .
Quy tắc và giới hạn
Thêm những tệp lan rộng ra APK là tính năng được cung ứng khi bạn tải ứng dụng lên bằng Play Console. Trong lần tiên phong tải ứng dụng lên hoặc update một ứng dụng sử dụng tệp lan rộng ra, bạn phải chú ý quan tâm những quy tắc và số lượng giới hạn sau :
- Mỗi tệp mở rộng không được vượt quá 2 GB.
- Để tải các tệp mở rộng của bạn xuống từ Google Play, người dùng phải mua ứng dụng của bạn từ Google Play. Google Play sẽ không cung cấp URL cho các tệp mở rộng nếu ứng dụng được cài đặt bằng các phương pháp khác.
- Khi tải xuống từ ứng dụng của bạn, URL mà Google Play cung cấp cho từng tệp là duy nhất cho mỗi lần tải xuống và mỗi URL sẽ hết hạn ngay sau khi được cấp cho ứng dụng của bạn.
- Nếu cập nhật ứng dụng bằng một APK mới hoặc tải nhiều APK lên cho cùng một
ứng dụng, bạn có thể chọn các tệp mở rộng được tải lên cho APK trước đó. Tên của tệp mở rộng không thay đổi – tên này giữ lại phiên bản nhận được từ APK liên kết từ đầu. - Nếu sử dụng tệp mở rộng kết hợp với nhiều APK để
cung cấp các tệp mở rộng khác nhau cho thiết bị khác nhau, bạn vẫn phải tải các APK riêng biệt lên cho từng thiết bị để cung cấp một giá trịversionCode
và khai báo các bộ lọc khác nhau cho
mỗi APK. - Bạn không thể phát hành bản cập nhật cho ứng dụng bằng cách chỉ thay đổi các tệp mở rộng – bạn phải tải APK mới lên để cập nhật ứng dụng. Nếu nội dung thay đổi chỉ liên quan đến các tài sản trong tệp mở rộng, bạn có thể cập nhật APK chỉ bằng cách thay đổi
versionCode
(và cũng có thể làversionName
). - Không lưu dữ liệu khác vào thư mục
obb/
của bạn. Nếu bạn phải giải nén một số dữ liệu, hãy lưu dữ liệu đó vào vị trí màgetExternalFilesDir()
chỉ định. - Không xoá hoặc đổi tên tệp mở rộng
.obb
(trừ khi bạn
đang cập nhật). Làm vậy có thể khiến Google Play (hoặc chính ứng dụng của bạn) tải tệp mở rộng xuống nhiều lần. - Khi cập nhật tệp mở rộng theo cách thủ công, bạn phải xoá tệp mở rộng trước đó.
Tải tệp mở rộng xuống
Trong hầu hết trường hợp, Google Play sẽ tải xuống và lưu những tệp lan rộng ra của bạn về thiết bị tại cùng thời gian setup hoặc update APK. Bằng cách này, những tệp lan rộng ra sẽ sẵn có khi ứng dụng của bạn khởi chạy lần tiên phong. Tuy nhiên, trong 1 số ít trường hợp, ứng dụng phải tải những tệp lan rộng ra xuống bằng cách nhu yếu những tệp đó từ một URL được cung ứng cho bạn trong một phản hồi từ dịch vụ Cấp phép ứng dụng của Google Play .
Logic cơ bản mà bạn cần để tải những tệp lan rộng ra xuống là :
- Khi ứng dụng của bạn khởi động, hãy tìm các tệp mở rộng trên vị trí bộ nhớ dùng chung (trong
thư mụcAndroid/obb/
)./ - Nếu các tệp mở rộng có trong bộ nhớ đó thì bạn đã hoàn thành các bước cần thiết và ứng dụng của bạn có thể tiếp tục.
- Nếu tệp mở rộng không có trong bộ nhớ đó:
- Hãy yêu cầu bằng cách sử dụng dịch vụ Cấp phép ứng dụng của Google Play để có được URL, các kích thước và tên tệp mở rộng của ứng dụng.
- Sử dụng các URL mà Google Play cung cấp để tải các tệp mở rộng xuống và lưu
chúng. Bạn phải lưu tệp vào vị trí bộ nhớ dùng chung
(Android/obb/
) và sử dụng đúng tên tệp/
theo phản hồi của Google Play.Lưu ý: URL mà Google Play cung cấp cho
các tệp mở rộng là duy nhất cho mỗi lượt tải xuống và mỗi URL sẽ hết hạn ngay sau khi được cấp cho
ứng dụng của bạn.
Nếu ứng dụng của bạn không lấy phí ( không phải là ứng dụng có tính phí ) thì hoàn toàn có thể bạn chưa sử dụng dịch vụ Cấp phép ứng dụng. Dịch Vụ Thương Mại này đa phần được phong cách thiết kế để bạn thực thi những chủ trương cấp phép cho ứng dụng của mình và bảo vệ rằng người dùng có quyền sử dụng ứng dụng của bạn ( anh ấy hoặc cô ấy đã giao dịch thanh toán chính đáng cho ứng dụng trên Google Play ). Để tạo điều kiện kèm theo cho tính năng tệp lan rộng ra, dịch vụ cấp phép đã được tăng cấp để cung ứng phản hồi cho ứng dụng của bạn, gồm có URL của những tệp lan rộng ra của ứng dụng được lưu trữ trên Google Play. Vì vậy, ngay cả khi ứng dụng của bạn không tính tiền so với người dùng, bạn vẫn cần phải gồm có cả Thư viện xác định giấy phép ( LVL ) để sử dụng những tệp lan rộng ra APK. Tất nhiên, nếu ứng dụng của bạn không lấy phí, bạn không cần xác định giấy phép mà chỉ cần thư viện triển khai nhu yếu trả về URL của những tệp lan rộng ra .
Lưu ý: Cho dù ứng dụng của bạn miễn phí hay không, Google Play
chỉ trả về URL tệp mở rộng nếu người dùng đã mua ứng dụng của bạn từ Google Play.
Ngoài LVL, bạn cần một bộ mã tải những tệp lan rộng ra xuống qua liên kết HTTP và lưu những tệp đó vào vị trí thích hợp trên bộ nhớ san sẻ của thiết bị. Khi kiến thiết xây dựng tiến trình này trong ứng dụng, bạn nên quan tâm 1 số ít yếu tố sau :
- Thiết bị có thể không có đủ dung lượng cho các tệp mở rộng, vì vậy, bạn nên kiểm tra trước khi bắt đầu tải xuống và cảnh báo người dùng nếu không có đủ dung lượng.
- Việc tải tệp xuống nên diễn ra trong một dịch vụ nền để tránh chặn tương tác của người dùng
và cho phép họ rời khỏi ứng dụng trong khi thực hiện quá trình tải xuống. - Bạn phải xử lý một cách thoả đáng nhiều lỗi có thể xảy ra trong quá trình yêu cầu và tải xuống.
- Kết nối mạng có thể thay đổi trong quá trình tải xuống, vì vậy, bạn nên xử lý những điều thay đổi đó và
nếu bị gián đoạn, hãy tiếp tục tải xuống khi có thể. - Mặc dù quá trình tải xuống diễn ra trong chế độ nền, bạn nên cung cấp một thông báo
về tiến trình tải xuống, thông báo cho người dùng khi quá trình tải xuống hoàn tất và đưa họ trở lại
ứng dụng của bạn khi được chọn.
Để đơn giản hoá việc làm này cho bạn, chúng tôi đã thiết kế xây dựng Thư viện trình tải xuống. Thư viện này nhu yếu URL của tệp lan rộng ra trải qua dịch vụ cấp phép, tải tệp lan rộng ra xuống, triển khai tổng thể tác vụ được liệt kê bên trên và thậm chí còn được cho phép bạn tạm dừng hoạt động giải trí và liên tục tải xuống. Bằng cách thêm Thư viện trình tải xuống và một phần móc của mã vào ứng dụng, hầu hết tổng thể việc làm tải những tệp lan rộng ra đã được mã hoá xuống cho bạn. Do đó, để thay bạn cung ứng thưởng thức người dùng tốt nhất mà không tốn nhiều công sức của con người, bạn nên sử dụng Thư viện trình tải xuống để tải tệp lan rộng ra xuống. Thông tin trong những phần sau lý giải cách tích hợp thư viện vào ứng dụng .
Nếu bạn muốn phát triển giải pháp riêng để tải các tệp mở rộng xuống thông qua các URL Google Play, bạn phải làm theo tài liệu Cấp phép ứng dụng để thực hiện yêu cầu cấp phép, sau đó truy xuất các url, kích thước và tên tệp mở rộng phần bổ sung phản hồi. Bạn nên sử dụng lớp APKExpansionPolicy
(có trong Thư viện xác minh giấy phép) làm chính sách
cấp phép, trong đó ghi lại các URL, kích thước và tên tệp mở rộng từ dịch vụ cấp phép.
Giới thiệu về Thư viện trình tải xuống
Để thay bạn sử dụng những tệp lan rộng ra APK với ứng dụng và phân phối thưởng thức người dùng tốt nhất mà không tốn nhiều công sức của con người, bạn nên sử dụng Thư viện trình tải xuống có trong gói Thư viện lan rộng ra APK Google Play. Thư viện này tải những tệp lan rộng ra của bạn xuống trong dịch vụ nền, hiển thị thông tin cho người dùng về trạng thái tải xuống, giải quyết và xử lý thực trạng mất liên kết mạng, liên tục tải xuống khi hoàn toàn có thể và nhiều tính năng khác .
Để tiến hành quy trình tải tệp lan rộng ra xuống bằng Thư viện trình tải xuống, bạn chỉ cần :
- Mở rộng một lớp con
Service
đặc biệt và lớp conBroadcastReceiver
, mỗi lớp chỉ yêu cầu bạn
nhập một vài dòng mã. - Thêm một số logic vào hoạt động chính để kiểm tra xem các tệp mở rộng đã được tải xuống
hay chưa, và nếu chưa, gọi quy trình tải xuống và hiển thị
giao diện người dùng tiến trình. - Triển khai giao diện gọi lại với một vài phương thức trong hoạt động chính để nhận cập nhật về tiến trình tải xuống.
Các phần sau lý giải cách thiết lập ứng dụng bằng Thư viện trình tải xuống .
Chuẩn bị sử dụng Thư viện trình tải xuống
Để sử dụng Thư viện trình tải xuống, bạn cần tải hai gói xuống từ Trình quản trị SDK và thêm những thư viện tương thích vào ứng dụng .
Trước tiên, hãy mở Trình quản lý SDK Android
(Tools > SDK Manager)(Công cụ > Trình quản lý SDK) và trong mục
Appearance & Behavior > System Settings > Android SDK (Giao diện và hành vi > Cài đặt hệ thống > SDK Android), chọn
thẻ SDK Tools (Công cụ SDK) để chọn và tải xuống:
- Gói Thư viện cấp phép của Google Play
- Gói Thư viện mở rộng APK Google Play
Tạo một mô-đun thư viện mới cho Thư viện xác định giấy phép và Thư viện trình tải xuống. Với mỗi thư viện :
- Chọn File > New > New Module (Tệp > Mới > Mô-đun mới).
- Trong cửa sổ Tạo mô-đun mới, hãy chọn Android Library, (Thư viện Android)
rồi chọn Next (Tiếp theo). - Chỉ định tên ứng dụng/Thư viện như “Thư viện giấy phép Google Play”
và “Thư viện trình tải xuống Google Play”, chọn cấp SDK tối thiểu, rồi chọn
Finish (Hoàn tất). - Chọn File > Project Structure (Tệp > Cấu trúc dự án).
- Chọn tab Thuộc tính và trong Kho lưu trữ
thư viện, hãy nhập thư viện từ thư mục/extras/google/
(play_licensing/
cho Thư viện xác minh giấy phép hoặcplay_apk_expansion/downloader_library/
cho Thư viện trình tải xuống). - Chọn OK để tạo mô-đun mới.
Lưu ý: Thư viện trình tải xuống phụ thuộc vào Thư viện xác minh giấy phép. Hãy nhớ thêm Thư viện xác minh giấy phép vào thuộc tính dự án của Thư viện trình tải xuống.
Hoặc trên một dòng lệnh, hãy update dự án Bất Động Sản của bạn để gồm có những thư viện :
- Thay đổi các thư mục thành thư mục
./tools/ - Thực thi
android update project
bằng tuỳ chọn--library
để thêm cả
LVL và Thư viện trình tải xuống vào dự án. Ví dụ:android update project --path ~/Android/MyApp \ --library ~/android_sdk/extras/google/market_licensing \ --library ~/android_sdk/extras/google/market_apk_expansion/downloader_library
Khi thêm cả Thư viện xác định giấy phép và Thư viện trình tải xuống vào ứng dụng, bạn sẽ hoàn toàn có thể nhanh gọn tích hợp năng lực tải những tệp lan rộng ra xuống từ Google Play. Định dạng mà bạn chọn cho những tệp lan rộng ra và cách bạn đọc chúng từ bộ nhớ dùng chung là hoạt động giải trí thực thi riêng mà bạn nên xem xét dựa trên nhu yếu của ứng dụng .
Mẹo: Gói mở rộng Apk bao gồm một ứng dụng mẫu cho biết cách sử dụng Thư viện trình tải xuống trong một ứng dụng. Ứng dụng mẫu này sử dụng một thư viện thứ ba có sẵn trong gói Mở rộng Apk có tên là Thư viện ZIP mở rộng APK. Nếu định sử dụng các tệp ZIP cho tệp mở rộng, bạn nên thêm Thư viện mã mở rộng APK vào ứng dụng của mình. Để biết thêm thông tin, hãy xem phần bên dưới về cách sử dụng Thư viện Zip mở rộng APK.
Khai báo sự cho phép của người dùng
Để tải những tệp lan rộng ra xuống, Thư viện trình tải xuống cần có 1 số ít quyền mà bạn phải khai báo trong tệp kê khai của ứng dụng. Các quyền như sau :
...
Lưu ý: Theo mặc định, Thư viện trình tải xuống yêu cầu API cấp 4, nhưng Thư viện zip mở rộng APK yêu cầu API cấp 5.
Triển khai dịch vụ trình tải xuống
Để thực hiện việc tải xuống trong nền, Thư viện trình tải xuống cung cấp
lớp con Service
riêng, gọi là DownloaderService
mà bạn nên mở rộng. Ngoài việc tải các tệp mở rộng xuống cho bạn, DownloaderService
cũng:
- Đăng ký một
BroadcastReceiver
để theo dõi các thay đổi kết nối mạng của thiết bị (truyền phátCONNECTIVITY_ACTION
) để tạm dừng việc tải xuống khi cần (chẳng hạn như do mất kết nối) và tiếp tục tải xuống khi có thể (có kết nối). - Lên lịch chuông báo
RTC_WAKEUP
để thử tải xuống lại
đối với các trường hợp dịch vụ bị ngừng. - Xây dựng một
Notification
tuỳ chỉnh hiển thị tiến trình tải xuống và
bất cứ lỗi hoặc thay đổi trạng thái nào. - Cho phép ứng dụng tạm dừng và tiếp tục quá trình tải xuống theo cách thủ công.
- Xác minh rằng bộ nhớ dùng chung đã được gắn và sẵn có, các tệp chưa tồn tại, và có đủ dung lượng trước khi tải tệp mở rộng xuống. Sau đó, hãy thông báo cho người dùng
nếu có bất kỳ thông tin nào trong đó không chính xác.
Bạn chỉ cần tạo một lớp trong ứng dụng sẽ mở rộng lớp DownloaderService
và ghi đè ba phương pháp cung cấp thông tin chi tiết về ứng dụng:
getPublicKey()
- Hàm này phải trả về một chuỗi là khoá công khai RSA được mã hoá Base64 cho tài khoản
nhà xuất bản của bạn, sẵn có từ trang hồ sơ trên Play Console (xem phần Cài đặt để cấp phép). getSALT()
- Hàm này phải trả về một mảng các byte ngẫu nhiên mà
Policy
cấp phép sử dụng để tạo mộtObfuscator
. Dữ liệu ngẫu nhiên đảm bảo rằng tệpSharedPreferences
được làm rối có chứa dữ liệu cấp phép của bạn sẽ là tệp duy nhất và không thể phát hiện. getAlarmReceiverClassName()
- Hàm này phải trả về tên lớp của
BroadcastReceiver
trong ứng dụng sẽ nhận được thông báo cho biết cần bắt đầu lại quá trình tải xuống (có thể xảy ra nếu dịch vụ tải xuống dừng đột ngột).
Ví dụ: sau đây là quá trình thực thi DownloaderService
đầy đủ:
Kotlin
// You must use the public key belonging to your publisher account const val BASE64_PUBLIC_KEY = "YourLVLKey" // You should also modify this salt val SALT = byteArrayOf( 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 ) class SampleDownloaderService : DownloaderService() { override fun getPublicKey(): String = BASE64_PUBLIC_KEY override fun getSALT(): ByteArray = SALT override fun getAlarmReceiverClassName(): String = SampleAlarmReceiver::class.java.name }
Java
public class SampleDownloaderService extends DownloaderService { // You must use the public key belonging to your publisher account public static final String BASE64_PUBLIC_KEY = "YourLVLKey"; // You should also modify this salt public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 }; @Override public String getPublicKey() { return BASE64_PUBLIC_KEY; } @Override public byte[] getSALT() { return SALT; } @Override public String getAlarmReceiverClassName() { return SampleAlarmReceiver.class.getName(); } }
Lưu ý: Bạn phải cập nhật giá trị BASE64_PUBLIC_KEY
thành khoá công khai thuộc về tài khoản nhà xuất bản của bạn. Bạn có thể tìm thấy khoá trong Play Console trong mục thông tin hồ sơ của mình. Điều này cần thiết ngay cả khi bạn kiểm thử các tệp tải xuống của mình.
Hãy nhớ khai báo dịch vụ trong tệp kê khai :
...
Triển khai trình nhận thông báo
Để theo dõi tiến trình tải tệp xuống và khởi động lại quá trình tải xuống nếu cần, DownloaderService
sẽ lập lịch biểu cho một thông báo RTC_WAKEUP
để cung cấp một Intent
cho một BroadcastReceiver
trong ứng dụng của bạn. Bạn phải thiết lập BroadcastReceiver
để gọi API từ Thư viện trình tải xuống nhằm kiểm tra trạng thái của tệp tải xuống và khởi động lại quá trình tải xuống nếu cần.
Bạn chỉ cần ghi đè phương thức onReceive()
để gọi DownloaderClientMarshaller.startDownloadServiceIfRequired()
.
Ví dụ :
Kotlin
class SampleAlarmReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired( context, intent, SampleDownloaderService::class.java ) } catch (e: PackageManager.NameNotFoundException) { e.printStackTrace() } } }
Java
public class SampleAlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, SampleDownloaderService.class); } catch (NameNotFoundException e) { e.printStackTrace(); } } }
Lưu ý rằng đây là lớp mà bạn phải trả tên về
trong phương thức getAlarmReceiverClassName()
của dịch vụ (xem mục trước).
Hãy nhớ khai báo trình nhận trong tệp kê khai :
...
Bắt đầu tiến trình tải xuống
Hoạt động chính trong ứng dụng của bạn ( hoạt động giải trí được hình tượng trình chạy mở màn ) chịu nghĩa vụ và trách nhiệm xác định xem những tệp lan rộng ra đã có trên thiết bị hay chưa và mở màn tải xuống nếu chưa có .
Cần triển khai những quá trình sau để khởi đầu tải xuống bằng Thư viện trình tải xuống :
- Kiểm tra xem tệp đã được tải xuống hay chưa.
Thư viện trình tải xuống bao gồm một số API trong lớp
Helper
để
hỗ trợ quá trình này:getExpansionAPKFileName(Context, c, boolean mainFile, int
versionCode)doesFileExist(Context c, String fileName, long fileSize)
Ví dụ: ứng dụng mẫu được cung cấp trong gói Mở rộng Apk sẽ gọi
phương thức sau trong phương thứconCreate()
của hoạt động để kiểm tra xem
các tệp mở rộng có trên thiết bị hay chưa:Kotlin
fun expansionFilesDelivered(): Boolean { xAPKS.forEach { xf -> Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion).also { fileName -> if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false } } return true }
Java
boolean expansionFilesDelivered() { for (XAPKFile xf : xAPKS) { String fileName = Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion); if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false; } return true; }
Trong trường hợp này, mỗi đối tượng
XAPKFile
chứa số phiên bản và kích thước tệp của một tệp mở rộng đã biết và một giá trị boolean để xem tệp có phải là tệp mở rộng chính hay không. (Hãy xem lớp
SampleDownloaderActivity
của ứng dụng mẫu để biết thông tin chi tiết).Nếu phương pháp này trả về giá trị là false thì ứng dụng phải khởi đầu tải xuống .
- Bắt đầu tải xuống bằng cách gọi phương thức tĩnh
DownloaderClientMarshaller.startDownloadServiceIfRequired(Context c, PendingIntent
.
notificationClient, Class > serviceClass)
Phương thức này sẽ lấy những thông số kỹ thuật sau :context
:Context
của ứng dụng của bạn.notificationClient
: MộtPendingIntent
để bắt đầu hoạt động chính. Tệp này được dùng trongNotification
màDownloaderService
tạo để hiển thị tiến trình tải xuống. Khi người dùng chọn thông báo, hệ thống
sẽ gọiPendingIntent
bạn cung cấp tại đây và mở hoạt động
cho thấy tiến trình tải xuống (thường là cùng hoạt động đã bắt đầu quá trình tải xuống).serviceClass
: Đối tượngClass
để triển khai
DownloaderService
bắt buộc phải khởi động dịch vụ và bắt đầu tải xuống nếu cần.
Phương thức này trả về 1 số ít nguyên cho biết liệu người dùng có cần phải tải xuống hay không. Các giá trị hoàn toàn có thể là :
NO_DOWNLOAD_REQUIRED
: Được trả về nếu các tệp đã tồn tại hoặc đã đang được tải xuống.LVL_CHECK_REQUIRED
: Được trả về nếu cần xác minh giấy phép để lấy các URL của tệp mở rộng.DOWNLOAD_REQUIRED
: Được trả về nếu đã biết các URL của tệp mở rộng, nhưng chưa tải các tệp xuống.
Hành vi của
LVL_CHECK_REQUIRED
vàDOWNLOAD_REQUIRED
về cơ bản là giống nhau và thường bạn không cần lo ngại về các hành vi này. Trong hoạt động chính của bạn có chức năng gọistartDownloadServiceIfRequired()
, bạn chỉ cần kiểm tra xem phản hồi có phải làNO_DOWNLOAD_REQUIRED
hay không. Nếu phản hồi không phải làNO_DOWNLOAD_REQUIRED
, Thư viện trình tải xuống sẽ bắt đầu tải xuống và bạn nên cập nhật giao diện người dùng hoạt động của mình để
hiển thị tiến trình tải xuống (xem bước tiếp theo). Nếu phản hồi làNO_DOWNLOAD_REQUIRED
, các tệp sẽ sẵn có và ứng dụng của bạn có thể khởi động.Ví dụ :
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { val pendingIntent = // Build an Intent to start this activity from the Notification Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP }.let { notifierIntent -> PendingIntent.getActivity( this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT ) } // Start the download service (if required) val startResult: Int = DownloaderClientMarshaller.startDownloadServiceIfRequired( this, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return } // If the download wasn't necessary, fall through to start the app } startApp() // Expansion files are available, start the app }
Java
@Override public void onCreate(Bundle savedInstanceState) { // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { // Build an Intent to start this activity from the Notification Intent notifierIntent = new Intent(this, MainActivity.getClass()); notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); ... PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return; } // If the download wasn't necessary, fall through to start the app } startApp(); // Expansion files are available, start the app }
- Khi phương thức
startDownloadServiceIfRequired()
trả về bất cứ nội dung gì không phải làNO_DOWNLOAD_REQUIRED
, hãy tạo một bản sao củaIStub
bằng cách gọiDownloaderClientMarshaller.CreateStub(IDownloaderClient client, Class >
.
downloaderService)IStub
liên kết hoạt động của bạn với dịch vụ trình tải xuống
để hoạt động của bạn nhận lệnh gọi lại về tiến trình tải xuống.Để tạo bản sao
IStub
bằng cách gọi hàmCreateStub()
, bạn phải chuyển một hoạt động triển khai của
giao diệnIDownloaderClient
và hoạt động triển khaiDownloaderService
cho hàm. Phần tiếp theo về Nhận tiến trình tải xuống thảo luận về
giao diệnIDownloaderClient
mà bạn thường nên triển khai trong lớpActivity
để có thể cập nhật giao diện người dùng hoạt động khi trạng thái tải xuống thay đổi.Chúng tôi khuyến nghị bạn nên gọi
CreateStub()
để tạo bảo saoIStub
trong phương thứconCreate()
của hoạt động sau khistartDownloadServiceIfRequired()
bắt đầu tải xuống.Ví dụ: trong mã mẫu trước đó của
onCreate()
, bạn có thể phản hồi kết quảstartDownloadServiceIfRequired()
như sau:Kotlin
// Start the download service (if required) val startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( this@MainActivity, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService::class.java) // Inflate layout that shows download progress setContentView(R.layout.downloader_ui) return }
Java
// Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService.class); // Inflate layout that shows download progress setContentView(R.layout.downloader_ui); return; }
Sau khi phương thức
onCreate()
trả về, hoạt động
của bạn sẽ nhận được một lệnh gọi tớionResume()
, đây là nơi bạn nên
gọiconnect()
trênIStub
, truyền hoạt động đó đếnContext
của ứng dụng của bạn. Ngược lại, bạn nên gọi
disconnect()
trong lệnh gọi lạionStop()
của hoạt động.Kotlin
override fun onResume() { downloaderClientStub?.connect(this) super.onResume() } override fun onStop() { downloaderClientStub?.disconnect(this) super.onStop() }
Java
@Override protected void onResume() { if (null != downloaderClientStub) { downloaderClientStub.connect(this); } super.onResume(); } @Override protected void onStop() { if (null != downloaderClientStub) { downloaderClientStub.disconnect(this); } super.onStop(); }
Việc gọi hàm
connect()
trênIStub
sẽ liên kết hoạt động của bạn vớiDownloaderService
, hoạt động của bạn sẽ nhận được lệnh gọi lại liên quan đến các thay đổi trạng thái tải xuống
thông qua giao diệnIDownloaderClient
.
Đang nhận tiến trình tải xuống
Để nhận thông tin cập nhật về tiến trình tải xuống và tương tác với DownloaderService
, bạn phải triển khai giao diện IDownloaderClient
của Thư viện trình tải xuống.
Thông thường, hoạt động bạn sử dụng để bắt đầu tải xuống sẽ triển khai giao diện này để hiển thị tiến trình tải xuống và gửi yêu cầu đến dịch vụ.
Các phương thức thuộc giao diện bắt buộc cho IDownloaderClient
là:
onServiceConnected(Messenger m)
- Sau khi tạo bản sao
IStub
trong hoạt động, bạn sẽ nhận được một lệnh gọi đến phương thức này, lệnh này sẽ chuyển một đối tượngMessenger
được kết nối với bản sao củaDownloaderService
. Để gửi các yêu cầu đến dịch vụ, chẳng hạn như tạm dừng và tiếp tục
tải xuống, bạn phải gọi hàmDownloaderServiceMarshaller.CreateProxy()
để nhận giao diệnIDownloaderService
được kết nối với dịch vụ.
Cách tiến hành được khuyến nghị như sau :Kotlin
private var remoteService: IDownloaderService? = null ... override fun onServiceConnected(m: Messenger) { remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { downloaderClientStub?.messenger?.also { messenger -> onClientUpdated(messenger) } } }
Java
private IDownloaderService remoteService; ... @Override public void onServiceConnected(Messenger m) { remoteService = DownloaderServiceMarshaller.CreateProxy(m); remoteService.onClientUpdated(downloaderClientStub.getMessenger()); }
Sau khi khởi tạo đối tượng
IDownloaderService
, bạn có thể gửi các lệnh đến
dịch vụ trình tải xuống, chẳng hạn như tạm dừng và tiếp tục quá trình tải xuống (requestPauseDownload()
vàrequestContinueDownload()
). onDownloadStateChanged(int newState)
- Dịch vụ tải xuống gọi hàm này khi có thay đổi về trạng thái tải xuống, chẳng hạn như
bắt đầu hoặc hoàn tất việc tải xuống.Giá trị
newState
sẽ là một trong nhiều giá trị có thể được chỉ định trong
một trong các hằng sốSTATE_*
của lớpIDownloaderClient
.Để cung cấp thông báo hữu ích cho người dùng, bạn có thể yêu cầu một chuỗi tương ứng cho từng trạng thái bằng cách gọi
Helpers.getDownloaderStringResourceIDFromState()
. Thao tác này
sẽ trả về mã nhận dạng tài nguyên cho một trong các chuỗi trong gói Thư viện
trình tải xuống. Ví dụ: chuỗi “Tạm dừng tải xuống vì bạn đang chuyển vùng” tương ứng vớiSTATE_PAUSED_ROAMING
. onDownloadProgress(DownloadProgressInfo progress)
- Dịch vụ tải xuống gọi hàm này để cung cấp một đối tượng
DownloadProgressInfo
mô tả nhiều thông tin khác nhau về tiến trình tải xuống, bao gồm thời gian ước tính còn lại, tốc độ hiện tại, tiến trình tổng thể và tổng số để bạn có thể cập nhật giao diện người dùng cho tiến trình tải xuống.
Lưu ý: Để biết ví dụ về các lệnh gọi lại cập nhật giao diện người dùng
của tiến trình tải xuống, hãy xem SampleDownloaderActivity
trong ứng dụng mẫu được cung cấp cùng với gói
Mở rộng Apk.
Một số phương thức công khai cho giao diện IDownloaderService
có thể hữu ích là:
requestPauseDownload()
- Tạm dừng quá trình tải xuống.
requestContinueDownload()
- Tiếp tục tải một tệp đã tạm dừng xuống.
setDownloadFlags(int flags)
- Đặt tuỳ chọn người dùng cho những loại mạng mà bạn có thể tải tệp xuống. Cách triển khai hiện tại
hỗ trợ một cờFLAGS_DOWNLOAD_OVER_CELLULAR
, tuy nhiên bạn có thể thêm
cờ khác. Theo mặc định, cờ này không được bật, vì vậy, người dùng phải sử dụng Wi-Fi để tải tệp mở rộng xuống. Có thể bạn muốn cung cấp một tuỳ chọn người dùng để cho phép tải xuống qua
mạng di động. Trong trường hợp đó, bạn có thể gọi:Kotlin
remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { ... setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR) }
Java
remoteService .setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);
Sử dụng APKExpansionPolicy
Nếu quyết định xây dựng dịch vụ tải xuống của riêng bạn thay vì sử dụng Thư viện trình tải xuống của Google Play, bạn vẫn nên sử dụng APKExpansionPolicy
được cung cấp trong Thư viện xác minh giấy phép. Lớp APKExpansionPolicy
gần giống với lớp ServerManagedPolicy
(có sẵn trong Thư viện xác minh giấy phép của Google Play) nhưng có thêm tính năng xử lý bổ sung cho những ứng dụng khác của phản hồi tệp mở rộng APK.
Lưu ý: Nếu bạn sử dụng Thư viện trình tải xuống như đã thảo luận trong phần trước, thư viện sẽ thực hiện tất cả hoạt động tương tác với APKExpansionPolicy
nên bạn không phải sử dụng trực tiếp
lớp này.
Lớp này gồm có những phương pháp để giúp bạn nhận được thông tin thiết yếu về những tệp lan rộng ra có sẵn :
getExpansionURLCount()
getExpansionURL(int index)
getExpansionFileName(int index)
getExpansionFileSize(int index)
Để biết thêm thông tin về cách sử dụng APKExpansionPolicy
khi bạn không
sử dụng Thư viện trình tải xuống, hãy xem tài liệu về cách Thêm giấy phép vào Ứng dụng,
trong đó giải thích cách triển khai chính sách cấp phép giống chính sách này.
Đọc tệp mở rộng
Sau khi lưu các tệp mở rộng APK trên thiết bị, cách bạn đọc tệp
sẽ phụ thuộc vào loại tệp bạn đã sử dụng. Như đã thảo luận trong phần tổng quan, tệp mở rộng của bạn có thể là bất kỳ loại tệp nào bạn
muốn, nhưng được đổi tên bằng một định dạng tên tệp cụ thể và được lưu vào
.
Bất kể bạn đọc tệp theo cách nào, bạn phải luôn kiểm tra trước để chắc rằng bộ nhớ ngoài có sẵn để đọc. Có thể người dùng sẽ lắp bộ nhớ vào một máy tính qua USB hoặc đã tháo thẻ SD .
Lưu ý: Khi ứng dụng của bạn khởi động, bạn phải luôn kiểm tra xem
dung lượng bộ nhớ ngoài có đủ và có thể đọc được hay không bằng cách gọi getExternalStorageState()
. Hàm này sẽ trả về một trong những chuỗi có thể
hiển thị trạng thái của bộ nhớ ngoài. Để bộ nhớ ngoài của bạn có thể đọc được thì
giá trị trả về phải là MEDIA_MOUNTED
.
Lấy tên tệp
Như đã miêu tả trong phần tổng quan, tệp lan rộng ra APK của bạn được lưu dưới một định dạng tên tệp đơn cử :
[main|patch].. .obb
Để biết vị trí và tên của các tệp mở rộng, bạn nên sử dụng các phương thức
getExternalStorageDirectory()
và getPackageName()
để tạo đường dẫn đến tệp của mình.
Dưới đây là một phương pháp bạn hoàn toàn có thể sử dụng trong ứng dụng để nhận một mảng chứa đường dẫn không thiếu đến cả hai tệp lan rộng ra :
Kotlin
fun getAPKExpansionFiles(ctx: Context, mainVersion: Int, patchVersion: Int): Array{ val packageName = ctx.packageName val ret = mutableListOf () if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) { // Build the full path to the app's expansion files val root = Environment.getExternalStorageDirectory() val expPath = File(root.toString() + EXP_PATH + packageName) // Check that expansion file path exists if (expPath.exists()) { if (mainVersion > 0) { val strMainPath = "$expPath${File.separator}main.$mainVersion.$packageName.obb" val main = File(strMainPath) if (main.isFile) { ret += strMainPath } } if (patchVersion > 0) { val strPatchPath = "$expPath${File.separator}patch.$mainVersion.$packageName.obb" val main = File(strPatchPath) if (main.isFile) { ret += strPatchPath } } } } return ret.toTypedArray() }
Java
// The shared path to all app expansion files private final static String EXP_PATH = "/Android/obb/"; static String[] getAPKExpansionFiles(Context ctx, int mainVersion, int patchVersion) { String packageName = ctx.getPackageName(); Vectorret = new Vector (); if (Environment.getExternalStorageState() .equals(Environment.MEDIA_MOUNTED)) { // Build the full path to the app's expansion files File root = Environment.getExternalStorageDirectory(); File expPath = new File(root.toString() + EXP_PATH + packageName); // Check that expansion file path exists if (expPath.exists()) { if ( mainVersion > 0 ) { String strMainPath = expPath + File.separator + "main." + mainVersion + "." + packageName + ".obb"; File main = new File(strMainPath); if ( main.isFile() ) { ret.add(strMainPath); } } if ( patchVersion > 0 ) { String strPatchPath = expPath + File.separator + "patch." + mainVersion + "." + packageName + ".obb"; File main = new File(strPatchPath); if ( main.isFile() ) { ret.add(strPatchPath); } } } } String[] retArray = new String[ret.size()]; ret.toArray(retArray); return retArray; }
Bạn có thể gọi phương thức này bằng cách truyền Context
của ứng dụng và phiên bản tệp mở rộng mong muốn cho phương thức.
Có nhiều cách để bạn xác định số phiên bản của tệp mở rộng. Một cách đơn giản là
lưu phiên bản trong tệp SharedPreferences
khi quá trình tải xuống bắt đầu, bằng cách
truy vấn tên tệp mở rộng bằng phương thức getExpansionFileName(int index)
của lớp APKExpansionPolicy
. Sau đó, bạn có thể nhận mã phiên bản bằng cách đọc tệp SharedPreferences
khi muốn truy cập vào tệp mở rộng.
Để biết thêm thông tin về cách đọc từ bộ nhớ dùng chung, hãy xem tài liệu về Bộ nhớ tài liệu .
Sử dụng Thư viện zip tệp mở rộng APK
Gói mở rộng Apk Google Market bao gồm một thư viện có tên là Thư viện APK mở rộng APK (nằm trong
). Đây là thư viện không bắt buộc
giúp bạn đọc các tệp mở rộng
khi chúng được lưu dưới dạng tệp ZIP. Thư viện này cho phép bạn dễ dàng đọc tài nguyên từ
các tệp mở rộng ZIP dưới dạng hệ thống tệp ảo.
Thư viện zip lan rộng ra APK gồm có những lớp và API sau :
APKExpansionSupport
- Cung cấp một số phương thức để truy cập vào tên tệp mở rộng và tệp ZIP:
getAPKExpansionFiles()
- Phương thức tương tự ở trên trả lại đường dẫn tệp đầy đủ đến cả hai tệp
mở rộng. getAPKExpansionZipFile(Context ctx, int mainVersion, int
patchVersion)- Trả về một
ZipResourceFile
thể hiện cả tệp chính và tệp bản vá. Điều này nghĩa là, nếu bạn chỉ định cảmainVersion
vàpatchVersion
, thì thao tác này sẽ trả về mộtZipResourceFile
cung cấp quyền đọc
tất cả dữ liệu, trong đó dữ liệu của tệp bản vá được hợp nhất trên tệp chính.
ZipResourceFile
- Là một tệp ZIP trên bộ nhớ dùng chung và thực hiện tất cả công việc để cung cấp một hệ thống tệp ảo dựa trên các tệp ZIP của bạn. Bạn có thể nhận một bản sao bằng cách sử dụng hàm
APKExpansionSupport.getAPKExpansionZipFile()
hoặc vớiZipResourceFile
bằng cách truyền bản sao đó tới đường dẫn đến tệp mở rộng. Lớp này bao gồm nhiều phương thức hữu ích, nhưng bạn thường không cần truy cập vào hầu hết các phương thức đó. Sau đây là một số phương thức quan trọng:getInputStream(String assetPath)
- Cung cấp
InputStream
để đọc một tệp trong tệp ZIP.assetPath
phải là đường dẫn đến tệp mong muốn, tương ứng với thư mục gốc của nội dung tệp ZIP. getAssetFileDescriptor(String assetPath)
- Cung cấp một
AssetFileDescriptor
cho một tệp trong
tệp ZIP.assetPath
phải là đường dẫn đến tệp mong muốn, tương ứng với thư mục gốc của nội dung tệp ZIP. Thông tin này sẽ hữu ích với một số API Android yêu cầu cóAssetFileDescriptor
, chẳng hạn như một số APIMediaPlayer
.
APEZProvider
- Phần lớn các ứng dụng không cần dùng lớp này. Lớp này xác định một
ContentProvider
sẽ sắp xếp dữ liệu từ các tệp ZIP thông qua một
nhà cung cấp nội dungUri
để cung cấp quyền truy cập vào tệp cho một số API Android nhất định
mong muốn quyền truy cậpUri
vào các tệp nội dung nghe nhìn. Ví dụ: lớp này hữu ích khi bạn muốn phát một video cóVideoView.setVideoURI()
.
Bỏ qua quá trình nén ZIP cho tệp nội dung nghe nhìn
Nếu bạn đang sử dụng các tệp mở rộng để lưu trữ tệp nội dung nghe nhìn, thì tệp ZIP vẫn cho phép bạn
sử dụng lệnh gọi phát nội dung nghe nhìn trên Android cung cấp các tuỳ chọn kiểm soát độ lệch và độ dài (chẳng hạn như hàm MediaPlayer.setDataSource()
và
SoundPool.load()
). Để thực hiện việc này,
bạn không được nén thêm trên các tệp nội dung nghe nhìn khi tạo các gói ZIP. Ví dụ: khi sử dụng công cụ zip
, bạn nên sử dụng tuỳ chọn -n
để chỉ định hậu tố tệp không nên được nén:
zip -n .mp4;.ogg main_expansion media_files
Đọc trên tệp ZIP
Khi sử dụng Thư viện zip lan rộng ra, việc đọc trên một tệp từ tệp ZIP thường nhu yếu :
Kotlin
// Get a ZipResourceFile representing a merger of both the main and patch files val expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a merger of both the main and patch files ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
Mã trên đây cung cấp quyền truy cập vào bất kỳ tệp nào tồn tại trong tệp mở rộng chính hoặc
tệp bản vá mở rộng, bằng cách đọc từ bản đồ hợp nhất tất cả tệp từ cả hai tệp. Bạn chỉ cần cung cấp cho phương thức getAPKExpansionFile()
ứng dụng android.content.Context
của bạn và số phiên bản của cả tệp mở rộng chính cũng như tệp bản vá mở rộng.
Nếu muốn đọc một tệp mở rộng cụ thể, bạn có thể sử dụng hàm khởi tạo ZipResourceFile
với đường dẫn đến tệp mở rộng mong muốn:
Kotlin
// Get a ZipResourceFile representing a specific expansion file val expansionFile = ZipResourceFile(filePathToMyZip) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a specific expansion file ZipResourceFile expansionFile = new ZipResourceFile(filePathToMyZip); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
Để biết thêm thông tin về cách sử dụng thư viện này cho các tệp mở rộng, hãy xem lớp
SampleDownloaderActivity
của ứng dụng mẫu, bao gồm mã bổ sung để
xác minh các tệp đã tải xuống bằng CRC. Hãy lưu ý rằng nếu bạn sử dụng mẫu này làm cơ sở cho hoạt động triển khai của riêng mình, thì bạn phải khai báo kích thước byte của tệp mở rộng trong mảng xAPKS
.
Kiểm thử tệp mở rộng
Trước khi phát hành ứng dụng, bạn cần kiểm thử hai việc sau : Đọc tệp lan rộng ra và tải tệp xuống .
Kiểm thử lượt đọc tệp
Trước khi tải ứng dụng lên Google Play, bạn phải kiểm thử năng lực đọc tệp của ứng dụng từ bộ nhớ dùng chung. Bạn chỉ cần thêm tệp vào vị trí thích hợp trên bộ nhớ dùng chung trên thiết bị và chạy ứng dụng của mình :
- Hãy tạo thư mục phù hợp trên bộ nhớ dùng chung trên thiết bị của bạn để Google Play lưu tệp.
Ví dụ: nếu tên gói là
com.example.android
thì bạn cần tạo
thư mụcAndroid/obb/com.example.android/
trên bộ nhớ dùng chung. (Cắm
thiết bị thử nghiệm vào máy tính để gắn bộ nhớ dùng chung và tạo thư mục này
theo cách thủ công.) - Thêm tệp mở rộng vào thư mục đó theo cách thủ công. Hãy đảm bảo rằng bạn đổi tên các tệp sao cho phù hợp với định dạng tên tệp Google Play sẽ sử dụng.
Ví dụ: bất kể loại tệp là gì thì tệp mở rộng chính cho ứng dụng
com.example.android
sẽ làmain.0300110.com.example.android.obb
.
Mã phiên bản có thể là bất kỳ giá trị nào bạn muốn. Chỉ cần nhớ rằng:- Tệp mở rộng chính luôn bắt đầu bằng
main
, còn tệp bản vá bắt đầu bằng
patch
. - Tên gói luôn khớp với tên APK mà bạn đính kèm tệp trên
Google Play.
- Tệp mở rộng chính luôn bắt đầu bằng
- Bây giờ (các) tệp mở rộng đã có trên thiết bị, bạn có thể cài đặt và chạy ứng dụng để
kiểm thử (các) tệp mở rộng của mình.
Dưới đây là một số ít lời nhắc về việc giải quyết và xử lý những tệp lan rộng ra :
- Không xoá hoặc đổi tên tệp mở rộng
.obb
(kể cả khi bạn giải nén dữ liệu tới một vị trí khác). Làm vậy có thể khiến Google Play (hoặc chính ứng dụng của bạn)
tải tệp mở rộng xuống nhiều lần. - Không lưu dữ liệu khác vào thư mục
obb/
của bạn. Nếu bạn phải giải nén một số dữ liệu, hãy lưu dữ liệu đó vào vị trí màgetExternalFilesDir()
chỉ định.
Kiểm thử tiến trình tải tệp xuống
Vì ứng dụng của bạn nhiều lúc phải tải những tệp lan rộng ra xuống theo cách thủ công bằng tay khi mở lần đầu, điều quan trọng là bạn phải kiểm thử quy trình này để bảo vệ rằng ứng dụng hoàn toàn có thể truy vấn thành công xuất sắc những URL, hãy tải những tệp xuống và lưu chúng vào thiết bị .
Để kiểm thử việc tiến hành quy trình tiến độ tải xuống thủ công bằng tay trong ứng dụng của mình, bạn hoàn toàn có thể xuất bản quá trình đó lên kênh thử nghiệm nội bộ để chỉ những người kiểm thử được uỷ quyền mới hoàn toàn có thể thực thi. Nếu mọi thứ hoạt động giải trí như dự kiến, ứng dụng của bạn sẽ khởi đầu tải những tệp lan rộng ra xuống ngay khi hoạt động giải trí chính khởi đầu .
Lưu ý: Trước đây, bạn có thể kiểm thử ứng dụng bằng cách tải phiên bản “nháp” chưa phát hành lên. Chức năng này không còn được hỗ trợ. Thay vào đó, bạn phải phát hành tệp này lên một kênh thử nghiệm nội bộ, khép kín hoặc công khai. Để biết thêm thông tin, hãy xem phần
Các ứng dụng nháp không còn được hỗ trợ.
Cập nhật ứng dụng
Một trong những quyền lợi tuyệt vời của việc sử dụng tệp lan rộng ra trên Google Play là năng lực update ứng dụng mà không cần tải lại tổng thể thành phần bắt đầu xuống. Vì Google Play được cho phép bạn cung ứng hai tệp lan rộng ra với mỗi APK, bạn hoàn toàn có thể sử dụng tệp thứ hai làm ” bản vá ” để cung ứng nội dung update và gia tài mới. Việc này sẽ giúp người dùng không cần tải lại tệp lan rộng ra chính hoàn toàn có thể có size lớn và đắt đỏ .
Về mặt kỹ thuật, tệp bản vá lan rộng ra giống với tệp lan rộng ra chính và cả mạng lưới hệ thống Android lẫn Google Play đều không triển khai việc vá lỗi giữa những tệp lan rộng ra và bản vá chính. Mã ứng dụng của bạn phải tự triển khai mọi bản vá thiết yếu .
Nếu bạn sử dụng tệp ZIP làm tệp mở rộng, Thư viện ZIP mở rộng APK đi kèm trong gói Mở rộng Apk bao gồm khả năng hợp nhất
tệp bản vá với tệp mở rộng chính.
Xem thêm: Các hệ điều hành thông dụng hiện nay thường được lưu trữ ở đâu – Chia Sẻ Kiến Thức Điện Máy Việt Nam
Lưu ý: Ngay cả khi bạn chỉ cần thực hiện thay đổi cho tệp bản vá mở rộng, bạn vẫn phải cập nhật APK để Google Play thực hiện cập nhật.
Nếu bạn không yêu cầu thay đổi mã trong ứng dụng, bạn chỉ cần cập nhật versionCode
trong tệp kê khai.
Miễn là bạn không biến hóa tệp lan rộng ra chính link với APK trong Play Console, những người dùng đã thiết lập ứng dụng của bạn trước đây sẽ không tải tệp lan rộng ra chính xuống. Người dùng hiện tại chỉ nhận được APK đã update và tệp bản vá lan rộng ra mới ( giữ lại tệp lan rộng ra chính trước đó ) .
Dưới đây là 1 số ít yếu tố cần chú ý quan tâm về những bản update cho những tệp lan rộng ra :
- Ứng dụng của bạn chỉ được có hai tệp mở rộng cùng một lúc. Một tệp mở rộng
chính và một tệp bản vá mở rộng. Trong quá trình cập nhật một tệp, Google Play sẽ xoá
phiên bản trước đó (do đó cũng phải xoá ứng dụng của bạn khi cập nhật thủ công). - Khi thêm tệp bản vá mở rộng, hệ thống Android không thực sự vá tệp mở rộng hoặc ứng dụng chính của bạn. Bạn phải thiết kế ứng dụng của mình để hỗ trợ dữ liệu bản vá.
Tuy nhiên, gói Apk Mở rộng bao gồm một thư viện để sử dụng tệp ZIP dưới dạng tệp mở rộng, hợp nhất dữ liệu từ tệp bản vá vào tệp mở rộng chính để bạn có thể dễ dàng đọc tất cả dữ liệu của tệp mở rộng.
Source: https://vh2.com.vn
Category: Lưu Trữ VH2