Cấp độ API: 18
Android 4.3 (JELLY_BEAN_MR2
)
là bản cập nhật cho bản phát hành Jelly Bean, cung cấp các tính năng mới cho người dùng và ứng dụng
nhà phát triển. Tài liệu này giới thiệu phần giới thiệu
các API mới.
Là nhà phát triển ứng dụng, bạn nên tải hình ảnh hệ thống Android 4.3 xuống và nền tảng SDK khỏi Trình quản lý SDK dưới dạng sớm nhất có thể. Nếu bạn không có thiết bị chạy Android 4.3 để kiểm thử ứng dụng của bạn, hãy dùng hệ thống Android 4.3 hình ảnh để kiểm thử ứng dụng của bạn trên trình mô phỏng Android. Sau đó xây dựng ứng dụng của bạn dựa trên nền tảng Android 4.3 để bắt đầu sử dụng các API mới nhất.
Cập nhật cấp độ API mục tiêu của bạn
Để tối ưu hoá ứng dụng của bạn hiệu quả hơn cho các thiết bị chạy Android 4.3,
bạn nên đặt targetSdkVersion
thành
"18"
, hãy cài đặt tiện ích này trên ảnh hệ thống Android 4.3,
hãy kiểm thử rồi xuất bản bản cập nhật cùng với thay đổi này.
Bạn có thể sử dụng API trong Android 4.3 mà vẫn hỗ trợ các phiên bản cũ bằng cách thêm API
các điều kiện vào mã của bạn để kiểm tra cấp độ API của hệ thống trước khi thực thi
Các API không được minSdkVersion
của bạn hỗ trợ.
Để tìm hiểu thêm về cách duy trì khả năng tương thích ngược, hãy đọc bài viết Hỗ trợ các
Phiên bản nền tảng.
Nhiều API khác nhau cũng có sẵn trong Thư viện hỗ trợ Android cho phép bạn triển khai các tính năng mới trên các phiên bản cũ hơn của nền tảng.
Để biết thêm thông tin về cách hoạt động của các cấp độ API, hãy đọc bài viết API là gì Cấp độ?
Thay đổi quan trọng về hành vi
Nếu bạn từng xuất bản một ứng dụng dành cho Android, thì xin lưu ý rằng có thể ứng dụng đó có thể bị ảnh hưởng bởi những thay đổi trong Android 4.3.
Nếu ứng dụng của bạn dùng ý định ngầm ẩn...
Ứng dụng của bạn có thể hoạt động không chính xác trong môi trường hồ sơ bị hạn chế.
Người dùng trong môi trường hồ sơ bị hạn chế có thể không
có sẵn tất cả các ứng dụng Android tiêu chuẩn. Ví dụ: một hồ sơ bị hạn chế có thể có
đã tắt trình duyệt web và ứng dụng máy ảnh. Do đó, ứng dụng của bạn không nên đưa ra giả định về việc ứng dụng nào
vì nếu bạn gọi startActivity()
mà không có
xác minh xem có ứng dụng nào để xử lý Intent
hay không,
ứng dụng của bạn có thể gặp sự cố trong hồ sơ bị hạn chế.
Khi sử dụng ý định ngầm ẩn, bạn phải luôn xác minh rằng có ứng dụng có sẵn để xử lý ý định bằng cách gọi resolveActivity()
hoặc queryIntentActivities()
. Ví dụ:
Kotlin
val intent = Intent(Intent.ACTION_SEND) ... if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } else { Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show() }
Java
Intent intent = new Intent(Intent.ACTION_SEND); ... if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } else { Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show(); }
Nếu ứng dụng của bạn phụ thuộc vào tài khoản...
Ứng dụng của bạn có thể hoạt động không chính xác trong môi trường hồ sơ bị hạn chế.
Theo mặc định, người dùng trong môi trường hồ sơ bị hạn chế không có quyền truy cập vào tài khoản người dùng.
Nếu ứng dụng của bạn phụ thuộc vào một Account
, thì ứng dụng đó có thể gặp sự cố hoặc hoạt động
không mong muốn khi dùng trong hồ sơ bị hạn chế.
Nếu bạn muốn ngăn các hồ sơ bị hạn chế sử dụng ứng dụng của bạn hoàn toàn vì
ứng dụng phụ thuộc vào thông tin tài khoản nhạy cảm, hãy chỉ định thuộc tính android:requiredAccountType
trong <application>
của tệp kê khai
.
Nếu bạn muốn cho phép các hồ sơ bị hạn chế tiếp tục dùng ứng dụng của mình mặc dù chúng không thể tạo tài khoản của riêng mình, sau đó bạn có thể tắt những tính năng yêu cầu tài khoản của ứng dụng hoặc cho phép hồ sơ bị hạn chế truy cập vào tài khoản do người dùng chính tạo. Để biết thêm thông tin, hãy xem phần bên dưới về Tài khoản hỗ trợ trong hồ sơ bị hạn chế.
Nếu ứng dụng của bạn sử dụng VideoView...
Video của bạn có thể xuất hiện nhỏ hơn trên Android 4.3.
Trên các phiên bản Android trước, tiện ích VideoView
không chính xác
đã tính giá trị "wrap_content"
cho layout_height
và layout_width
giống với "match_parent"
. Vì vậy, trong khi sử dụng "wrap_content"
cho chiều cao hoặc chiều rộng có thể trước đó bạn đã cung cấp bố cục video mong muốn,
làm như vậy có thể làm cho video nhỏ hơn nhiều trên Android 4.3 trở lên. Để khắc phục vấn đề này, hãy thay thế
"wrap_content"
bằng "match_parent"
và xác nhận rằng video của bạn xuất hiện như mong đợi trên
Android 4.3 cũng như trên các phiên bản cũ hơn.
Hồ sơ bị hạn chế
Trên máy tính bảng Android, người dùng hiện có thể tạo hồ sơ bị hạn chế dựa trên người dùng chính. Khi tạo hồ sơ bị hạn chế, người dùng có thể bật các hạn chế như ứng dụng nào được có sẵn cho hồ sơ. Một bộ API mới trong Android 4.3 cũng cho phép bạn tạo hiệu ứng hạt nhỏ các chế độ cài đặt hạn chế cho các ứng dụng mà bạn phát triển. Ví dụ: bằng cách sử dụng các API mới, bạn có thể cho phép người dùng kiểm soát loại nội dung nào có sẵn trong ứng dụng của bạn khi chạy trong môi trường hồ sơ bị hạn chế.
Giao diện người dùng để người dùng kiểm soát các hạn chế bạn đã tạo được quản lý bởi
Ứng dụng cài đặt. Để người dùng thấy được chế độ cài đặt quy định hạn chế của ứng dụng,
bạn phải khai báo các hạn chế mà ứng dụng cung cấp bằng cách tạo BroadcastReceiver
nhận ý định ACTION_GET_RESTRICTION_ENTRIES
. Hệ thống gọi ý định này để truy vấn
tất cả ứng dụng để biết các hạn chế hiện có, sau đó xây dựng giao diện người dùng để cho phép người dùng chính
quản lý các quy định hạn chế cho từng hồ sơ bị hạn chế.
Trong phương thức onReceive()
của
BroadcastReceiver
, bạn phải tạo RestrictionEntry
cho từng quy định hạn chế mà ứng dụng cung cấp. Mỗi RestrictionEntry
xác định một tiêu đề, nội dung mô tả và một trong các tuỳ chọn hạn chế
các loại dữ liệu sau:
TYPE_BOOLEAN
cho quy định hạn chế đúng hoặc sai.TYPE_CHOICE
đối với quy định hạn chế có nhiều lựa chọn loại trừ lẫn nhau (lựa chọn nút chọn).TYPE_MULTI_SELECT
đối với quy định hạn chế có nhiều lựa chọn không loại trừ lẫn nhau (các lựa chọn trong hộp đánh dấu).
Sau đó, bạn đặt tất cả đối tượng RestrictionEntry
vào ArrayList
rồi đưa vào kết quả của broadcast receiver dưới dạng giá trị cho thuộc tính
Thêm EXTRA_RESTRICTIONS_LIST
.
Hệ thống sẽ tạo giao diện người dùng cho các quy tắc hạn chế của ứng dụng trong ứng dụng Cài đặt và lưu từng quy tắc
bằng cách sử dụng khoá duy nhất bạn đã cung cấp cho mỗi RestrictionEntry
. Khi người dùng mở ứng dụng, bạn có thể truy vấn mọi hạn chế hiện tại bằng cách
đang gọi getApplicationRestrictions()
.
Thao tác này sẽ trả về một Bundle
chứa các cặp khoá-giá trị cho mỗi quy tắc hạn chế
mà bạn đã xác định bằng các đối tượng RestrictionEntry
.
Nếu bạn muốn cung cấp các hạn chế cụ thể hơn không thể xử lý bằng boolean duy nhất
và giá trị nhiều lựa chọn, thì bạn có thể tạo một hoạt động trong đó người dùng có thể chỉ định
các hạn chế và cho phép người dùng mở hoạt động đó trong phần cài đặt hạn chế. Trong
broadcast receiver để thêm EXTRA_RESTRICTIONS_INTENT
trong kết quả Bundle
. Phần bổ sung này phải chỉ định một Intent
cho biết lớp Activity
cần chạy (sử dụng phương thức
putParcelable()
để truyền EXTRA_RESTRICTIONS_INTENT
cùng với ý định).
Khi người dùng chính nhập hoạt động của bạn để đặt giới hạn tuỳ chỉnh,
thì hoạt động phải trả về kết quả chứa các giá trị hạn chế trong phần bổ sung bằng cách sử dụng
khoá EXTRA_RESTRICTIONS_LIST
hoặc EXTRA_RESTRICTIONS_BUNDLE
, tuỳ thuộc vào việc bạn chỉ định
RestrictionEntry
hoặc cặp khoá-giá trị tương ứng.
Các tài khoản hỗ trợ trong hồ sơ bị hạn chế
Bất kỳ tài khoản nào được thêm vào người dùng chính đều có sẵn trong hồ sơ bị hạn chế, nhưng
theo mặc định, không thể truy cập tài khoản qua API AccountManager
.
Nếu bạn cố thêm tài khoản bằng AccountManager
khi ở chế độ hạn chế
, bạn sẽ nhận được kết quả không thành công. Do những hạn chế này, bạn có:
3 lựa chọn:
Để có quyền truy cập vào tài khoản từ hồ sơ bị hạn chế, bạn phải thêm thuộc tính android:restrictedAccountType
vào thẻ <application>:
<application ... android:restrictedAccountType="com.example.account.type" >
Thận trọng: Việc bật thuộc tính này sẽ cung cấp cho bạn quyền truy cập của ứng dụng vào tài khoản của người dùng chính từ hồ sơ bị hạn chế. Vì vậy, bạn nên cho phép điều này chỉ khi thông tin mà ứng dụng của bạn hiển thị không tiết lộ thông tin nhận dạng cá nhân thông tin nhận dạng cá nhân (PII) được coi là nhạy cảm. Chế độ cài đặt hệ thống sẽ cung cấp thông tin người dùng rằng ứng dụng của bạn cấp hồ sơ bị hạn chế cho tài khoản của họ, vì vậy, người dùng phải được thông báo rõ ràng rằng quyền truy cập vào tài khoản đóng vai trò quan trọng đối với chức năng của ứng dụng. Nếu có thể, bạn cũng nên cung cấp đầy đủ các chế độ kiểm soát hạn chế cho người dùng chính để xác định mức độ truy cập vào tài khoản được phép trong ứng dụng của bạn.
Nếu bạn muốn sử dụng tài khoản nhưng không thực sự cần đến tài khoản đó cho phiên bản
bạn có thể kiểm tra khả năng sử dụng tài khoản và tắt các tính năng khi không sử dụng được.
Trước tiên, bạn nên kiểm tra xem đã có tài khoản hay chưa. Nếu không, hãy truy vấn xem
bạn có thể tạo một tài khoản mới bằng cách gọi getUserRestrictions()
và kiểm tra thêm DISALLOW_MODIFY_ACCOUNTS
trong kết quả. Nếu giá trị là true
,
thì bạn nên tắt bất kỳ chức năng nào của ứng dụng yêu cầu quyền truy cập vào tài khoản.
Ví dụ:
Kotlin
val um = context.getSystemService(Context.USER_SERVICE) as UserManager val restrictions: Bundle = um.userRestrictions if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { // cannot add accounts, disable some functionality }
Java
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); Bundle restrictions = um.getUserRestrictions(); if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { // cannot add accounts, disable some functionality }
Lưu ý: Trong trường hợp này, bạn không nên khai báo mọi thuộc tính mới trong tệp kê khai.
Nếu bạn không cung cấp ứng dụng cho các hồ sơ bị hạn chế vì
ứng dụng của bạn phụ thuộc vào thông tin cá nhân nhạy cảm trong tài khoản (và do hồ sơ bị hạn chế
hiện không thể thêm tài khoản mới), hãy thêm
thuộc tính android:requiredAccountType
cho thẻ <application>:
<application ... android:requiredAccountType="com.example.account.type" >
Ví dụ: ứng dụng Gmail sử dụng thuộc tính này để tự vô hiệu hoá đối với các hồ sơ bị hạn chế, vì bạn không nên sử dụng email cá nhân của chủ sở hữu cho các trang doanh nghiệp bị hạn chế.
Không dây và khả năng kết nối
Bluetooth năng lượng thấp (Hỗ trợ thông minh)
Android hiện hỗ trợ Bluetooth năng lượng thấp (LE) với các API mới trong android.bluetooth
.
Với các API mới, bạn có thể xây dựng các ứng dụng Android giao tiếp với Bluetooth năng lượng thấp
thiết bị ngoại vi như máy đo nhịp tim và máy đếm bước.
Vì Bluetooth LE là một tính năng phần cứng chưa có trên tất cả các thiết bị
Nếu là thiết bị chạy Android, bạn phải khai báo trong tệp kê khai một <uses-feature>
cho "android.hardware.bluetooth_le"
:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
Nếu bạn đã quen với các API Bluetooth cổ điển của Android, hãy lưu ý rằng việc sử dụng
Bluetooth LE API có một số điểm khác biệt. Quan trọng nhất là giờ đây đã có lớp BluetoothManager
mà bạn nên dùng cho một số thao tác cấp cao
chẳng hạn như lấy BluetoothAdapter
, lấy danh sách người dùng đã kết nối
thiết bị và kiểm tra trạng thái của thiết bị. Ví dụ: dưới đây là cách mà bây giờ bạn sẽ nhận được
BluetoothAdapter
:
Kotlin
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothAdapter = bluetoothManager.adapter
Java
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter();
Để khám phá thiết bị ngoại vi Bluetooth LE, hãy gọi startLeScan()
trên BluetoothAdapter
, truyền phương thức triển khai
của giao diện BluetoothAdapter.LeScanCallback
. Khi Bluetooth
bộ chuyển đổi phát hiện thiết bị ngoại vi Bluetooth LE, quá trình triển khai BluetoothAdapter.LeScanCallback
của bạn sẽ nhận được một cuộc gọi đến
onLeScan()
. Chiến dịch này
phương thức cung cấp cho bạn một đối tượng BluetoothDevice
biểu thị
thiết bị được phát hiện, giá trị RSSI cho thiết bị và một mảng byte chứa dữ liệu của thiết bị
bản ghi quảng cáo.
Nếu chỉ muốn quét để tìm một số loại thiết bị ngoại vi cụ thể, bạn có thể gọi startLeScan()
và thêm một mảng đối tượng UUID
chỉ định các dịch vụ GATT mà ứng dụng của bạn hỗ trợ.
Lưu ý: Bạn chỉ có thể quét tìm thiết bị Bluetooth năng lượng thấp hoặc quét tìm thiết bị Bluetooth cổ điển bằng các API trước đó. Bạn không quét được cả LE và Classic Các thiết bị Bluetooth cùng lúc.
Sau đó, để kết nối với thiết bị ngoại vi Bluetooth LE tương ứng, hãy gọi connectGatt()
trên
Đối tượng BluetoothDevice
, truyền vào đó phương thức triển khai của
BluetoothGattCallback
. Quá trình triển khai BluetoothGattCallback
của bạn sẽ nhận được lệnh gọi lại liên quan đến khả năng kết nối
trạng thái với thiết bị và các sự kiện khác. Sự kiện này diễn ra trong onConnectionStateChange()
lệnh gọi lại mà bạn có thể bắt đầu giao tiếp với thiết bị nếu phương thức chuyển STATE_CONNECTED
dưới dạng trạng thái mới.
Để truy cập các tính năng Bluetooth trên một thiết bị, ứng dụng của bạn cũng yêu cầu một số Quyền của người dùng Bluetooth. Để biết thêm thông tin, hãy xem hướng dẫn về API Bluetooth năng lượng thấp.
Chế độ chỉ quét Wi-Fi
Khi cố gắng xác định vị trí của người dùng, Android có thể sử dụng Wi-Fi để giúp xác định vị trí bằng cách quét các điểm truy cập lân cận. Tuy nhiên, người dùng thường tắt Wi-Fi để tiết kiệm pin, khiến dữ liệu vị trí kém chính xác hơn. Android hiện bao gồm chế độ chỉ quét cho phép thiết bị Wi-Fi quét các điểm truy cập để giúp xác định vị trí mà không cần kết nối với điểm truy cập, do đó làm giảm đáng kể mức sử dụng pin.
Nếu muốn lấy thông tin vị trí của người dùng nhưng Wi-Fi hiện đang tắt, bạn có thể yêu cầu
bật chế độ chỉ quét tìm Wi-Fi bằng cách gọi startActivity()
qua thao tác ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
.
Cấu hình Wi-Fi
API WifiEnterpriseConfig
mới cho phép các dịch vụ hướng doanh nghiệp
tự động định cấu hình Wi-Fi cho các thiết bị được quản lý.
Trả lời nhanh cho cuộc gọi đến
Kể từ Android 4.0, một tính năng có tên là "Phản hồi nhanh" cho phép người dùng phản hồi tin nhắn đến
các cuộc gọi bằng tin nhắn văn bản tức thì mà không cần nhấc máy hoặc mở khoá thiết bị.
Trước đây, các tin nhắn nhanh này luôn do ứng dụng Nhắn tin mặc định xử lý. Giờ đây, bất kỳ ứng dụng nào
có thể khai báo khả năng xử lý những thông báo này bằng cách tạo một Service
bằng bộ lọc ý định cho ACTION_RESPOND_VIA_MESSAGE
.
Khi người dùng trả lời cuộc gọi đến bằng câu trả lời nhanh, ứng dụng Điện thoại sẽ gửi
ý định ACTION_RESPOND_VIA_MESSAGE
thông qua URI
mô tả người nhận (người gọi) và EXTRA_TEXT
bổ sung
bằng thông điệp mà người dùng muốn gửi. Khi nhận được ý định, dịch vụ của bạn sẽ được phân phối
thông báo và tự dừng ngay lập tức (ứng dụng của bạn không được hiển thị hoạt động).
Để nhận được ý định này, bạn phải khai báo quyền SEND_RESPOND_VIA_MESSAGE
.
Đa phương tiện
Các tính năng nâng cao MediaExtractor và MediaCodec
Android hiện giúp bạn dễ dàng viết Quảng cáo thích ứng động của riêng mình
Phát trực tuyến qua trình phát HTTP (DASH) theo tiêu chuẩn ISO/IEC 23009-1,
bằng các API hiện có trong MediaCodec
và MediaExtractor
. Khung cơ sở của các API này đã được cập nhật để hỗ trợ
phân tích cú pháp các tệp MP4 rời rạc, nhưng ứng dụng của bạn vẫn chịu trách nhiệm phân tích cú pháp siêu dữ liệu MPD
và truyền từng luồng riêng lẻ đến MediaExtractor
.
Nếu bạn muốn sử dụng DASH với nội dung đã mã hoá, hãy lưu ý rằng phương thức getSampleCryptoInfo()
trả về siêu dữ liệu MediaCodec.CryptoInfo
mô tả cấu trúc của từng nội dung nghe nhìn đã mã hoá
mẫu. Ngoài ra, phương thức getPsshInfo()
đã được thêm vào
MediaExtractor
để bạn có thể truy cập siêu dữ liệu PSSH cho nội dung đa phương tiện DASH.
Phương thức này trả về tệp ánh xạ đối tượng UUID
tới byte, với
UUID
chỉ định lược đồ mã hoá và các byte là dữ liệu cụ thể
cho lược đồ đó.
DRM cho nội dung đa phương tiện
Lớp MediaDrm
mới cung cấp giải pháp mô-đun cho quyền kỹ thuật số
(DRM) với nội dung nghe nhìn của bạn bằng cách tách riêng các vấn đề về DRM khỏi việc phát nội dung nghe nhìn. Cho
Chẳng hạn như, việc phân tách API này cho phép bạn phát lại nội dung được mã hoá Widevine mà không phải
để sử dụng định dạng phương tiện Widevine. Giải pháp DRM này cũng hỗ trợ Mã hoá chung DASH để bạn
có thể sử dụng nhiều lược đồ DRM khác nhau cho nội dung truyền trực tuyến của mình.
Bạn có thể sử dụng MediaDrm
để nhận các thông báo và quy trình yêu cầu khoá không rõ ràng
thông báo phản hồi khoá từ máy chủ để lấy giấy phép và cấp phép. Ứng dụng của bạn là
chịu trách nhiệm xử lý việc giao tiếp qua mạng với máy chủ; lớp MediaDrm
chỉ cung cấp khả năng tạo và xử lý thông báo.
Các API MediaDrm
được dành để sử dụng cùng với
API MediaCodec
được ra mắt trong Android 4.1 (API cấp 16),
bao gồm MediaCodec
để mã hoá và giải mã nội dung, MediaCrypto
để xử lý nội dung đã mã hoá và MediaExtractor
để trích xuất và tách riêng nội dung của bạn.
Trước tiên, bạn phải tạo MediaExtractor
và
Đối tượng MediaCodec
. Sau đó, bạn có thể truy cập vào tính năng xác định lược đồ DRM
UUID
(thường là từ siêu dữ liệu trong nội dung) và sử dụng nó để tạo
thực thể của đối tượng MediaDrm
bằng hàm khởi tạo.
Mã hoá video qua một nền tảng
Android 4.1 (API cấp 16) thêm lớp MediaCodec
cho cấp thấp
mã hoá và giải mã nội dung đa phương tiện. Khi mã hoá video, Android 4.1 yêu cầu bạn cung cấp
nội dung đa phương tiện có mảng ByteBuffer
, nhưng Android 4.3 hiện cho phép bạn sử dụng Surface
làm dữ liệu đầu vào cho bộ mã hoá. Chẳng hạn, phương thức này cho phép bạn mã hoá dữ liệu đầu vào
từ một tệp video hiện có hoặc sử dụng khung hình tạo qua OpenGL ES.
Để dùng Surface
làm dữ liệu đầu vào cho bộ mã hoá, trước tiên hãy gọi configure()
cho MediaCodec
của bạn.
Sau đó, hãy gọi createInputSurface()
để nhận Surface
mà bạn có thể dùng để phát trực tuyến nội dung nghe nhìn của mình.
Ví dụ: bạn có thể sử dụng Surface
đã cho làm cửa sổ cho một OpenGL
ngữ cảnh bằng cách truyền tham số đó đến eglCreateWindowSurface()
. Sau đó, trong khi kết xuất nền tảng, hãy gọi eglSwapBuffers()
để truyền khung đến MediaCodec
.
Để bắt đầu mã hoá, hãy gọi start()
trên MediaCodec
. Khi hoàn tất, hãy gọi signalEndOfInputStream()
để chấm dứt quá trình mã hoá và gọi release()
trên
Surface
.
Ghép nội dung đa phương tiện
Lớp MediaMuxer
mới cho phép ghép kênh giữa một luồng âm thanh
và một luồng video. Các API này đóng vai trò như phiên bản đối chiếu của MediaExtractor
đã thêm vào Android 4.2 cho nội dung đa phương tiện tách kênh (demuxing).
Bạn có thể xác định các định dạng đầu ra được hỗ trợ trong MediaMuxer.OutputFormat
. Hiện tại,
MP4 là định dạng đầu ra duy nhất được hỗ trợ và MediaMuxer
hiện hỗ trợ
chỉ một luồng âm thanh và/hoặc một luồng video tại một thời điểm.
MediaMuxer
chủ yếu được thiết kế để hoạt động với MediaCodec
để bạn có thể xử lý video thông qua MediaCodec
, sau đó lưu
sang tệp MP4 thông qua MediaMuxer
. Bạn cũng có thể sử dụng MediaMuxer
kết hợp với MediaExtractor
để thực hiện
chỉnh sửa nội dung đa phương tiện mà không cần mã hoá hoặc giải mã.
Tiến trình phát và tua cho RemoteControlClient
Trong Android 4.0 (API cấp 14), RemoteControlClient
đã được thêm vào
bật điều khiển phát lại nội dung nghe nhìn từ ứng dụng điều khiển từ xa, chẳng hạn như các nút điều khiển có sẵn trên
màn hình khóa. Android 4.3 hiện cung cấp khả năng cho phép các bộ điều khiển đó hiển thị phát lại
vị trí và các nút điều khiển
để tua nhanh phát. Nếu bạn đã bật điều khiển từ xa cho
ứng dụng đa phương tiện với API RemoteControlClient
, thì bạn có thể cho phép phát lại
quét bằng cách triển khai hai giao diện mới.
Trước tiên, bạn phải bật cờ FLAG_KEY_MEDIA_POSITION_UPDATE
bằng cách truyền cờ đó đến
setTransportControlsFlags()
Sau đó, hãy triển khai hai giao diện mới sau đây:
RemoteControlClient.OnGetPlaybackPositionListener
- Trong đó có cả lệnh gọi lại
onGetPlaybackPosition()
. Lệnh gọi lại này yêu cầu thông tin vị trí hiện tại của nội dung nghe nhìn khi điều khiển từ xa cần cập nhật tiến trình trong giao diện người dùng. RemoteControlClient.OnPlaybackPositionUpdateListener
- Điều này bao gồm phương thức gọi lại
onPlaybackPositionUpdate()
cho ứng dụng biết mã thời gian mới cho nội dung đa phương tiện khi người dùng tua nội dung phát bằng giao diện người dùng điều khiển từ xa.Sau khi bạn cập nhật chế độ phát với vị trí mới, hãy gọi
setPlaybackState()
để cho biết trạng thái, vị trí và tốc độ phát mới.
Sau khi xác định các giao diện này, bạn có thể thiết lập giao diện cho RemoteControlClient
bằng cách gọi setOnGetPlaybackPositionListener()
và
setPlaybackPositionUpdateListener()
.
Đồ hoạ
Hỗ trợ OpenGL ES 3.0
Android 4.3 bổ sung giao diện Java và hỗ trợ riêng cho OpenGL ES 3.0. Chức năng mới quan trọng được cung cấp trong OpenGL ES 3.0 bao gồm:
- Tăng tốc hiệu ứng hình ảnh nâng cao
- Nén kết cấu ETC2/EAC chất lượng cao theo tiêu chuẩn
- Phiên bản mới của ngôn ngữ tô bóng GLSL ES có hỗ trợ số nguyên và dấu phẩy động 32 bit
- Kết xuất hoạ tiết nâng cao
- Tiêu chuẩn hoá kích thước hoạ tiết và định dạng vùng đệm kết xuất rộng hơn
Giao diện Java cho OpenGL ES 3.0 trên Android được cung cấp cùng với GLES30
.
Khi sử dụng OpenGL ES 3.0, hãy nhớ khai báo trong tệp kê khai bằng phần tử
<uses-feature>
và thuộc tính android:glEsVersion
. Ví dụ:
<manifest> <uses-feature android:glEsVersion="0x00030000" /> ... </manifest>
Đồng thời, hãy nhớ chỉ định ngữ cảnh OpenGL ES bằng cách gọi setEGLContextClientVersion()
,
truyền 3
làm phiên bản.
Để biết thêm thông tin về cách sử dụng OpenGL ES, bao gồm cả cách kiểm tra xem thiết bị có hỗ trợ hay không Phiên bản OpenGL ES trong thời gian chạy, hãy xem hướng dẫn về API OpenGL ES.
Ánh xạ Mip cho đối tượng có thể vẽ
Dùng mipmap làm nguồn cho bitmap hoặc đối tượng có thể vẽ là một cách đơn giản để cung cấp hình ảnh chất lượng cao và nhiều tỷ lệ hình ảnh khác nhau. Điều này có thể đặc biệt hữu ích nếu bạn muốn được điều chỉnh theo tỷ lệ trong khi tạo ảnh động.
Android 4.2 (API cấp 17) hỗ trợ thêm mipmap trong Bitmap
lớp – Android hoán đổi hình ảnh mip trong Bitmap
khi bạn
đã cung cấp nguồn mipmap và đã bật setHasMipMap()
. Giờ đây, trong Android 4.3, bạn cũng có thể bật mipmap cho đối tượng BitmapDrawable
bằng cách cung cấp thành phần mipmap và
đặt thuộc tính android:mipMap
trong tệp tài nguyên bitmap hoặc bằng cách gọi hasMipMap()
.
Giao diện người dùng
Xem lớp phủ
Lớp ViewOverlay
mới cung cấp một lớp trong suốt ở trên cùng
View
mà bạn có thể thêm nội dung hình ảnh vào đó và không ảnh hưởng đến
hệ phân cấp bố cục. Bạn có thể nhận ViewOverlay
cho bất kỳ View
nào bằng cách gọi getOverlay()
. Lớp phủ
luôn có cùng kích thước và vị trí như khung hiển thị máy chủ lưu trữ (chế độ xem mà khung hiển thị được tạo từ đó),
cho phép bạn thêm nội dung xuất hiện phía trước chế độ xem máy chủ lưu trữ, nhưng không thể mở rộng
giới hạn của khung hiển thị máy chủ lưu trữ đó.
Việc sử dụng ViewOverlay
đặc biệt hữu ích khi bạn muốn tạo
ảnh động như trượt khung hiển thị ra ngoài vùng chứa hoặc di chuyển các mục xung quanh màn hình
mà không ảnh hưởng đến hệ phân cấp khung hiển thị. Tuy nhiên, vì diện tích có thể sử dụng của lớp phủ là
bị hạn chế ở cùng một khu vực với khung hiển thị máy chủ, nếu bạn muốn tạo hiệu ứng động cho khung hiển thị di chuyển ra bên ngoài
trong bố cục, bạn phải sử dụng lớp phủ từ khung hiển thị mẹ có
ranh giới bố cục.
Khi tạo lớp phủ cho chế độ xem tiện ích, chẳng hạn như Button
, bạn
có thể thêm đối tượng Drawable
vào lớp phủ bằng cách gọi
add(Drawable)
. Nếu bạn gọi getOverlay()
cho chế độ xem bố cục, chẳng hạn như RelativeLayout
,
đối tượng được trả về là một ViewGroupOverlay
. Chiến lược phát hành đĩa đơn
Lớp ViewGroupOverlay
là một lớp con
của ViewOverlay
, cũng như cho phép bạn thêm View
bằng cách gọi add(View)
.
Lưu ý: Tất cả các đối tượng có thể vẽ và khung hiển thị mà bạn thêm vào lớp phủ chỉ có hình ảnh. Họ không thể nhận được sự kiện nhập hoặc tiêu điểm.
Ví dụ: mã sau đây tạo hiệu ứng động cho một khung hiển thị trượt sang phải bằng cách đặt khung hiển thị đó trong lớp phủ của chế độ xem gốc, sau đó thực hiện ảnh động dịch trên chế độ xem đó:
Kotlin
val view: View? = findViewById(R.id.view_to_remove) val container: ViewGroup? = view?.parent as ViewGroup container?.apply { overlay.add(view) ObjectAnimator.ofFloat(view, "translationX", right.toFloat()) .start() }
Java
View view = findViewById(R.id.view_to_remove); ViewGroup container = (ViewGroup) view.getParent(); container.getOverlay().add(view); ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight()); anim.start();
Bố cục giới hạn quang học
Đối với các khung hiển thị chứa hình nền 9-patch, giờ đây, bạn có thể chỉ định rằng chúng được căn chỉnh với các chế độ xem lân cận dựa trên "quang học" các ranh giới của hình nền thay vì so với "clip" giới hạn của khung hiển thị.
Ví dụ: Hình 1 và 2 mỗi hình ảnh thể hiện cùng một bố cục, nhưng phiên bản trong hình 1 là sử dụng giới hạn đoạn video (hành vi mặc định), trong khi hình 2 sử dụng giới hạn quang học. Vì hình ảnh 9-patch dùng cho nút và khung ảnh bao gồm khoảng đệm xung quanh các cạnh, chúng dường như không khớp với nhau hoặc văn bản khi sử dụng giới hạn đoạn video.
Lưu ý: Ảnh chụp màn hình trong hình 1 và 2 có nút "Hiển thị ranh giới bố cục" bật cài đặt dành cho nhà phát triển. Đối với mỗi hình ảnh, các đường màu đỏ biểu thị ranh giới, đường màu xanh dương biểu thị giới hạn đối với đoạn video và màu hồng biểu thị lề.
![](https://developer.android.com/static/images/tools/clipbounds_2x.png?authuser=9&hl=vi)
Hình 1. Bố cục sử dụng giới hạn đoạn video (mặc định).
![](https://developer.android.com/static/images/tools/opticalbounds_2x.png?authuser=9&hl=vi)
Hình 2. Bố cục sử dụng ranh giới quang học.
Để căn chỉnh khung hiển thị dựa trên giới hạn quang học, hãy đặt thuộc tính android:layoutMode
thành "opticalBounds"
ở một trong các bố cục mẹ. Ví dụ:
<LinearLayout android:layoutMode="opticalBounds" ... >
![](https://developer.android.com/static/images/tools/ninepatch_opticalbounds_2x.png?authuser=9&hl=vi)
Hình 3. Chế độ xem phóng to của nút Holo 9-patch với giới hạn quang học.
Để làm được điều này, hình ảnh 9-patch được áp dụng cho nền của khung hiển thị phải chỉ định ranh giới quang học bằng cách sử dụng các đường màu đỏ dọc theo phần dưới cùng và phía bên phải của tệp 9-patch (như như minh hoạ trong hình 3). Các đường màu đỏ cho biết vùng cần bị trừ đi giới hạn đoạn video, chừa lại ranh giới quang học của hình ảnh.
Khi bạn bật giới hạn quang học cho ViewGroup
trong bố cục, tất cả
các khung hiển thị con kế thừa chế độ bố cục giới hạn quang học, trừ phi bạn ghi đè chế độ này cho một nhóm
đang đặt android:layoutMode
thành "clipBounds"
. Tất cả các phần tử bố cục cũng tôn trọng
giới hạn quang học của khung nhìn con, điều chỉnh giới hạn của chính chúng dựa trên giới hạn quang học của
chế độ xem trong các nhóm đó. Tuy nhiên, các phần tử bố cục (các lớp con của ViewGroup
)
hiện không hỗ trợ giới hạn quang học cho hình ảnh 9-patch được áp dụng cho nền riêng.
Nếu bạn tạo một thành phần hiển thị tuỳ chỉnh bằng cách phân lớp con View
, ViewGroup
hoặc bất kỳ lớp con nào của các thành phần đó, thì thành phần hiển thị của bạn sẽ kế thừa các hành vi ràng buộc quang học này.
Lưu ý: Tất cả các tiện ích được chủ đề Holo hỗ trợ đã được cập nhật
có giới hạn quang học, bao gồm Button
, Spinner
,
EditText
và những người khác. Vì vậy, bạn có thể hưởng lợi ngay lập tức bằng cách đặt
Thuộc tính android:layoutMode
cho "opticalBounds"
nếu ứng dụng của bạn áp dụng chủ đề Holo
(Theme.Holo
, Theme.Holo.Light
, v.v.).
Để chỉ định giới hạn quang học cho hình ảnh 9-patch của riêng bạn bằng công cụ Draw 9-patch, giữ phím Control khi bằng cách nhấp vào các pixel đường viền.
Ảnh động cho các giá trị ct
Giờ đây, bạn có thể tạo ảnh động giữa hai giá trị Rect
bằng RectEvaluator
mới. Lớp mới này là cách triển khai TypeEvaluator
mà bạn có thể truyền đến ValueAnimator.setEvaluator()
.
Trình nghe tiêu điểm và đính kèm cửa sổ
Trước đây, nếu bạn muốn lắng nghe thời điểm góc nhìn của bạn được gắn vào/nằm gần cửa sổ hoặc
khi tiêu điểm của tệp thay đổi, bạn cần ghi đè lớp View
để
triển khai onAttachedToWindow()
và onDetachedFromWindow()
hoặc onWindowFocusChanged()
tương ứng.
Bây giờ, để nhận các sự kiện đính kèm và tách, bạn có thể triển khai ViewTreeObserver.OnWindowAttachListener
và đặt nó trên một khung hiển thị bằng
addOnWindowAttachListener()
Để nhận các sự kiện tiêu điểm, bạn có thể triển khai ViewTreeObserver.OnWindowFocusChangeListener
và đặt trên một khung hiển thị có
addOnWindowFocusChangeListener()
Hỗ trợ quét quá mức TV
Để đảm bảo ứng dụng của bạn lấp đầy toàn bộ màn hình trên mọi TV, giờ đây, bạn có thể bật tính năng quét tràn
cho bố cục ứng dụng của mình. Chế độ quét quá mức được xác định bằng cờ FLAG_LAYOUT_IN_OVERSCAN
. Bạn có thể bật chế độ này bằng các giao diện nền tảng như
Theme_DeviceDefault_NoActionBar_Overscan
hoặc bằng cách bật
Kiểu windowOverscan
trong giao diện tuỳ chỉnh.
Hướng màn hình
<activity>
screenOrientation
của thẻ
hiện hỗ trợ các giá trị bổ sung để thực hiện theo lựa chọn ưu tiên của người dùng về chế độ xoay tự động:
"userLandscape"
- Hoạt động giống như
"sensorLandscape"
, trừ phi người dùng tắt chế độ tự động xoay thì màn hình sẽ khoá theo hướng ngang thông thường và không lật. "userPortrait"
- Hoạt động giống như
"sensorPortrait"
, trừ phi người dùng tắt chế độ tự động xoay thì màn hình sẽ khoá theo hướng dọc thông thường và sẽ không lật. "fullUser"
- Hoạt động giống như
"fullSensor"
và cho phép xoay theo cả bốn hướng, ngoại trừ nếu người dùng tắt chế độ tự động xoay, thì chế độ này sẽ khoá theo hướng ưu tiên của người dùng.
Ngoài ra, giờ đây bạn cũng có thể khai báo "locked"
để khoá hướng ứng dụng thành
hướng hiện tại của màn hình.
Ảnh động xoay
Trường rotationAnimation
mới trong
WindowManager
cho phép bạn chọn một trong ba ảnh động để
muốn sử dụng khi hệ thống chuyển hướng màn hình. Ba ảnh động này là:
Lưu ý: Những ảnh động này chỉ xuất hiện nếu bạn đã đặt hoạt động ở chế độ "toàn màn hình" mà bạn có thể bật với các chủ đề như Theme.Holo.NoActionBar.Fullscreen
.
Ví dụ: dưới đây là cách bạn có thể bật tính năng "mờ dần" ảnh động:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val params: WindowManager.LayoutParams = window.attributes params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE window.attributes = params ... }
Java
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WindowManager.LayoutParams params = getWindow().getAttributes(); params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; getWindow().setAttributes(params); ... }
Dữ liệu do người dùng nhập
Các loại cảm biến mới
Cảm biến TYPE_GAME_ROTATION_VECTOR
mới cho phép bạn phát hiện góc xoay của thiết bị mà không lo lắng về hiện tượng nhiễu từ. Không giống như cảm biến TYPE_ROTATION_VECTOR
, TYPE_GAME_ROTATION_VECTOR
không dựa trên hướng bắc từ tính.
Cảm biến TYPE_GYROSCOPE_UNCALIBRATED
và TYPE_MAGNETIC_FIELD_UNCALIBRATED
mới cung cấp dữ liệu cảm biến thô mà không
xem xét ước tính độ lệch. Tức là TYPE_GYROSCOPE
và TYPE_MAGNETIC_FIELD
hiện có
cảm biến cung cấp dữ liệu cảm biến có tính đến độ lệch ước tính từ con quay hồi chuyển và sắt cứng
trong thiết bị. Trong khi đó, tiêu chí "không được hiệu chỉnh" mới các phiên bản của các cảm biến này cung cấp
dữ liệu cảm biến thô và cung cấp riêng các giá trị độ lệch ước tính. Những cảm biến này cho phép bạn
cung cấp hiệu chỉnh tuỳ chỉnh riêng cho dữ liệu cảm biến bằng cách tăng độ lệch ước tính nhờ
dữ liệu bên ngoài.
Trình tiếp nhận thông báo
Android 4.3 bổ sung một lớp dịch vụ mới là NotificationListenerService
, cho phép ứng dụng của bạn nhận thông tin về các thông báo mới khi hệ thống đăng chúng.
Nếu ứng dụng của bạn đang dùng API dịch vụ hỗ trợ tiếp cận để truy cập vào thông báo của hệ thống, thì bạn nên cập nhật ứng dụng để dùng những API này.
Trình cung cấp danh bạ
Truy vấn về "đối tượng có thể liên hệ"
Truy vấn Contactables.CONTENT_URI
của Trình cung cấp danh bạ mới là một cách hiệu quả để lấy một Cursor
chứa tất cả địa chỉ email và số điện thoại của tất cả những người liên hệ khớp với truy vấn đã chỉ định.
Truy vấn delta danh bạ
Các API mới đã được thêm vào Trình cung cấp danh bạ, cho phép bạn truy vấn hiệu quả những thay đổi gần đây đối với dữ liệu danh bạ. Trước đây, ứng dụng của bạn có thể được thông báo khi có nội dung nào đó trong dữ liệu danh bạ thay đổi, nhưng bạn sẽ không biết chính xác điều gì đã thay đổi và cần phải truy xuất tất cả liên hệ, sau đó lặp lại để khám phá thay đổi.
Để theo dõi các thay đổi đối với hoạt động chèn và cập nhật, giờ đây, bạn có thể đưa tham số CONTACT_LAST_UPDATED_TIMESTAMP
vào lựa chọn của mình để chỉ truy vấn những người liên hệ đã thay đổi kể từ lần gần đây nhất bạn truy vấn nhà cung cấp.
Để theo dõi những địa chỉ liên hệ đã bị xoá, bảng mới ContactsContract.DeletedContacts
cung cấp nhật ký các địa chỉ liên hệ đã bị xoá (nhưng mỗi địa chỉ liên hệ đã xoá sẽ được lưu giữ trong bảng này trong một khoảng thời gian giới hạn). Tương tự như CONTACT_LAST_UPDATED_TIMESTAMP
, bạn có thể sử dụng tham số lựa chọn mới CONTACT_DELETED_TIMESTAMP
để kiểm tra những người liên hệ đã bị xoá kể từ lần gần đây nhất bạn truy vấn nhà cung cấp. Bảng này cũng chứa hằng số DAYS_KEPT_MILLISECONDS
chứa số ngày (tính bằng mili giây) mà nhật ký sẽ được lưu giữ.
Ngoài ra, Trình cung cấp danh bạ giờ đây sẽ truyền phát thao tác CONTACTS_DATABASE_CREATED
khi người dùng
xoá bộ nhớ danh bạ thông qua trình đơn cài đặt hệ thống, tạo lại
Cơ sở dữ liệu của Trình cung cấp Danh bạ. Nút này được dùng để báo hiệu cho các ứng dụng rằng ứng dụng cần bỏ tất cả người liên hệ
thông tin họ đã lưu trữ và tải lại thông tin đó
bằng một truy vấn mới.
Để xem mã mẫu sử dụng những API này nhằm kiểm tra thay đổi đối với danh bạ, hãy tìm trong Apidemos mẫu có sẵn trong nội dung tải xuống Mẫu SDK.
Bản địa hoá
Cải thiện hỗ trợ cho văn bản hai chiều
Các phiên bản trước của Android hỗ trợ ngôn ngữ và bố cục từ phải sang trái (RTL),
nhưng đôi khi không xử lý đúng cách văn bản theo hướng hỗn hợp. Vì vậy, Android 4.3 sẽ thêm các API BidiFormatter
giúp bạn định dạng đúng cách văn bản theo hướng ngược lại
mà không cắt xén bất kỳ phần nào của nội dung.
Ví dụ: khi bạn muốn tạo một câu có một biến chuỗi, chẳng hạn như "Ý của bạn là
15 Bay Street, Laurel, CA?", bạn thường truyền tài nguyên chuỗi đã bản địa hoá và biến đến
String.format()
:
Kotlin
val suggestion = String.format(resources.getString(R.string.did_you_mean), address)
Java
Resources res = getResources(); String suggestion = String.format(res.getString(R.string.did_you_mean), address);
Tuy nhiên, nếu ngôn ngữ là tiếng Do Thái, thì chuỗi được định dạng sẽ có dạng như sau:
Không
Sai vì "15" phải ở bên trái "Bay Street". Giải pháp là sử dụng BidiFormatter
và phương thức unicodeWrap()
của nó. Ví dụ: mã ở trên trở thành:
Kotlin
val bidiFormatter = BidiFormatter.getInstance() val suggestion = String.format( resources.getString(R.string.did_you_mean), bidiFormatter.unicodeWrap(address) )
Java
Resources res = getResources(); BidiFormatter bidiFormatter = BidiFormatter.getInstance(); String suggestion = String.format(res.getString(R.string.did_you_mean), bidiFormatter.unicodeWrap(address));
Theo mặc định, unicodeWrap()
sử dụng
phỏng đoán ước tính hướng mạnh đầu tiên, có thể mắc lỗi nếu giá trị đầu tiên
tín hiệu cho hướng văn bản không thể hiện hướng phù hợp cho toàn bộ nội dung.
Nếu cần, bạn có thể chỉ định một phương pháp phỏng đoán khác bằng cách truyền một trong các hằng số TextDirectionHeuristic
từ TextDirectionHeuristics
đến unicodeWrap()
.
Lưu ý: Các API mới này cũng có cho các phiên bản trước
của Android thông qua Hỗ trợ của Android
Thư viện, với lớp BidiFormatter
và các API liên quan.
Dịch vụ hỗ trợ tiếp cận
Xử lý các sự kiện chính
Giờ đây, AccessibilityService
có thể nhận được lệnh gọi lại cho
các sự kiện nhập chính bằng phương thức gọi lại onKeyEvent()
. Điều này cho phép dịch vụ hỗ trợ tiếp cận của bạn xử lý dữ liệu đầu vào cho
thiết bị đầu vào dựa trên phím (như bàn phím) và dịch các sự kiện đó thành các hành động đặc biệt
trước đây có thể chỉ dùng được bằng phương thức nhập bằng cách chạm hoặc bàn phím di chuyển của thiết bị.
Chọn văn bản và sao chép/dán
AccessibilityNodeInfo
hiện cung cấp các API cho phép
AccessibilityService
để chọn, cắt, sao chép và dán
văn bản trong nút.
Để chỉ định phần văn bản cần cắt hoặc sao chép, dịch vụ hỗ trợ tiếp cận của bạn có thể sử dụng thuộc tính
hành động, ACTION_SET_SELECTION
, truyền
chọn vị trí bắt đầu và kết thúc bằng ACTION_ARGUMENT_SELECTION_START_INT
và ACTION_ARGUMENT_SELECTION_END_INT
.
Ngoài ra, bạn có thể chọn văn bản bằng cách thao tác với vị trí con trỏ bằng cách sử dụng
hành động, ACTION_NEXT_AT_MOVEMENT_GRANULARITY
(trước đây chỉ dùng để di chuyển vị trí con trỏ) và thêm đối số ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
.
Sau đó, bạn có thể cắt hoặc sao chép bằng ACTION_CUT
,
ACTION_COPY
, sau đó dán bằng
ACTION_PASTE
.
Lưu ý: Các API mới này cũng có cho các phiên bản trước
của Android thông qua Hỗ trợ của Android
Thư viện với AccessibilityNodeInfoCompat
.
Khai báo bộ tính năng hỗ trợ tiếp cận
Kể từ Android 4.3, dịch vụ hỗ trợ tiếp cận phải khai báo khả năng hỗ trợ tiếp cận
trong tệp siêu dữ liệu để sử dụng một số tính năng hỗ trợ tiếp cận. Nếu chức năng này không
được yêu cầu trong tệp siêu dữ liệu thì tính năng này sẽ không hoạt động. Để khai báo
khả năng hỗ trợ tiếp cận, bạn phải sử dụng các thuộc tính XML tương ứng với
"chức năng" hằng số trong AccessibilityServiceInfo
.
Ví dụ: nếu một dịch vụ không yêu cầu chức năng flagRequestFilterKeyEvents
,
thì sẽ không nhận được các sự kiện chính.
Kiểm thử và gỡ lỗi
Kiểm thử giao diện người dùng tự động
Lớp UiAutomation
mới cung cấp các API cho phép bạn mô phỏng người dùng
để tự động hoá thử nghiệm. Bằng cách sử dụng các API AccessibilityService
của nền tảng, UiAutomation
Các API cho phép bạn kiểm tra nội dung trên màn hình cũng như chèn các sự kiện chạm và bàn phím tuỳ ý.
Để nhận một thực thể của UiAutomation
, hãy gọi Instrumentation.getUiAutomation()
. Đơn đặt hàng
để tính năng này hoạt động, bạn phải cung cấp tuỳ chọn -w
cùng với lệnh instrument
khi chạy InstrumentationTestCase
từ adb shell
.
Với thực thể UiAutomation
, bạn có thể thực thi các sự kiện tuỳ ý để kiểm thử
ứng dụng của bạn bằng cách gọi executeAndWaitForEvent()
, truyền cho ứng dụng một Runnable
để thực hiện, thời gian chờ
thời gian cho hoạt động và quá trình triển khai giao diện UiAutomation.AccessibilityEventFilter
. Bạn sẽ nhận được một cuộc gọi trong quá trình triển khai UiAutomation.AccessibilityEventFilter
cho phép bạn lọc các sự kiện mà bạn quan tâm và xác định tỷ lệ thành công hoặc
lỗi của một trường hợp kiểm thử nhất định.
Để quan sát tất cả sự kiện trong quá trình kiểm thử, hãy tạo một phương thức triển khai UiAutomation.OnAccessibilityEventListener
rồi truyền cho setOnAccessibilityEventListener()
.
Sau đó, giao diện trình nghe của bạn sẽ nhận được một lệnh gọi đến onAccessibilityEvent()
mỗi khi một sự kiện xảy ra, nhận đối tượng AccessibilityEvent
mô tả sự kiện.
Có nhiều thao tác khác mà API UiAutomation
hiển thị
ở mức rất thấp để khuyến khích phát triển các công cụ kiểm thử giao diện người dùng như uiautomator. Ví dụ:
UiAutomation
cũng có thể:
- Chèn sự kiện đầu vào
- Thay đổi hướng của màn hình
- Chụp ảnh màn hình
Và điều quan trọng nhất đối với các công cụ kiểm thử giao diện người dùng là API UiAutomation
hoạt động
trên các ranh giới của ứng dụng, không giống như các API trong Instrumentation
.
Sự kiện Systrace cho ứng dụng
Android 4.3 thêm lớp Trace
bằng hai phương thức tĩnh,
beginSection()
và endSection()
,
cho phép bạn xác định các khối mã để đưa vào báo cáo systrace. Bằng cách tạo
của mã có thể theo dõi trong ứng dụng của bạn, nhật ký systrace cung cấp cho bạn thông tin chi tiết hơn
bản phân tích vị trí xảy ra ùn tắc nhẹ trong ứng dụng của bạn.
Để biết thông tin về cách sử dụng công cụ Systrace, hãy đọc bài viết Phân tích hoạt động hiển thị và hiệu suất với Systrace.
Bảo mật
Kho khoá Android cho khoá riêng tư của ứng dụng
Android hiện cung cấp một Trình cung cấp dịch vụ bảo mật Java tuỳ chỉnh trong KeyStore
có tên là Android Key Store, cho phép bạn tạo và lưu các khoá riêng tư
chỉ có ứng dụng của bạn mới có thể xem và sử dụng. Để tải Android Key Store, hãy truyền
"AndroidKeyStore"
đến KeyStore.getInstance()
.
Để quản lý thông tin xác thực riêng tư của ứng dụng trong Kho khoá Android, hãy tạo một khoá mới bằng
KeyPairGenerator
cho thành viên KeyPairGeneratorSpec
. Đầu tiên
nhận một thực thể của KeyPairGenerator
bằng cách gọi getInstance()
. Sau đó gọi
initialize()
, truyền vào đó một thực thể của
KeyPairGeneratorSpec
mà bạn có thể dùng
KeyPairGeneratorSpec.Builder
.
Cuối cùng, hãy nhận KeyPair
bằng cách gọi generateKeyPair()
.
Lưu trữ thông tin xác thực phần cứng
Android nay cũng hỗ trợ bộ nhớ dựa trên phần cứng cho KeyChain
của bạn
thông tin xác thực, giúp tăng tính bảo mật bằng cách không trích xuất khoá. Tức là một lần
những khoá này nằm trong kho khoá dựa trên phần cứng (Secure Element, TPM hoặc TrustZone), chúng có thể được dùng để
các thao tác mã hoá nhưng không thể xuất tài liệu khoá riêng tư. Ngay cả nhân hệ điều hành
không thể truy cập vào tài liệu khoá này. Mặc dù không phải tất cả thiết bị chạy Android đều hỗ trợ bộ nhớ bật
phần cứng, bạn có thể kiểm tra trong thời gian chạy xem có bộ nhớ dựa trên phần cứng không bằng cách gọi
KeyChain.IsBoundKeyAlgorithm()
.
Nội dung khai báo trong tệp kê khai
Các tính năng bắt buộc có thể khai báo
Các giá trị sau hiện đã được hỗ trợ trong <uses-feature>
để bạn có thể đảm bảo rằng ứng dụng của mình chỉ được cài đặt trên những thiết bị cung cấp các tính năng
mà ứng dụng của bạn cần.
FEATURE_APP_WIDGETS
- Khai báo rằng ứng dụng của bạn cung cấp một tiện ích ứng dụng và chỉ nên được cài đặt trên các thiết bị
bao gồm Màn hình chính hoặc vị trí tương tự nơi người dùng có thể nhúng tiện ích ứng dụng.
Ví dụ:
<uses-feature android:name="android.software.app_widgets" android:required="true" />
FEATURE_HOME_SCREEN
- Khai báo rằng ứng dụng của bạn hoạt động như một thiết bị thay thế Màn hình chính và chỉ nên được cài đặt trên
những thiết bị hỗ trợ ứng dụng trên Màn hình chính của bên thứ ba.
Ví dụ:
<uses-feature android:name="android.software.home_screen" android:required="true" />
FEATURE_INPUT_METHODS
- Khai báo rằng ứng dụng của bạn cung cấp phương thức nhập tuỳ chỉnh (bàn phím tích hợp
InputMethodService
) và chỉ nên được cài đặt trên các thiết bị hỗ trợ phương thức nhập của bên thứ ba. Ví dụ:<uses-feature android:name="android.software.input_methods" android:required="true" />
FEATURE_BLUETOOTH_LE
- Khai báo rằng ứng dụng của bạn sử dụng API Bluetooth năng lượng thấp và chỉ nên được cài đặt trên thiết bị
có khả năng giao tiếp với các thiết bị khác qua Bluetooth năng lượng thấp.
Ví dụ:
<uses-feature android:name="android.software.bluetooth_le" android:required="true" />
Quyền của người dùng
Các giá trị sau hiện đã được hỗ trợ trong <uses-permission>
để khai báo
các quyền mà ứng dụng của bạn yêu cầu để truy cập một số API nhất định.
BIND_NOTIFICATION_LISTENER_SERVICE
- Bắt buộc khi sử dụng các API
NotificationListenerService
mới. SEND_RESPOND_VIA_MESSAGE
- Bắt buộc để nhận
ACTION_RESPOND_VIA_MESSAGE
ý định.
Để có cái nhìn chi tiết về tất cả các thay đổi đối với API trong Android 4.3, hãy xem Báo cáo khác biệt về API.