Cấp độ API: 19
Android 4.4 (KITKAT
) là một bản phát hành mới dành cho nền tảng Android, cung cấp các tính năng mới cho người dùng và nhà phát triển ứng dụng. Tài liệu này giới thiệu các API mới đáng chú ý nhất.
Là nhà phát triển ứng dụng, bạn nên tải hình ảnh hệ thống và nền tảng SDK Android 4.4 xuống qua Trình quản lý SDK càng sớm càng tốt. Nếu bạn không có thiết bị chạy Android 4.4 để kiểm thử ứng dụng, hãy sử dụng ảnh hệ thống Android 4.4 để kiểm thử ứng dụng trên trình mô phỏng Android. Sau đó, hãy xây dựng ứng dụng dựa trên nền tảng Android 4.4 để 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 một cách hiệu quả hơn cho các thiết bị chạy Android 4.4, bạn nên đặt targetSdkVersion
thành "19"
, cài đặt ứng dụng này trên ảnh hệ thống Android 4.4, kiểm thử rồi phát hành bản cập nhật với thay đổi này.
Bạn có thể sử dụng API trong Android 4.4 trong khi vẫn hỗ trợ các phiên bản cũ hơn bằng cách thêm
điều kiện vào mã để kiểm tra cấp độ API 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 phần Hỗ trợ nhiều phiên bản 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 Cấp độ API là gì?
Thay đổi quan trọng về hành vi
Nếu bạn từng phát hành một ứng dụng dành cho Android, hãy lưu ý rằng các thay đổi trong Android 4.4 có thể ảnh hưởng đến ứng dụng của bạn.
Nếu ứng dụng của bạn đọc từ bộ nhớ ngoài...
Ứng dụng của bạn không thể đọc các tệp được chia sẻ trên bộ nhớ ngoài khi chạy trên Android 4.4, trừ khi ứng dụng có quyền READ_EXTERNAL_STORAGE
. Tức là không thể truy cập vào các tệp trong thư mục do getExternalStoragePublicDirectory()
trả về nữa nếu không có quyền. Tuy nhiên, nếu chỉ cần truy cập vào các thư mục dành riêng cho ứng dụng do getExternalFilesDir()
cung cấp, thì bạn không cần quyền READ_EXTERNAL_STORAGE
.
Nếu ứng dụng của bạn dùng WebView...
Ứng dụng của bạn có thể hoạt động theo cách khác khi chạy trên Android 4.4, đặc biệt là khi bạn cập nhật targetSdkVersion
của ứng dụng lên "19" trở lên.
Mã cơ sở cho lớp WebView
và các API liên quan đã được nâng cấp để dựa trên bản tổng quan nhanh hiện đại của mã nguồn Chromium. Tính năng này mang đến nhiều điểm cải tiến về hiệu suất, khả năng hỗ trợ các tính năng HTML5 mới và hỗ trợ gỡ lỗi từ xa đối với nội dung WebView
của bạn. Phạm vi của bản nâng cấp này có nghĩa là nếu ứng dụng của bạn sử dụng WebView
, thì trong một số trường hợp, hành vi của ứng dụng đó có thể bị ảnh hưởng. Mặc dù các thay đổi về hành vi đã biết được ghi nhận và phần lớn chỉ ảnh hưởng đến ứng dụng của bạn khi bạn cập nhật targetSdkVersion
của ứng dụng lên "19" trở lên, WebView
mới hoạt động ở "chế độ tương thích" để cung cấp một số chức năng cũ trong ứng dụng nhắm đến API cấp 18 trở xuống. Có thể ứng dụng của bạn phụ thuộc vào các hành vi không xác định trong phiên bản WebView
trước.
Vì vậy, nếu ứng dụng hiện tại của bạn sử dụng WebView
, bạn cần thử nghiệm trên Android 4.4 càng sớm càng tốt và tham khảo bài viết Di chuyển sang WebView trong Android 4.4 để biết thông tin về việc ứng dụng của bạn có thể bị ảnh hưởng như thế nào khi cập nhật targetSdkVersion
lên "19" trở lên.
Nếu ứng dụng của bạn sử dụng AlarmManager...
Khi bạn đặt targetSdkVersion
của ứng dụng thành "19" trở lên, các chuông báo mà bạn tạo bằng set()
hoặc setRepeating()
sẽ không chính xác.
Để cải thiện hiệu quả sử dụng pin, giờ đây, Android sẽ gộp nhóm chuông báo của tất cả ứng dụng vào những thời điểm tương tự nhau một cách hợp lý. Nhờ đó, hệ thống sẽ đánh thức thiết bị một lần thay vì nhiều lần để xử lý từng chuông báo.
Nếu chuông báo của bạn không liên kết với giờ đồng hồ chính xác, nhưng vẫn cần phải gọi chuông báo trong một khoảng thời gian cụ thể (chẳng hạn như từ 2 giờ chiều đến 4 giờ chiều), thì bạn có thể sử dụng phương thức setWindow()
mới. Phương thức này chấp nhận thời điểm "sớm nhất" của chuông báo và một "khoảng thời gian" sau khoảng thời gian sớm nhất mà hệ thống nên gọi chuông báo.
Nếu bạn phải ghim chuông báo vào thời gian đồng hồ chính xác (chẳng hạn như lời nhắc sự kiện trên lịch), thì bạn có thể sử dụng phương thức setExact()
mới.
Hành vi tạo lô không chính xác này chỉ áp dụng cho các ứng dụng đã cập nhật. Nếu bạn đặt targetSdkVersion
thành "18" trở xuống, chuông báo sẽ tiếp tục hoạt động như trên các phiên bản trước khi chạy trên Android 4.4.
Nếu ứng dụng của bạn đồng bộ hoá dữ liệu bằng ContentResolver...
Khi bạn đặt targetSdkVersion
của ứng dụng thành "19" trở lên, việc tạo quy trình đồng bộ hoá với addPeriodicSync()
sẽ thực hiện các hoạt động đồng bộ hoá trong khoảng thời gian linh hoạt mặc định là khoảng 4% khoảng thời gian mà bạn chỉ định. Ví dụ: nếu tần suất thăm dò ý kiến là 24 giờ, thì hoạt động đồng bộ hoá của bạn có thể diễn ra trong khoảng thời gian khoảng một giờ mỗi ngày, thay vì vào cùng một thời điểm chính xác mỗi ngày.
Để chỉ định khoảng thời gian linh hoạt của riêng bạn cho các hoạt động đồng bộ hoá, bạn nên bắt đầu sử dụng phương thức requestSync()
mới. Để biết thêm thông tin chi tiết, hãy xem phần bên dưới về Bộ điều hợp đồng bộ hoá.
Hành vi khoảng thời gian linh hoạt này chỉ áp dụng cho các ứng dụng đã cập nhật. Nếu bạn đã đặt targetSdkVersion
thành "18" trở xuống, các yêu cầu đồng bộ hóa hiện có của bạn sẽ tiếp tục hoạt động như có trên các phiên bản trước khi chạy trên Android 4.4.
Khung in
Android hiện có một khung hoàn chỉnh cho phép người dùng in bất kỳ tài liệu nào bằng máy in kết nối qua Wi-Fi, Bluetooth hoặc các dịch vụ khác. Hệ thống này xử lý giao dịch giữa một ứng dụng muốn in tài liệu và các dịch vụ gửi lệnh in tới máy in. Khung android.print
cung cấp tất cả API cần thiết để chỉ định tài liệu in và gửi tài liệu đó đến hệ thống để in. Những API mà bạn thực sự cần cho một lệnh in nhất định sẽ tuỳ thuộc vào nội dung của bạn.
In nội dung chung chung
Nếu muốn in nội dung trên giao diện người dùng dưới dạng tài liệu, trước tiên, bạn cần tạo một lớp con của PrintDocumentAdapter
. Trong lớp này, bạn phải triển khai một số phương thức gọi lại, bao gồm cả onLayout()
để thiết lập bố cục dựa trên các thuộc tính in được cung cấp và onWrite()
để chuyển đổi tuần tự nội dung có thể in thành ParcelFileDescriptor
.
Để ghi nội dung vào ParcelFileDescriptor
, bạn phải chuyển nội dung đó ở dạng PDF. Các API PdfDocument
mới giúp bạn thực hiện việc này một cách thuận tiện bằng cách cung cấp Canvas
từ getCanvas()
, nơi bạn có thể vẽ nội dung có thể in trên đó. Sau đó, ghi PdfDocument
vào ParcelFileDescriptor
bằng phương thức writeTo()
.
Sau khi xác định phương thức triển khai cho PrintDocumentAdapter
, bạn có thể thực thi các lệnh in theo yêu cầu của người dùng bằng cách sử dụng phương thức PrintManager
(print()
) để lấy PrintDocumentAdapter
làm một trong các đối số của phương thức này.
In hình ảnh
Nếu bạn chỉ muốn in ảnh hoặc các bitmap khác, thì các API trợ giúp trong thư viện hỗ trợ sẽ làm mọi việc cho bạn. Bạn chỉ cần tạo một thực thể mới của PrintHelper
, đặt chế độ tỷ lệ bằng setScaleMode()
, sau đó truyền Bitmap
đến printBitmap()
. Vậy là xong. Thư viện này xử lý tất cả hoạt động tương tác còn lại với hệ thống để phân phối bitmap đến máy in.
Dịch vụ in xây dựng
Là nhà sản xuất thiết bị gốc (OEM) máy in, bạn có thể sử dụng khung android.printservice
để cung cấp khả năng tương tác với máy in trên thiết bị Android. Bạn có thể xây dựng và phân phối dịch vụ in dưới dạng tệp APK mà người dùng có thể cài đặt trên thiết bị của họ . Ứng dụng dịch vụ in hoạt động chủ yếu dưới dạng dịch vụ không có giao diện người dùng bằng cách phân lớp con lớp PrintService
. Lớp này nhận lệnh in từ hệ thống rồi truyền lệnh đó đến máy in của ứng dụng đó bằng giao thức thích hợp.
Để biết thêm thông tin về cách in nội dung ứng dụng, hãy đọc bài viết In nội dung.
Nhà cung cấp dịch vụ SMS
Nhà cung cấp nội dung Telephony
("Nhà cung cấp SMS") cho phép các ứng dụng đọc và ghi tin nhắn SMS và MMS trên thiết bị. Dữ liệu này bao gồm các bảng chứa tin nhắn SMS và MMS đã nhận, đã soạn, đã gửi, đang chờ xử lý và nhiều tin nhắn khác.
Kể từ Android 4.4, phần cài đặt hệ thống cho phép người dùng chọn "ứng dụng SMS mặc định". Sau khi được chọn, chỉ ứng dụng SMS mặc định mới có thể ghi vào Nhà cung cấp dịch vụ SMS và chỉ ứng dụng SMS mặc định mới nhận được thông báo SMS_DELIVER_ACTION
khi người dùng nhận một tin nhắn SMS hoặc WAP_PUSH_DELIVER_ACTION
khi người dùng nhận được tin nhắn MMS. Ứng dụng SMS mặc định chịu trách nhiệm ghi thông tin chi tiết cho Nhà cung cấp tin nhắn SMS khi nhận được hoặc gửi một tin nhắn mới.
Các ứng dụng khác không được chọn làm ứng dụng SMS mặc định chỉ có thể đọc Nhà cung cấp tin nhắn SMS nhưng cũng có thể được thông báo khi có tin nhắn SMS mới bằng cách nghe thông báo SMS_RECEIVED_ACTION
. Đây là một tin truyền không thể huỷ được mà có thể được gửi đến nhiều ứng dụng. Thông báo này dành cho các ứng dụng---trong khi không được chọn làm ứng dụng SMS mặc định---cần đọc các tin nhắn đến đặc biệt chẳng hạn như để thực hiện xác minh số điện thoại.
Để biết thêm thông tin, hãy đọc bài đăng trên blog Chuẩn bị ứng dụng SMS của bạn sẵn sàng cho KitKat.
Không dây và kết nối
Mô phỏng thẻ dựa trên máy chủ
Giờ đây, các ứng dụng Android có thể mô phỏng thẻ NFC ISO14443-4 (ISO-DEP) sử dụng APDU để trao đổi dữ liệu (như quy định trong ISO7816-4). Điều này cho phép thiết bị hỗ trợ NFC chạy Android 4.4 mô phỏng nhiều thẻ NFC cùng lúc và cho phép thiết bị thanh toán NFC hoặc đầu đọc NFC khác bắt đầu giao dịch bằng thẻ NFC phù hợp dựa trên giá trị nhận dạng ứng dụng (AID).
Nếu bạn muốn mô phỏng một thẻ NFC đang sử dụng các giao thức này trong ứng dụng, hãy tạo một thành phần dịch vụ dựa trên lớp HostApduService
. Ngược lại, nếu ứng dụng dùng một phần tử bảo mật để mô phỏng thẻ, thì bạn cần tạo một dịch vụ dựa trên lớp OffHostApduService
. Lớp này sẽ không trực tiếp tham gia vào các giao dịch nhưng cần đăng ký các AID mà phần tử bảo mật cần phải xử lý.
Để biết thêm thông tin, hãy đọc hướng dẫn Mô phỏng thẻ NFC.
Chế độ đọc NFC
Chế độ đọc NFC mới cho phép một hoạt động giới hạn mọi hoạt động NFC thành chỉ đọc các loại thẻ mà hoạt động quan tâm khi ở nền trước. Bạn có thể bật chế độ đọc cho hoạt động của mình bằng enableReaderMode()
, cho phép triển khai NfcAdapter.ReaderCallback
để nhận lệnh gọi lại khi phát hiện thấy các thẻ mới.
Khả năng mới này, cùng với quy trình mô phỏng thẻ máy chủ, cho phép Android hoạt động trên cả hai đầu giao diện thanh toán di động: Một thiết bị hoạt động như một thiết bị thanh toán (thiết bị chạy hoạt động ở chế độ đọc) và một thiết bị khác hoạt động như máy khách thanh toán (một thiết bị mô phỏng thẻ NFC).
Bộ phát hồng ngoại
Giờ đây, khi chạy trên một thiết bị có bộ phát hồng ngoại (IR), bạn có thể truyền tín hiệu IR bằng các API ConsumerIrManager
. Để nhận một thực thể của ConsumerIrManager
, hãy gọi getSystemService()
với đối số là CONSUMER_IR_SERVICE
. Sau đó, bạn có thể truy vấn tần số hồng ngoại được hỗ trợ của thiết bị bằng getCarrierFrequencies()
và truyền tín hiệu bằng cách truyền tần số và mẫu tín hiệu mong muốn bằng transmit()
.
Trước tiên, bạn phải luôn kiểm tra xem thiết bị có bộ phát IR hay không bằng cách gọi hasIrEmitter()
. Tuy nhiên, nếu ứng dụng của bạn chỉ tương thích với các thiết bị có bộ phát này, thì bạn nên thêm phần tử <uses-feature>
vào tệp kê khai cho "android.hardware.consumerir"
(FEATURE_CONSUMER_IR
).
Nội dung đa phương tiện
Phát thích ứng
Giờ đây, các API MediaCodec
có thể hỗ trợ tính năng phát video thích ứng, cho phép thay đổi liền mạch độ phân giải trong khi phát trên Surface
– bạn có thể cung cấp khung đầu vào của bộ giải mã có độ phân giải mới và độ phân giải của vùng đệm đầu ra thay đổi mà không có khoảng trống đáng kể.
Bạn có thể bật tính năng phát thích ứng bằng cách thêm hai phím vào MediaFormat
để chỉ định độ phân giải tối đa mà ứng dụng của bạn yêu cầu trong bộ mã hoá và giải mã: KEY_MAX_WIDTH
và KEY_MAX_HEIGHT
. Sau khi thêm những giá trị này vào MediaFormat
, hãy truyền MediaFormat
vào thực thể MediaCodec
bằng configure()
.
Bộ mã hoá và giải mã sẽ chuyển đổi liền mạch giữa các độ phân giải bằng hoặc nhỏ hơn các giá trị này. Bộ mã hoá và giải mã cũng có thể hỗ trợ các độ phân giải lớn hơn mức tối đa đã chỉ định (miễn là nằm trong giới hạn của cấu hình được hỗ trợ), nhưng việc chuyển đổi sang độ phân giải lớn hơn có thể không liền mạch.
Để thay đổi độ phân giải trong khi giải mã video H.264, hãy tiếp tục xếp các khung hình vào hàng đợi bằng MediaCodec.queueInputBuffer(), nhưng hãy chắc chắn rằng bạn cung cấp các giá trị Sequence Parameter Set (SPS) và hình ảnh Set (PPS) mới cùng với khung làm mới bộ giải mã tức thì (IDR) trong một bộ đệm duy nhất.
Tuy nhiên, trước khi định cấu hình bộ mã hoá và giải mã cho tính năng phát thích ứng, bạn phải xác minh rằng thiết bị hỗ trợ tính năng phát thích ứng bằng cách gọi isFeatureSupported(String)
bằng FEATURE_AdaptivePlayback
.
Lưu ý: Tính năng hỗ trợ phát lại thích ứng tuỳ thuộc vào từng nhà cung cấp. Một số bộ mã hoá và giải mã có thể cần nhiều bộ nhớ hơn đối với các gợi ý có độ phân giải lớn hơn. Do đó, bạn nên đặt độ phân giải tối đa dựa trên tài liệu nguồn mà bạn đang giải mã.
Dấu thời gian của âm thanh theo yêu cầu
Để tạo điều kiện đồng bộ hoá âm thanh và video, lớp AudioTimestamp
mới cung cấp thông tin chi tiết về dòng thời gian của một "khung hình" cụ thể trong luồng âm thanh do AudioTrack
xử lý. Để có được dấu thời gian mới nhất, hãy tạo thực thể cho đối tượng AudioTimestamp
rồi truyền đối tượng đó đến getTimestamp()
. Nếu yêu cầu dấu thời gian thành công, thực thể AudioTrack
sẽ được điền vào một vị trí trong đơn vị khung hình, cùng với thời gian ước tính khi khung hình đó được trình bày hoặc được cam kết hiển thị.
Bạn có thể sử dụng giá trị của nanoTime
trong AudioTimestamp
(là đơn điệu) để tìm khung hình video liên kết gần nhất so với framePosition
. Nhờ vậy, bạn có thể thả, sao chép hoặc nội suy khung hình video cho khớp với âm thanh. Ngoài ra, bạn có thể xác định thời gian delta giữa giá trị của nanoTime
và thời gian dự kiến của khung hình video trong tương lai (có cân nhắc tốc độ lấy mẫu) để dự đoán khung âm thanh nào được mong đợi tại cùng thời điểm với khung hình video.
Trình đọc hình ảnh trên nền tảng
API ImageReader
mới cho phép bạn truy cập trực tiếp vào vùng đệm hình ảnh khi chúng được kết xuất vào Surface
. Bạn có thể lấy ImageReader
bằng phương thức tĩnh newInstance()
. Sau đó, hãy gọi getSurface()
để tạo Surface
mới và phân phối dữ liệu hình ảnh qua một nhà sản xuất như MediaPlayer
hoặc MediaCodec
. Để nhận thông báo khi có hình ảnh mới trên nền tảng, hãy triển khai giao diện ImageReader.OnImageAvailableListener
và đăng ký giao diện đó với setOnImageAvailableListener()
.
Bây giờ, khi bạn vẽ nội dung vào Surface
, ImageReader.OnImageAvailableListener
sẽ nhận được lệnh gọi đến onImageAvailable()
khi mỗi khung hình ảnh mới có sẵn, cung cấp cho bạn ImageReader
tương ứng. Bạn có thể sử dụng ImageReader
để lấy dữ liệu hình ảnh của khung dưới dạng đối tượng Image
bằng cách gọi acquireLatestImage()
hoặc acquireNextImage()
.
Đối tượng Image
cung cấp quyền truy cập trực tiếp vào dấu thời gian, định dạng, kích thước và dữ liệu pixel của hình ảnh trong ByteBuffer
. Tuy nhiên, để lớp Image
diễn giải hình ảnh của bạn, hình ảnh phải được định dạng theo một trong các kiểu được xác định bằng các hằng số trong ImageFormat
hoặc PixelFormat
.
Đo lường giá trị cao nhất và RMS
Giờ đây, bạn có thể truy vấn đỉnh và RMS của luồng âm thanh hiện tại qua Visualizer
bằng cách tạo một thực thể mới của Visualizer.MeasurementPeakRms
rồi truyền dữ liệu đó vào getMeasurementPeakRms()
. Khi bạn gọi phương thức này, các giá trị cao nhất và RMS của Visualizer.MeasurementPeakRms
đã cho sẽ được đặt thành các giá trị đo được mới nhất.
Chất tăng âm thanh
LoudnessEnhancer
là một lớp con mới của AudioEffect
cho phép bạn tăng âm lượng âm thanh của MediaPlayer
hoặc AudioTrack
. Tính năng này có thể đặc biệt hữu ích khi kết hợp với phương thức getMeasurementPeakRms()
mới nêu trên để tăng âm lượng của bản âm thanh được nói trong khi nội dung nghe nhìn khác đang phát.
Bộ điều khiển từ xa
Android 4.0 (API cấp 14) đã ra mắt các API RemoteControlClient
cho phép các ứng dụng đa phương tiện sử dụng các sự kiện của trình điều khiển nội dung nghe nhìn từ các ứng dụng từ xa, chẳng hạn như các nút điều khiển nội dung nghe nhìn trên màn hình khoá. Giờ đây, các API RemoteController
mới cho phép bạn tạo bộ điều khiển từ xa của riêng mình, hỗ trợ việc tạo các ứng dụng và thiết bị ngoại vi mới, sáng tạo có thể điều khiển chế độ phát bất kỳ ứng dụng đa phương tiện nào tích hợp với RemoteControlClient
.
Để tạo bộ điều khiển từ xa, bạn có thể triển khai giao diện người dùng theo bất kỳ cách nào mình muốn. Tuy nhiên, để phân phối các sự kiện nút đa phương tiện tới ứng dụng đa phương tiện của người dùng, bạn phải tạo một dịch vụ mở rộng lớp NotificationListenerService
và triển khai giao diện RemoteController.OnClientUpdateListener
. Việc sử dụng NotificationListenerService
làm cơ sở rất quan trọng vì nó đưa ra các hạn chế thích hợp về quyền riêng tư. Theo đó, người dùng phải bật ứng dụng của bạn làm trình nghe thông báo trong phần cài đặt bảo mật của hệ thống.
Lớp NotificationListenerService
bao gồm một số phương thức trừu tượng mà bạn phải triển khai, nhưng nếu chỉ quan tâm đến các sự kiện trình điều khiển nội dung đa phương tiện để xử lý việc phát nội dung đa phương tiện, thì bạn có thể để trống phương thức triển khai các phương thức đó và thay vào đó, hãy tập trung vào các phương thức RemoteController.OnClientUpdateListener
.
Điểm xếp hạng của bộ điều khiển từ xa
Android 4.4 được xây dựng dựa trên các tính năng hiện có dành cho các ứng dụng điều khiển từ xa (ứng dụng nhận sự kiện điều khiển nội dung nghe nhìn thông qua RemoteControlClient
) bằng cách bổ sung khả năng xếp hạng bản nhạc hiện tại trên bộ điều khiển từ xa.
Lớp Rating
mới bao gồm thông tin về điểm xếp hạng của người dùng. Mức phân loại được xác định theo kiểu phân loại (RATING_HEART
, RATING_THUMB_UP_DOWN
, RATING_3_STARS
, RATING_4_STARS
, RATING_5_STARS
hoặc RATING_PERCENTAGE
) và giá trị phân loại phù hợp với kiểu đó.
Cách cho phép người dùng xếp hạng tuyến đường của bạn bằng bộ điều khiển từ xa:
- Tín hiệu cho biết bạn muốn hiển thị giao diện người dùng điểm xếp hạng cho người dùng (nếu có) bằng cách thêm cờ
FLAG_KEY_MEDIA_RATING
vàosetTransportControlFlags()
. - Gọi
editMetadata()
để truy xuấtRemoteControlClient.MetadataEditor
và truyền nóRATING_KEY_BY_USER
bằngaddEditableKey()
. - Sau đó, hãy chỉ định kiểu xếp hạng bằng cách gọi
putObject()
rồi truyền vào đóRATING_KEY_BY_USER
làm khoá và một trong các kiểu xếp hạng ở trên làm giá trị.
Để nhận lệnh gọi lại khi người dùng thay đổi điểm xếp hạng trên bộ điều khiển từ xa, hãy triển khai giao diện RemoteControlClient.OnMetadataUpdateListener
mới và truyền một thực thể đến setMetadataUpdateListener()
. Khi người dùng thay đổi điểm xếp hạng, RemoteControlClient.OnMetadataUpdateListener
của bạn sẽ nhận được lệnh gọi đến onMetadataUpdate()
, truyền RATING_KEY_BY_USER
làm khoá và đối tượng Rating
làm giá trị.
Phụ đề
VideoView
hiện hỗ trợ các bản phụ đề trên WebVTT khi phát video Luồng trực tiếp qua HTTP (HLS), hiển thị bản phụ đề theo tùy chọn phụ đề mà người dùng đã xác định trong phần cài đặt hệ thống.
Bạn cũng có thể cung cấp các bản phụ đề WebVTT cho VideoView
bằng phương thức addSubtitleSource()
. Phương thức này chấp nhận một InputStream
chứa dữ liệu phụ đề và đối tượng MediaFormat
chỉ định định dạng cho dữ liệu phụ đề. Bạn có thể chỉ định định dạng này bằng cách sử dụng createSubtitleFormat()
. Những phụ đề này cũng xuất hiện trên video theo lựa chọn ưu tiên của người dùng.
Nếu không sử dụng VideoView
để hiển thị nội dung video thì bạn nên tạo lớp phủ phụ đề sao cho phù hợp nhất có thể với lựa chọn ưu tiên của người dùng về phụ đề. API CaptioningManager
mới cho phép bạn truy vấn các lựa chọn ưu tiên về phụ đề của người dùng, bao gồm cả các kiểu do CaptioningManager.CaptionStyle
xác định, chẳng hạn như kiểu chữ và màu. Trong trường hợp người dùng điều chỉnh một số lựa chọn ưu tiên khi video đã bắt đầu, bạn nên lắng nghe những thay đổi đối với lựa chọn ưu tiên bằng cách đăng ký một phiên bản của CaptioningManager.CaptioningChangeListener
để nhận lệnh gọi lại khi các lựa chọn ưu tiên thay đổi, sau đó cập nhật phụ đề nếu cần.
Ảnh động và đồ hoạ
Cảnh và hiệu ứng chuyển cảnh
Khung android.transition
mới cung cấp các API hỗ trợ ảnh động giữa nhiều trạng thái của giao diện người dùng. Một tính năng chính là khả năng giúp bạn xác định các trạng thái riêng biệt của giao diện người dùng (còn gọi là "cảnh") bằng cách tạo một bố cục riêng cho mỗi trạng thái. Khi bạn muốn tạo hiệu ứng động từ cảnh này sang cảnh khác, hãy thực hiện thao tác "chuyển đổi", giúp tính toán ảnh động cần thiết để thay đổi bố cục từ cảnh hiện tại sang cảnh tiếp theo.
Để chuyển đổi giữa hai cảnh, thông thường bạn cần thực hiện những việc sau:
- Chỉ định
ViewGroup
chứa các thành phần giao diện người dùng mà bạn muốn thay đổi. - Chỉ định bố cục thể hiện kết quả cuối cùng của thay đổi (cảnh tiếp theo).
- Chỉ định loại chuyển đổi sẽ tạo hiệu ứng ảnh động cho thay đổi về bố cục.
- Thực hiện hiệu ứng chuyển đổi.
Bạn có thể sử dụng đối tượng Scene
để hoàn thành bước 1 và 2. Scene
chứa siêu dữ liệu mô tả các thuộc tính của bố cục cần thiết để thực hiện chuyển đổi, bao gồm cả khung hiển thị mẹ và bố cục của cảnh. Bạn có thể tạo Scene
bằng hàm khởi tạo lớp hoặc phương thức tĩnh getSceneForLayout()
.
Sau đó, bạn phải sử dụng TransitionManager
để hoàn tất bước 3 và 4. Có một cách là truyền Scene
sang phương thức tĩnh go()
. Thao tác này sẽ tìm khung hiển thị mẹ của cảnh trong bố cục hiện tại và thực hiện hiệu ứng chuyển đổi trên các khung hiển thị con để đạt đến bố cục do Scene
xác định.
Ngoài ra, bạn không cần tạo đối tượng Scene
. Thay vào đó, bạn có thể gọi beginDelayedTransition()
, chỉ định ViewGroup
chứa các khung hiển thị mà bạn muốn thay đổi. Sau đó, hãy thêm, xoá hoặc định cấu hình lại các chế độ xem mục tiêu. Sau khi hệ thống bố trí các thay đổi nếu cần, quá trình chuyển đổi sẽ bắt đầu tạo ảnh động cho tất cả các chế độ xem bị ảnh hưởng.
Để có thêm quyền kiểm soát, bạn có thể xác định các tập hợp hiệu ứng chuyển đổi sẽ diễn ra giữa các cảnh được xác định trước bằng cách sử dụng tệp XML trong thư mục res/transition/
của dự án. Bên trong một phần tử <transitionManager>
, hãy chỉ định một hoặc nhiều thẻ <transition>
mà mỗi thẻ chỉ định một cảnh (tham chiếu đến tệp bố cục) và hiệu ứng chuyển đổi sẽ áp dụng khi vào và/hoặc thoát khỏi cảnh đó. Sau đó, tăng cường tập hợp hiệu ứng chuyển đổi này bằng inflateTransitionManager()
. Sử dụng TransitionManager
được trả về để thực thi từng hiệu ứng chuyển đổi bằng transitionTo()
, truyền một Scene
được biểu thị bằng một trong các thẻ <transition>
. Bạn cũng có thể xác định các nhóm hiệu ứng chuyển đổi theo phương thức lập trình bằng các API TransitionManager
.
Khi chỉ định hiệu ứng chuyển đổi, bạn có thể dùng một số loại định sẵn được xác định bằng các lớp con của Transition
, chẳng hạn như Fade
và ChangeBounds
. Nếu bạn không chỉ định loại chuyển đổi, hệ thống sẽ sử dụng AutoTransition
theo mặc định để tự động làm mờ, di chuyển và đổi kích thước khung hiển thị khi cần. Ngoài ra, bạn có thể tạo hiệu ứng chuyển đổi tuỳ chỉnh bằng cách mở rộng bất kỳ lớp nào trong số này để thực hiện ảnh động theo ý muốn. Hiệu ứng chuyển đổi tuỳ chỉnh có thể theo dõi mọi thay đổi về thuộc tính mà bạn muốn và tạo bất kỳ ảnh động nào bạn muốn dựa trên các thay đổi đó. Ví dụ: bạn có thể cung cấp một lớp con của Transition
giúp theo dõi các thay đổi đối với thuộc tính "rotation" của khung hiển thị, sau đó tạo ảnh động cho mọi thay đổi.
Để biết thêm thông tin, hãy xem tài liệu TransitionManager
.
Tạm dừng trình tạo hình động
API Animator
hiện cho phép bạn tạm dừng và tiếp tục ảnh động đang diễn ra bằng các phương thức pause()
và resume()
.
Để theo dõi trạng thái của ảnh động, bạn có thể triển khai giao diện Animator.AnimatorPauseListener
. Giao diện này cung cấp lệnh gọi lại khi một ảnh động tạm dừng và tiếp tục: pause()
và resume()
. Sau đó, thêm trình nghe vào đối tượng Animator
bằng addPauseListener()
.
Ngoài ra, bạn có thể phân lớp con của lớp trừu tượng AnimatorListenerAdapter
, hiện bao gồm các phương thức triển khai trống cho các lệnh gọi lại tạm dừng và tiếp tục do Animator.AnimatorPauseListener
xác định.
bitmap có thể sử dụng lại
Giờ đây, bạn có thể sử dụng lại bất kỳ bitmap có thể thay đổi nào trong BitmapFactory
để giải mã bất kỳ bitmap nào khác, ngay cả khi bitmap mới có kích thước khác, miễn là số byte nhận được của bitmap đã giải mã (có từ getByteCount()
) nhỏ hơn hoặc bằng số lượng byte được phân bổ của bitmap tái sử dụng (có từ getAllocationByteCount()
. Để biết thêm thông tin, hãy xem inBitmap
.
Các API mới của Bitmap
cho phép định cấu hình lại tương tự để sử dụng lại bên ngoài BitmapFactory
(để tạo bitmap thủ công hoặc logic giải mã tuỳ chỉnh). Giờ đây, bạn có thể đặt kích thước của bitmap bằng các phương thức setHeight()
và setWidth()
, đồng thời chỉ định một Bitmap.Config
mới bằng setConfig()
mà không ảnh hưởng đến hoạt động phân bổ bitmap cơ bản. Phương thức reconfigure()
cũng cung cấp một cách thuận tiện để kết hợp các thay đổi này bằng một lệnh gọi.
Tuy nhiên, bạn không nên định cấu hình lại một bitmap hiện đang được hệ thống khung hiển thị sử dụng, vì vùng đệm pixel cơ bản sẽ không được ánh xạ lại theo cách có thể dự đoán được.
Nội dung của người dùng
Khung truy cập bộ nhớ
Trên các phiên bản Android trước, nếu bạn muốn ứng dụng của mình truy xuất một loại tệp cụ thể từ một ứng dụng khác, ứng dụng đó phải gọi một ý định bằng thao tác ACTION_GET_CONTENT
. Thao tác này vẫn là cách thích hợp để yêu cầu một tệp bạn muốn nhập vào ứng dụng. Tuy nhiên, Android 4.4 ra mắt thao tác ACTION_OPEN_DOCUMENT
, cho phép người dùng chọn một tệp thuộc loại cụ thể và cấp cho ứng dụng của bạn quyền đọc dài hạn đối với tệp đó (có thể có quyền ghi) mà không cần nhập tệp vào ứng dụng của bạn.
Nếu đang phát triển một ứng dụng cung cấp dịch vụ lưu trữ cho tệp (chẳng hạn như dịch vụ lưu vào đám mây), thì bạn có thể tham gia giao diện người dùng hợp nhất này để chọn tệp bằng cách triển khai một nhà cung cấp nội dung làm lớp con của lớp DocumentsProvider
mới. Lớp con của DocumentsProvider
phải có một bộ lọc ý định chấp nhận thao tác PROVIDER_INTERFACE
("android.content.action.DOCUMENTS_PROVIDER"
). Sau đó, bạn phải triển khai 4 phương thức trừu tượng trong DocumentsProvider
:
queryRoots()
- Hàm này phải trả về
Cursor
mô tả tất cả thư mục gốc của bộ nhớ tài liệu, sử dụng các cột được xác định trongDocumentsContract.Root
. queryChildDocuments()
- Hàm này phải trả về
Cursor
mô tả tất cả các tệp trong thư mục được chỉ định, sử dụng các cột được xác định trongDocumentsContract.Document
. queryDocument()
- Hàm này phải trả về
Cursor
mô tả tệp cụ thể, sử dụng các cột được xác định trongDocumentsContract.Document
. openDocument()
- Hàm này phải trả về
ParcelFileDescriptor
đại diện cho tệp đã chỉ định. Hệ thống gọi phương thức này sau khi người dùng chọn một tệp và ứng dụng khách yêu cầu quyền truy cập vào tệp đó bằng cách gọiopenFileDescriptor()
.
Để biết thêm thông tin, hãy xem hướng dẫn về Khung truy cập bộ nhớ.
Quyền truy cập vào bộ nhớ ngoài
Giờ đây, bạn có thể đọc và ghi các tệp dành riêng cho ứng dụng trên phương tiện bộ nhớ ngoài phụ, chẳng hạn như khi một thiết bị cung cấp cả bộ nhớ được mô phỏng và thẻ SD. Phương thức mới getExternalFilesDirs()
hoạt động giống như phương thức getExternalFilesDir()
hiện có, ngoại trừ phương thức trả về một mảng gồm các đối tượng File
. Trước khi đọc hoặc ghi vào bất kỳ đường dẫn nào mà phương thức này trả về, hãy truyền đối tượng File
vào phương thức getStorageState()
mới để xác minh bộ nhớ hiện có sẵn.
Các phương thức khác để truy cập vào thư mục bộ nhớ đệm dành riêng cho ứng dụng và thư mục OBB hiện cũng có các phiên bản tương ứng cung cấp quyền truy cập vào các thiết bị lưu trữ phụ: getExternalCacheDirs()
và getObbDirs()
tương ứng.
Mục nhập đầu tiên trong mảng File
được trả về được coi là bộ nhớ ngoài chính của thiết bị, giống với File
mà các phương thức hiện có như getExternalFilesDir()
trả về.
Lưu ý: Kể từ Android 4.4, nền tảng này không còn yêu cầu ứng dụng của bạn phải có WRITE_EXTERNAL_STORAGE
hoặc READ_EXTERNAL_STORAGE
khi bạn chỉ cần truy cập vào các khu vực dành riêng cho ứng dụng của bộ nhớ ngoài bằng các phương thức trên. Tuy nhiên, bạn cần có quyền nếu muốn truy cập vào các khu vực có thể chia sẻ của bộ nhớ ngoài, do getExternalStoragePublicDirectory()
cung cấp.
Bộ điều hợp đồng bộ hoá
Phương thức requestSync()
mới trong ContentResolver
giúp đơn giản hoá một số quy trình để xác định yêu cầu đồng bộ hoá cho ContentProvider
bằng cách đóng gói các yêu cầu trong đối tượng SyncRequest
mới mà bạn có thể tạo bằng SyncRequest.Builder
. Các thuộc tính trong SyncRequest
cung cấp chức năng giống như các lệnh gọi đồng bộ hoá ContentProvider
hiện có nhưng thêm khả năng chỉ định việc sẽ đồng bộ hoá nếu mạng được đo lượng dữ liệu, bằng cách bật setDisallowMetered()
.
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_GEOMAGNETIC_ROTATION_VECTOR
mới cung cấp dữ liệu vectơ xoay dựa trên từ kế. Đây là một giải pháp thay thế hữu ích cho cảm biến TYPE_ROTATION_VECTOR
khi không có con quay hồi chuyển hoặc khi được dùng cùng với các sự kiện cảm biến theo lô để ghi lại hướng của thiết bị trong khi điện thoại ở chế độ ngủ. Cảm biến này cần ít pin hơn TYPE_ROTATION_VECTOR
, nhưng có thể dễ thu thập dữ liệu sự kiện ồn và hoạt động hiệu quả nhất khi người dùng đang ở ngoài trời.
Android hiện cũng hỗ trợ cảm biến bước tích hợp sẵn trong phần cứng:
TYPE_STEP_DETECTOR
- Cảm biến này kích hoạt một sự kiện mỗi khi người dùng thực hiện một bước. Sau mỗi bước của người dùng, cảm biến này sẽ cung cấp một sự kiện có giá trị là 1 và dấu thời gian cho biết thời điểm bước đó diễn ra.
TYPE_STEP_COUNTER
- Cảm biến này cũng kích hoạt một sự kiện mỗi bước được phát hiện, nhưng lại cung cấp tổng số bước được tích luỹ kể từ lần đầu tiên cảm biến này được một ứng dụng đăng ký.
Hãy lưu ý rằng các cảm biến 2 bước này không phải lúc nào cũng mang lại kết quả giống nhau. Các sự kiện TYPE_STEP_COUNTER
xảy ra với độ trễ cao hơn so với các sự kiện từ TYPE_STEP_DETECTOR
, nhưng nguyên nhân là do thuật toán TYPE_STEP_COUNTER
xử lý nhiều hơn để loại bỏ kết quả dương tính giả. Vì vậy, TYPE_STEP_COUNTER
có thể phân phối sự kiện chậm hơn, nhưng kết quả sẽ chính xác hơn.
Cả hai cảm biến bước đều phụ thuộc vào phần cứng (Nexus 5 là thiết bị đầu tiên hỗ trợ cảm biến này). Vì vậy, bạn nên kiểm tra tính sẵn có của hasSystemFeature()
, bằng cách sử dụng các hằng số FEATURE_SENSOR_STEP_DETECTOR
và FEATURE_SENSOR_STEP_COUNTER
.
Sự kiện cảm biến hàng loạt
Để quản lý hiệu quả hơn nguồn điện của thiết bị, API SensorManager
hiện cho phép bạn chỉ định tần suất mà bạn muốn hệ thống gửi các lô sự kiện cảm biến cho ứng dụng của mình. Điều này không làm giảm số sự kiện cảm biến thực tế có sẵn cho ứng dụng trong một khoảng thời gian nhất định, mà làm giảm tần suất hệ thống gọi SensorEventListener
bằng bản cập nhật cảm biến. Tức là thay vì cung cấp từng sự kiện đến ứng dụng ngay tại thời điểm sự kiện đó diễn ra, hệ thống sẽ lưu lại mọi sự kiện xảy ra trong một khoảng thời gian, rồi gửi tất cả sự kiện đó đến ứng dụng cùng một lúc.
Để cung cấp tính năng tạo lô, lớp SensorManager
thêm 2 phiên bản mới của phương thức registerListener()
, cho phép bạn chỉ định "độ trễ tối đa của báo cáo". Tham số mới này chỉ định độ trễ tối đa mà SensorEventListener
chấp nhận để gửi các sự kiện cảm biến mới. Ví dụ: nếu bạn chỉ định độ trễ của lô là 1 phút, thì hệ thống sẽ phân phối nhóm sự kiện được phân lô gần đây với khoảng thời gian không quá 1 phút bằng cách thực hiện các lệnh gọi liên tiếp đến phương thức onSensorChanged()
– một lần cho mỗi sự kiện được phân lô. Các sự kiện cảm biến sẽ không bao giờ bị trễ lâu hơn giá trị độ trễ tối đa của báo cáo, nhưng có thể đến sớm hơn nếu các ứng dụng khác đã yêu cầu độ trễ ngắn hơn cho cùng một cảm biến.
Tuy nhiên, hãy lưu ý rằng cảm biến sẽ phân phối cho ứng dụng các sự kiện theo lô dựa trên độ trễ của báo cáo chỉ khi CPU đang hoạt động. Mặc dù cảm biến phần cứng hỗ trợ tính năng tạo lô sẽ tiếp tục thu thập các sự kiện cảm biến trong khi CPU ở chế độ ngủ, nhưng cảm biến này sẽ không đánh thức CPU để phân phối các sự kiện được phân lô cho ứng dụng của bạn. Khi hết bộ nhớ cho các sự kiện, cảm biến sẽ bắt đầu loại bỏ các sự kiện cũ nhất để lưu các sự kiện mới nhất. Bạn có thể tránh mất sự kiện bằng cách đánh thức thiết bị trước khi cảm biến lấp đầy bộ nhớ, sau đó gọi flush()
để ghi lại lô sự kiện mới nhất. Để ước tính thời điểm bộ nhớ đầy và sẽ được đẩy xuống, hãy gọi getFifoMaxEventCount()
để nhận số sự kiện cảm biến tối đa có thể lưu rồi chia số đó cho tốc độ mà ứng dụng của bạn mong muốn đối với mỗi sự kiện. Sử dụng phép tính đó để đặt chuông báo thức bằng AlarmManager
gọi Service
(triển khai SensorEventListener
) để xả cảm biến.
Lưu ý: Không phải thiết bị nào cũng hỗ trợ việc phân lô sự kiện cảm biến theo lô vì tính năng này cần được cảm biến phần cứng hỗ trợ. Tuy nhiên, kể từ Android 4.4, bạn phải luôn sử dụng các phương thức registerListener()
mới vì nếu thiết bị không hỗ trợ tính năng tạo lô, thì hệ thống sẽ linh hoạt bỏ qua đối số độ trễ của lô và phân phối các sự kiện cảm biến theo thời gian thực.
Danh tính tay điều khiển
Android giờ đây xác định từng tay điều khiển đã kết nối bằng một số nguyên duy nhất mà bạn có thể truy vấn bằng getControllerNumber()
. Điều này giúp bạn dễ dàng liên kết mỗi tay điều khiển với một người chơi khác trong trò chơi. Số lượng tay điều khiển có thể thay đổi do người dùng bị ngắt kết nối, kết nối hoặc định cấu hình lại. Vì vậy, bạn nên theo dõi xem số tay điều khiển nào tương ứng với từng thiết bị đầu vào bằng cách đăng ký một thực thể của InputManager.InputDeviceListener
. Sau đó, hãy gọi getControllerNumber()
cho mỗi InputDevice
khi có thay đổi.
Giờ đây, thiết bị đã kết nối cũng cung cấp mã sản phẩm và mã nhà cung cấp có trong getProductId()
và getVendorId()
. Nếu cần sửa đổi sơ đồ phím dựa trên bộ phím có sẵn trên thiết bị, bạn có thể truy vấn thiết bị để kiểm tra xem hasKeys(int...)
có dùng được một số phím nhất định hay không.
Giao diện người dùng
Chế độ toàn màn hình sống động
Để cung cấp cho ứng dụng một bố cục lấp đầy toàn bộ màn hình, cờ SYSTEM_UI_FLAG_IMMERSIVE
mới cho setSystemUiVisibility()
(khi được kết hợp với SYSTEM_UI_FLAG_HIDE_NAVIGATION
) sẽ bật chế độ toàn màn hình immersed mới. Khi chế độ toàn màn hình sống động được bật, hoạt động của bạn sẽ tiếp tục nhận được tất cả các sự kiện chạm. Người dùng có thể hiển thị các thanh hệ thống bằng cách vuốt vào trong dọc theo khu vực mà các thanh hệ thống thường xuất hiện. Thao tác này sẽ xoá cờ SYSTEM_UI_FLAG_HIDE_NAVIGATION
(và cờ SYSTEM_UI_FLAG_FULLSCREEN
, nếu được áp dụng) để các thanh hệ thống vẫn hiển thị. Tuy nhiên, nếu muốn các thanh hệ thống ẩn lại sau vài giây, bạn có thể sử dụng cờ SYSTEM_UI_FLAG_IMMERSIVE_STICKY
.
Thanh hệ thống mờ
Giờ đây, bạn có thể làm cho các thanh hệ thống trong suốt một phần với các giao diện mới, Theme.Holo.NoActionBar.TranslucentDecor
và Theme.Holo.Light.NoActionBar.TranslucentDecor
. Khi bật thanh hệ thống mờ, bố cục của bạn sẽ lấp đầy khu vực phía sau các thanh hệ thống. Vì vậy, bạn cũng phải bật fitsSystemWindows
cho phần bố cục không bị các thanh hệ thống che phủ.
Nếu bạn đang tạo một giao diện tuỳ chỉnh, hãy đặt một trong các giao diện này làm giao diện mẹ hoặc thêm các thuộc tính kiểu windowTranslucentNavigation
và windowTranslucentStatus
vào giao diện của bạn.
Trình nghe thông báo nâng cao
Android 4.3 đã thêm các API NotificationListenerService
, cho phép ứng dụng nhận thông tin về thông báo mới khi thông báo mới được hệ thống đăng. Trong Android 4.4, trình nghe thông báo có thể truy xuất siêu dữ liệu bổ sung cho thông báo và đầy đủ thông tin chi tiết về các hành động của thông báo:
Trường Notification.extras
mới bao gồm Bundle
để cung cấp siêu dữ liệu bổ sung cho trình tạo thông báo như EXTRA_TITLE
và EXTRA_PICTURE
.
Lớp Notification.Action
mới định nghĩa các đặc điểm của hành động đính kèm với thông báo mà bạn có thể truy xuất từ trường actions
mới.
Phản chiếu đối tượng có thể vẽ cho bố cục RTL
Trên các phiên bản Android trước, nếu ứng dụng của bạn có các hình ảnh đảo ngược hướng ngang để có bố cục từ phải sang trái, thì bạn phải đưa hình ảnh được phản chiếu vào thư mục tài nguyên drawables-ldrtl/
. Giờ đây, hệ thống có thể tự động phản chiếu hình ảnh cho bạn bằng cách bật thuộc tính autoMirrored
trên tài nguyên có thể vẽ hoặc bằng cách gọi setAutoMirrored()
. Khi được bật, Drawable
sẽ tự động được phản chiếu khi hướng bố cục từ phải sang trái.
Hỗ trợ tiếp cận
Lớp View
hiện cho phép bạn khai báo "khu vực trực tiếp" cho các phần trên giao diện người dùng cập nhật động theo nội dung văn bản mới, bằng cách thêm thuộc tính accessibilityLiveRegion
mới vào bố cục XML hoặc gọi setAccessibilityLiveRegion()
. Ví dụ: màn hình đăng nhập có trường văn bản hiển thị thông báo "mật khẩu không đúng" phải được đánh dấu là khu vực trực tiếp để trình đọc màn hình đọc lại thông báo khi thông báo thay đổi.
Giờ đây, các ứng dụng cung cấp dịch vụ hỗ trợ tiếp cận cũng có thể nâng cao chức năng bằng các API mới cung cấp thông tin về các bộ sưu tập khung hiển thị, chẳng hạn như khung hiển thị danh sách hoặc khung hiển thị lưới bằng AccessibilityNodeInfo.CollectionInfo
và AccessibilityNodeInfo.CollectionItemInfo
.
Quyền cho ứng dụng
Sau đây là các quyền mới mà ứng dụng của bạn phải yêu cầu bằng thẻ <uses-permission>
để sử dụng một số API mới:
INSTALL_SHORTCUT
- Cho phép ứng dụng cài đặt lối tắt trong Trình chạy
UNINSTALL_SHORTCUT
- Cho phép ứng dụng gỡ cài đặt lối tắt trong Trình chạy
TRANSMIT_IR
- Cho phép ứng dụng sử dụng bộ phát IR của thiết bị (nếu có)
Lưu ý: Kể từ Android 4.4, nền tảng này không còn yêu cầu ứng dụng của bạn phải có WRITE_EXTERNAL_STORAGE
hoặc READ_EXTERNAL_STORAGE
khi bạn muốn truy cập vào các khu vực dành riêng cho ứng dụng của bộ nhớ ngoài bằng các phương thức như getExternalFilesDir()
. Tuy nhiên, bạn vẫn cần có quyền nếu muốn truy cập vào các khu vực có thể chia sẻ của bộ nhớ ngoài, do getExternalStoragePublicDirectory()
cung cấp.
Tính năng của thiết bị
Sau đây là các tính năng mới của thiết bị mà bạn có thể khai báo bằng thẻ <uses-feature>
để khai báo các yêu cầu đối với ứng dụng và bật tính năng lọc trên Google Play hoặc kiểm tra trong thời gian chạy:
FEATURE_CONSUMER_IR
- Thiết bị này có thể giao tiếp với các thiết bị điện tử tiêu dùng hồng ngoại.
FEATURE_DEVICE_ADMIN
- Thiết bị hỗ trợ thực thi chính sách thiết bị thông qua quản trị viên thiết bị.
FEATURE_NFC_HOST_CARD_EMULATION
- Thiết bị hỗ trợ quy trình mô phỏng thẻ NFC dựa trên máy chủ.
FEATURE_SENSOR_STEP_COUNTER
- Thiết bị có bộ đếm bước phần cứng.
FEATURE_SENSOR_STEP_DETECTOR
- Thiết bị có trình phát hiện bước phần cứng.
Để biết thông tin chi tiết về tất cả các thay đổi về API trong Android 4.4, hãy xem Báo cáo điểm khác biệt về API.