ระดับ API: 18
Android 4.3 (JELLY_BEAN_MR2
)
คือการอัปเดตรุ่น Jelly Bean ที่นำเสนอฟีเจอร์ใหม่ๆ สำหรับผู้ใช้และแอป
เอกสารนี้จะให้ข้อมูลเบื้องต้นเกี่ยวกับ
API ใหม่
ในฐานะนักพัฒนาแอป คุณควรดาวน์โหลดอิมเมจระบบของ Android 4.3 และแพลตฟอร์ม SDK จาก SDK Manager เป็น โดยเร็วที่สุด หากคุณไม่มีอุปกรณ์ที่ใช้ Android 4.3 ที่ต้อง ทดสอบแอปของคุณ ใช้ระบบ Android 4.3 รูปภาพเพื่อทดสอบแอปในโปรแกรมจำลอง Android จากนั้นสร้างแอปบนแพลตฟอร์ม Android 4.3 เพื่อเริ่มใช้ API ล่าสุด
อัปเดตระดับ API เป้าหมาย
หากต้องการเพิ่มประสิทธิภาพแอปสำหรับอุปกรณ์ที่ใช้ Android 4.3 ได้ดียิ่งขึ้น
คุณควรตั้งค่า targetSdkVersion
เป็น
"18"
ให้ติดตั้งในอิมเมจระบบ Android 4.3
แล้วเผยแพร่อัปเดตที่มีการเปลี่ยนแปลงนี้
คุณสามารถใช้ API ใน Android 4.3 และรองรับเวอร์ชันเก่าๆ ได้โดยเพิ่ม
เงื่อนไขในโค้ดของคุณที่ตรวจสอบระดับ API ของระบบก่อนดำเนินการ
API ไม่รองรับใน minSdkVersion
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการรักษาความเข้ากันได้แบบย้อนหลัง โปรดอ่านการสนับสนุนความแตกต่าง
เวอร์ชันของแพลตฟอร์ม
นอกจากนี้ยังมี API ต่างๆ ในไลบรารีการสนับสนุนของ Android ซึ่งจะช่วยให้คุณนำไปใช้ ฟีเจอร์ใหม่ในแพลตฟอร์มเวอร์ชันเก่า
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของระดับ API โปรดอ่าน API คืออะไร ระดับ
การเปลี่ยนแปลงลักษณะการทำงานที่สำคัญ
หากคุณเคยเผยแพร่แอปสำหรับ Android มาแล้วก่อนหน้านี้ โปรดทราบว่าแอปของคุณอาจ ได้รับผลกระทบจากการเปลี่ยนแปลงใน Android 4.3
หากแอปใช้ Intent แบบไม่เจาะจงปลายทาง...
แอปของคุณอาจทำงานผิดปกติในสภาพแวดล้อมโปรไฟล์ที่จำกัด
ผู้ใช้ในสภาพแวดล้อมโปรไฟล์ที่ถูกจำกัดอาจไม่สามารถ
มีแอป Android มาตรฐานทั้งหมดที่ใช้ได้ ตัวอย่างเช่น โปรไฟล์ที่ถูกจำกัดอาจมี
เว็บเบราว์เซอร์และแอปกล้องถ่ายรูปถูกปิดใช้งาน ดังนั้นแอปของคุณจึงไม่ควรคาดเดาว่าแอปใด
เพราะหากคุณโทรหา startActivity()
โดยไม่มี
ตรวจสอบว่าแอปใช้จัดการ Intent
ได้หรือไม่
แอปของคุณอาจขัดข้องในโปรไฟล์ที่ถูกจำกัด
เมื่อใช้ Intent แบบไม่เจาะจงปลายทาง คุณควรยืนยันว่าแอปพร้อมจัดการ Intent อยู่เสมอโดยโทรหา resolveActivity()
หรือ queryIntentActivities()
เช่น
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(); }
หากแอปขึ้นอยู่กับบัญชี...
แอปของคุณอาจทำงานผิดปกติในสภาพแวดล้อมโปรไฟล์ที่จำกัด
ผู้ใช้ในสภาพแวดล้อมโปรไฟล์ที่จำกัดจะไม่มีสิทธิ์เข้าถึงบัญชีผู้ใช้โดยค่าเริ่มต้น
หากแอปใช้ Account
แอปอาจขัดข้องหรือทำงาน
เมื่อใช้ในโปรไฟล์ที่ถูกจำกัด
หากต้องการป้องกันไม่ให้โปรไฟล์ที่จำกัดใช้แอปทั้งหมดเนื่องจาก
แอปขึ้นอยู่กับข้อมูลบัญชีที่มีความละเอียดอ่อน ให้ระบุแอตทริบิวต์ android:requiredAccountType
ใน <application>
ของไฟล์ Manifest
หากคุณต้องการอนุญาตให้โปรไฟล์ที่ถูกจำกัดใช้แอปของคุณต่อได้ แม้ว่าโปรไฟล์เหล่านั้นจะใช้งานไม่ได้ สร้างบัญชีของตนเอง จากนั้นคุณสามารถปิดใช้ฟีเจอร์ของแอปที่จำเป็นต้องใช้บัญชี หรืออนุญาตให้โปรไฟล์ที่ถูกจำกัดสามารถเข้าถึงบัญชีที่สร้างโดยผู้ใช้หลัก สำหรับข้อมูลเพิ่มเติม โปรดดูที่ส่วน ด้านล่างเกี่ยวกับการสนับสนุนบัญชีในโปรไฟล์ที่ถูกจำกัด
หากแอปของคุณใช้ VideoView...
วิดีโอของคุณอาจมีขนาดเล็กลงใน Android 4.3
ใน Android เวอร์ชันก่อนหน้า วิดเจ็ต VideoView
ไม่ถูกต้อง
คำนวณค่า "wrap_content"
สำหรับ layout_height
และ layout_width
ให้เหมือนกับ "match_parent"
ดังนั้นในขณะที่ใช้ "wrap_content"
สำหรับความสูงหรือความกว้างอาจมีเลย์เอาต์วิดีโอที่คุณต้องการก่อนหน้านี้แล้ว
ซึ่งอาจทำให้วิดีโอมีขนาดเล็กลงมากบน Android 4.3 และเวอร์ชันที่สูงกว่า แก้ไขปัญหาด้วยการเปลี่ยน
"wrap_content"
กับ "match_parent"
และยืนยันว่าวิดีโอของคุณปรากฏตามที่คาดไว้ในวันที่
Android 4.3 รวมถึงเวอร์ชันเก่า
โปรไฟล์ที่ถูกจำกัด
ในแท็บเล็ต Android ผู้ใช้สามารถสร้างโปรไฟล์แบบจำกัดโดยอิงตามผู้ใช้หลักได้แล้ว เมื่อสร้างโปรไฟล์ที่จำกัด ผู้ใช้สามารถเปิดใช้ข้อจำกัดต่างๆ เช่น แอปใดบ้างที่ ใช้ได้กับโปรไฟล์ นอกจากนี้ API ชุดใหม่ใน Android 4.3 ยังช่วยให้คุณสร้างชิ้นงานที่ละเอียดขึ้นได้ด้วย การตั้งค่าการจำกัดสำหรับแอปที่คุณพัฒนา ตัวอย่างเช่น เมื่อใช้ API ใหม่ คุณจะทำสิ่งต่อไปนี้ได้ ช่วยให้ผู้ใช้ควบคุมประเภทเนื้อหาที่พร้อมใช้งานภายในแอปเมื่อเรียกใช้ สภาพแวดล้อมโปรไฟล์ที่จำกัด
UI สำหรับให้ผู้ใช้ควบคุมข้อจำกัดที่คุณสร้างขึ้นมีการจัดการโดยระบบ
แอปพลิเคชันการตั้งค่า หากต้องการให้การตั้งค่าข้อจำกัดของแอปปรากฏต่อผู้ใช้
คุณต้องประกาศการจำกัดที่แอปกำหนดโดยการสร้าง BroadcastReceiver
ที่ได้รับ Intent ACTION_GET_RESTRICTION_ENTRIES
ระบบเรียกใช้ความตั้งใจนี้เพื่อค้นหา
แอปทั้งหมดสำหรับข้อจำกัดที่มีอยู่ แล้วสร้าง UI เพื่อให้ผู้ใช้หลัก
จัดการข้อจำกัดสำหรับแต่ละโปรไฟล์ที่ถูกจำกัด
ในเมธอด onReceive()
ของ
BroadcastReceiver
คุณต้องสร้าง RestrictionEntry
สำหรับข้อจำกัดแต่ละรายการที่แอปมีให้ RestrictionEntry
แต่ละรายการจะกำหนดชื่อ คำอธิบาย และหนึ่งใน
ประเภทข้อมูลต่อไปนี้
TYPE_BOOLEAN
สำหรับข้อจำกัดที่ จริงหรือเท็จTYPE_CHOICE
สำหรับข้อจำกัดที่มี ตัวเลือกที่หลากหลายซึ่งไม่เกี่ยวข้องกัน (ตัวเลือกปุ่มตัวเลือก)TYPE_MULTI_SELECT
สำหรับข้อจำกัดที่ มีตัวเลือกหลายตัวเลือกที่ไม่แยกกันอย่างสิ้นเชิง (ตัวเลือกแบบช่องทำเครื่องหมาย)
จากนั้นคุณใส่ออบเจ็กต์ RestrictionEntry
ทั้งหมดลงใน ArrayList
และใส่ไว้ในผลลัพธ์ของ Broadcast Receiver เป็นค่าสำหรับ
เพิ่มเติม EXTRA_RESTRICTIONS_LIST
ระบบจะสร้าง UI สำหรับข้อจำกัดของแอปในแอปการตั้งค่าและบันทึกแต่ละรายการ
ด้วยคีย์ที่ไม่ซ้ำกันที่คุณระบุสำหรับ RestrictionEntry
แต่ละรายการ
ออบเจ็กต์ เมื่อผู้ใช้เปิดแอป คุณจะค้นหาข้อจำกัดปัจจุบันได้โดย
กำลังโทรหา getApplicationRestrictions()
การดำเนินการนี้จะแสดงผล Bundle
ที่มีคู่คีย์-ค่าสำหรับข้อจำกัดแต่ละรายการ
ที่คุณกำหนดด้วยออบเจ็กต์ RestrictionEntry
ถ้าต้องการระบุข้อจำกัดที่เจาะจงมากขึ้นที่ค่าบูลีนจัดการไม่ได้ ให้ใช้ค่าเดียว
ตัวเลือก และค่าแบบหลายตัวเลือก คุณจะสามารถสร้างกิจกรรมที่ผู้ใช้สามารถระบุ
การจำกัด และอนุญาตให้ผู้ใช้เปิดกิจกรรมนั้นจากการตั้งค่าการจำกัด ใน
Broadcast Receiver รวม EXTRA_RESTRICTIONS_INTENT
เพิ่มเติม
ในผลลัพธ์ Bundle
ส่วนเกินนี้ต้องระบุ Intent
กำลังระบุคลาส Activity
ที่จะเปิดตัว (ใช้
putParcelable()
เพื่อส่ง EXTRA_RESTRICTIONS_INTENT
พร้อม Intent)
เมื่อผู้ใช้หลักป้อนกิจกรรมเพื่อตั้งข้อจำกัดที่กำหนดเอง
กิจกรรมจะต้องส่งคืนผลลัพธ์ที่มีค่าการจำกัดในเพิ่มเติมโดยใช้
คีย์ EXTRA_RESTRICTIONS_LIST
หรือ EXTRA_RESTRICTIONS_BUNDLE
ขึ้นอยู่กับว่าคุณระบุหรือไม่
RestrictionEntry
ออบเจ็กต์หรือคู่คีย์-ค่าตามลำดับ
การสนับสนุนบัญชีในโปรไฟล์ที่ถูกจำกัด
บัญชีใดๆ ที่เพิ่มลงในผู้ใช้หลักจะใช้งานในโปรไฟล์ที่ถูกจำกัดได้ แต่
บัญชีไม่สามารถเข้าถึงได้จาก API ของ AccountManager
โดยค่าเริ่มต้น
หากคุณพยายามเพิ่มบัญชีกับ AccountManager
ขณะอยู่ในพื้นที่ที่ถูกจำกัด
คุณจะเห็นผลลัพธ์แสดงความล้มเหลว และเนื่องจากข้อจำกัดเหล่านี้ คุณจึงมีสิ่งต่อไปนี้
สามตัวเลือก:
หากต้องการเข้าถึงบัญชีจากโปรไฟล์ที่ถูกจำกัด คุณต้องเพิ่มแอตทริบิวต์ android:restrictedAccountType
ลงในแท็ก <application> ดังนี้
<application ... android:restrictedAccountType="com.example.account.type" >
ข้อควรระวัง: การเปิดใช้แอตทริบิวต์นี้จะทำให้ สิทธิ์เข้าถึงของแอปเพื่อเข้าถึงบัญชีของผู้ใช้หลักจากโปรไฟล์ที่ถูกจำกัด คุณจึงควรอนุญาต เฉพาะเมื่อข้อมูลที่แอปของคุณแสดงไม่ได้เปิดเผยการระบุตัวบุคคล ข้อมูล (PII) ที่ถือว่ามีความละเอียดอ่อน การตั้งค่าระบบจะแจ้ง ว่าแอปของคุณให้สิทธิ์โปรไฟล์ที่จำกัดกับบัญชีของตน ดังนั้นจึงควรแจ้งให้ผู้ใช้ทราบอย่างชัดเจน การเข้าถึงบัญชีนั้นสำคัญต่อฟังก์ชันการทำงานของแอป หากเป็นไปได้ คุณควร ให้การควบคุมการจำกัดที่เพียงพอสำหรับผู้ใช้หลักที่กำหนดสิทธิ์เข้าถึงบัญชี ในแอปของคุณ
หากต้องการใช้บัญชี แต่ไม่ได้กำหนดว่าต้องใช้กับบัญชีหลักของแอป
คุณสามารถตรวจสอบความพร้อมใช้งานของบัญชี
และปิดใช้ฟีเจอร์เมื่อไม่พร้อมใช้งาน
คุณควรตรวจสอบว่ามีบัญชีที่ใช้อยู่ในปัจจุบันหรือไม่ หากไม่เป็นเช่นนั้น ให้ค้นหาว่า
คุณสร้างบัญชีใหม่ได้โดยโทรไปที่ getUserRestrictions()
และตรวจสอบส่วน DISALLOW_MODIFY_ACCOUNTS
เพิ่มเติมในผลลัพธ์ หากเป็นtrue
คุณควรปิดใช้ฟังก์ชันใดก็ตามของแอปที่จำเป็นต้องเข้าถึงบัญชี
เช่น
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 }
หมายเหตุ: ในสถานการณ์นี้ คุณไม่ควรประกาศ แอตทริบิวต์ใหม่ในไฟล์ Manifest
หากแต่เป็นเรื่องสำคัญที่แอปจะไม่สามารถใช้ได้กับโปรไฟล์ที่ถูกจำกัดเนื่องจาก
แอปของคุณต้องใช้ข้อมูลส่วนบุคคลที่มีความละเอียดอ่อนในบัญชี (และเนื่องจากโปรไฟล์ที่ถูกจำกัด
ขณะนี้ไม่สามารถเพิ่มบัญชีใหม่) เพิ่ม
แอตทริบิวต์ android:requiredAccountType
เป็นแท็ก <application>
<application ... android:requiredAccountType="com.example.account.type" >
เช่น แอป Gmail ใช้แอตทริบิวต์นี้เพื่อปิดใช้ตัวเองสำหรับโปรไฟล์ที่ถูกจำกัด เนื่องจากอีเมลส่วนตัวของเจ้าของไม่ควรอยู่ในโปรไฟล์ที่ถูกจำกัด
ระบบไร้สายและการเชื่อมต่อ
บลูทูธพลังงานต่ำ (รองรับอัจฉริยะ)
ตอนนี้ Android รองรับบลูทูธพลังงานต่ำ (LE) ด้วย API ใหม่ใน android.bluetooth
แล้ว
API ใหม่ช่วยให้คุณสร้างแอป Android ที่สื่อสารกับบลูทูธพลังงานต่ำได้
อุปกรณ์ต่อพ่วง เช่น เครื่องวัดอัตราการเต้นของหัวใจและเครื่องวัดจำนวนก้าว
เนื่องจาก Bluetooth LE เป็นฟีเจอร์ของฮาร์ดแวร์ที่ไม่พร้อมใช้งานในบางอุปกรณ์
อุปกรณ์ที่ใช้ Android คุณต้องประกาศในไฟล์ Manifest ว่า<uses-feature>
องค์ประกอบของ "android.hardware.bluetooth_le"
:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
ถ้าคุณคุ้นเคยกับ API บลูทูธแบบคลาสสิกของ Android ดีอยู่แล้ว ให้สังเกตว่าการใช้
Bluetooth LE API มีความแตกต่างกันอยู่บ้าง สิ่งสำคัญที่สุดคือตอนนี้มีคลาส BluetoothManager
ที่คุณควรใช้สำหรับการดำเนินการระดับสูงบางอย่าง
เช่น การรับ BluetoothAdapter
การรับรายการที่เชื่อมโยง
อุปกรณ์ และการตรวจสอบสถานะของอุปกรณ์ ตัวอย่างมีดังนี้ ต่อไปนี้คือวิธีที่คุณควรเข้าถึง
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();
หากต้องการค้นหาอุปกรณ์ต่อพ่วง Bluetooth LE โปรดโทรหา startLeScan()
ใน BluetoothAdapter
เพื่อส่งการติดตั้งใช้งาน
ของอินเทอร์เฟซ BluetoothAdapter.LeScanCallback
เมื่อบลูทูธ
อะแดปเตอร์ตรวจพบอุปกรณ์ต่อพ่วง Bluetooth LE การใช้งาน BluetoothAdapter.LeScanCallback
ได้รับสายเรียกเข้า
onLeScan()
วิธี ช่วงเวลานี้
จะให้ออบเจ็กต์ BluetoothDevice
ที่แสดงถึง
อุปกรณ์ที่ตรวจพบ ค่า RSSI สำหรับอุปกรณ์ และอาร์เรย์ไบต์ที่มีข้อมูล
บันทึกการโฆษณา
หากต้องการสแกนหาอุปกรณ์ต่อพ่วงบางประเภทเท่านั้น ให้เรียกใช้ startLeScan()
แล้วรวมอาร์เรย์ของออบเจ็กต์ UUID
ซึ่งระบุบริการ GATT ที่แอปของคุณรองรับ
หมายเหตุ: คุณจะสแกนหาอุปกรณ์ Bluetooth LE ได้ หรือเท่านั้น สแกนหาอุปกรณ์บลูทูธแบบคลาสสิกโดยใช้ API ก่อนหน้านี้ คุณสแกนหาทั้ง LE และ Classic ไม่ได้ อุปกรณ์บลูทูธได้พร้อมกัน
แล้วโทรหา connectGatt()
ที่อุปกรณ์ที่เกี่ยวข้อง เพื่อเชื่อมต่อกับอุปกรณ์ต่อพ่วง Bluetooth LE
BluetoothDevice
ออบเจ็กต์ผ่านการติดตั้งใช้งาน
BluetoothGattCallback
การใช้งาน BluetoothGattCallback
ได้รับการติดต่อกลับเกี่ยวกับการเชื่อมต่อ
สถานะตามอุปกรณ์และเหตุการณ์อื่นๆ อยู่ในช่วง onConnectionStateChange()
Callback ที่คุณจะเริ่มสื่อสารกับอุปกรณ์ได้หากเมธอดผ่าน STATE_CONNECTED
เป็นสถานะใหม่
การเข้าถึงฟีเจอร์บลูทูธในอุปกรณ์กำหนดให้คุณต้องส่งคำขอบางอย่าง สิทธิ์ของผู้ใช้บลูทูธ สำหรับข้อมูลเพิ่มเติม โปรดดูที่คู่มือ API บลูทูธพลังงานต่ำ
โหมดสแกนอย่างเดียวของ Wi-Fi
เมื่อพยายามระบุตำแหน่งของผู้ใช้ Android อาจใช้ Wi-Fi เพื่อช่วยระบุ ตำแหน่งได้โดยการสแกนจุดเข้าใช้งานใกล้เคียง แต่ผู้ใช้มักจะปิด Wi-Fi ไว้เพื่อ ประหยัดแบตเตอรี่ ทำให้ข้อมูลตำแหน่งมีความแม่นยำน้อยลง ตอนนี้ Android มี โหมดสแกนเท่านั้นที่อนุญาตให้ Wi-Fi ของอุปกรณ์สแกนจุดเข้าใช้งานเพื่อรับตำแหน่ง โดยไม่ต้องเชื่อมต่อจุดเข้าใช้งาน ซึ่งจะลดการใช้งานแบตเตอรี่ลงอย่างมาก
หากต้องการหาตำแหน่งของผู้ใช้ แต่ Wi-Fi ปิดอยู่ คุณสามารถส่งคำขอ
ผู้ใช้สามารถเปิดใช้โหมดสแกนอย่างเดียวของ Wi-Fi โดยเรียกใช้ startActivity()
ด้วยการดำเนินการ ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
การกำหนดค่า Wi-Fi
WifiEnterpriseConfig
API ใหม่ช่วยให้บริการแบบองค์กรทำสิ่งต่อไปนี้ได้
กำหนดค่า Wi-Fi สำหรับอุปกรณ์ที่มีการจัดการโดยอัตโนมัติ
คำตอบด่วนสำหรับสายเรียกเข้า
ตั้งแต่ Android 4.0 ฟีเจอร์ชื่อ "คำตอบด่วน" ช่วยให้ผู้ใช้สามารถตอบสนองต่อ
ด้วย SMS ทันทีโดยไม่ต้องรับสายหรือปลดล็อกอุปกรณ์
ก่อนหน้านี้แอปการรับส่งข้อความเริ่มต้นจะจัดการข้อความด่วนเหล่านี้เสมอ ตอนนี้ทุกแอป
สามารถประกาศความสามารถในการจัดการข้อความเหล่านี้โดยการสร้าง Service
ด้วยตัวกรอง Intent สำหรับ ACTION_RESPOND_VIA_MESSAGE
เมื่อผู้ใช้รับสายโทรเข้าด้วยคำตอบด่วน แอปโทรศัพท์จะส่ง
Intent ACTION_RESPOND_VIA_MESSAGE
ที่มี URI
การอธิบายถึงผู้รับ (ผู้โทร) และค่าใช้จ่ายเพิ่มเติม EXTRA_TEXT
ด้วยข้อความที่ผู้ใช้ต้องการส่ง เมื่อบริการได้รับความตั้งใจ บริการควรส่งมอบ
ข้อความและหยุดตัวเองทันที (แอปของคุณไม่ควรแสดงกิจกรรม)
หากต้องการรับ Intent นี้ คุณต้องประกาศสิทธิ์ SEND_RESPOND_VIA_MESSAGE
มัลติมีเดีย
การเพิ่มประสิทธิภาพ MediaExtractor และ MediaCodec
ตอนนี้ Android ให้คุณเขียน Dynamic Adaptive เองได้ง่ายขึ้น
การสตรีมผ่านโปรแกรมเล่น HTTP (DASH) ตามมาตรฐาน ISO/IEC 23009-1
ใช้ API ที่มีอยู่ใน MediaCodec
และ MediaExtractor
เฟรมเวิร์กที่เป็นพื้นฐานสำหรับ API เหล่านี้ได้รับการอัปเดตให้รองรับ
การแยกวิเคราะห์ไฟล์ MP4 ที่กระจัดกระจาย แต่แอปของคุณยังคงมีหน้าที่ในการแยกวิเคราะห์ข้อมูลเมตาของ MPD
และส่งต่อสตรีมแต่ละรายการไปยัง MediaExtractor
หากต้องการใช้ DASH กับเนื้อหาที่เข้ารหัส โปรดสังเกตว่าเมธอด getSampleCryptoInfo()
จะแสดงข้อมูลเมตา MediaCodec.CryptoInfo
ที่อธิบายโครงสร้างของสื่อที่เข้ารหัสแต่ละรายการ
ตัวอย่าง นอกจากนี้ยังมีการเพิ่มเมธอด getPsshInfo()
ลงใน
MediaExtractor
เพื่อให้คุณเข้าถึงข้อมูลเมตา PSSH สำหรับสื่อ DASH ได้
เมธอดนี้จะส่งคืนแผนที่ของวัตถุ UUID
รายการเป็นไบต์ด้วยฟังก์ชัน
UUID
ที่ระบุรูปแบบคริปโตและไบต์ที่เป็นข้อมูลเฉพาะ
มาใช้กับสคีมดังกล่าว
DRM ของสื่อ
คลาส MediaDrm
ใหม่มอบโซลูชันแบบโมดูลสำหรับสิทธิ์ดิจิทัล
การจัดการ (DRM) กับเนื้อหาสื่อของคุณโดยการแยกข้อกังวลเกี่ยวกับ DRM ออกจากการเล่นสื่อ สำหรับ
ตัวอย่างเช่น การแยก API นี้ช่วยให้คุณเล่นเนื้อหาที่เข้ารหัส Widevine ได้โดยไม่ต้อง
เพื่อใช้รูปแบบสื่อ Widevine โซลูชัน DRM นี้ยังรองรับการเข้ารหัสทั่วไป DASH คุณจึง
สามารถใช้แผน DRM ที่หลากหลายกับเนื้อหาสตรีมมิงของคุณได้
คุณสามารถใช้ MediaDrm
เพื่อรับข้อความและประมวลผลคำขอคีย์ทึบ
ข้อความตอบกลับคีย์จากเซิร์ฟเวอร์สำหรับการซื้อใบอนุญาตและการจัดสรร แอปของคุณเป็นแบบ
รับผิดชอบจัดการการสื่อสารของเครือข่ายกับเซิร์ฟเวอร์ คลาส MediaDrm
จะให้ความสามารถในการสร้างและประมวลผลข้อความเท่านั้น
API ของ MediaDrm
มีวัตถุประสงค์เพื่อใช้ร่วมกับ
MediaCodec
API ที่เปิดตัวใน Android 4.1 (API ระดับ 16)
ซึ่งรวมถึง MediaCodec
สำหรับการเข้ารหัสและถอดรหัสเนื้อหา MediaCrypto
สำหรับจัดการเนื้อหาที่เข้ารหัส และ MediaExtractor
ในการแยกและแยกส่วนเนื้อหาไม่ได้
ก่อนอื่น คุณต้องสร้าง MediaExtractor
และ
MediaCodec
ออบเจ็กต์ จากนั้นคุณจะสามารถเข้าถึงการระบุรูปแบบ DRM
UUID
ซึ่งมักมาจากข้อมูลเมตาในเนื้อหาและใช้เพื่อสร้าง
อินสแตนซ์ของออบเจ็กต์ MediaDrm
พร้อมตัวสร้าง
การเข้ารหัสวิดีโอจากแพลตฟอร์ม
Android 4.1 (API ระดับ 16) เพิ่มคลาส MediaCodec
สำหรับระดับต่ำ
การเข้ารหัสและถอดรหัสของเนื้อหาสื่อ เมื่อเข้ารหัสวิดีโอ Android 4.1 คุณต้องระบุเอาไว้
สื่อที่มีอาร์เรย์ ByteBuffer
แต่ตอนนี้ Android 4.3 อนุญาตให้คุณใช้ Surface
เป็นอินพุตไปยังโปรแกรมเปลี่ยนไฟล์ได้แล้ว ตัวอย่างเช่น วิธีนี้ให้คุณเข้ารหัสอินพุต
จากไฟล์วิดีโอที่มีอยู่หรือใช้เฟรมที่สร้างจาก OpenGL ES
หากต้องการใช้ Surface
เป็นอินพุตของโปรแกรมเปลี่ยนไฟล์ ก่อนอื่นให้เรียกใช้ configure()
สำหรับ MediaCodec
จากนั้นโทรหา createInputSurface()
เพื่อรับ Surface
ซึ่งคุณจะสตรีมสื่อได้
ตัวอย่างเช่น คุณสามารถใช้ Surface
ที่ระบุเป็นหน้าต่างสำหรับ OpenGL
โดยส่งไปยัง eglCreateWindowSurface()
จากนั้นขณะแสดงภาพพื้นผิว ให้เรียก eglSwapBuffers()
เพื่อส่งเฟรมไปยัง MediaCodec
หากต้องการเริ่มเข้ารหัส โปรดโทรหา start()
ใน MediaCodec
เมื่อเสร็จแล้ว ให้โทรหา signalEndOfInputStream()
ในการสิ้นสุดการเข้ารหัส และเรียก release()
ใน
Surface
การมักซ์สื่อ
คลาส MediaMuxer
ใหม่เปิดใช้การมัลติเพล็กซ์ระหว่างสตรีมเสียง 1 รายการ
และสตรีมวิดีโอ 1 รายการ API เหล่านี้ทำหน้าที่เป็นสิ่งที่เหมือนกับ MediaExtractor
ที่เพิ่มใน Android 4.2 สำหรับสื่อการแยกสัญญาณ (Demuxing) สื่อ
รูปแบบเอาต์พุตที่รองรับกำหนดไว้ใน MediaMuxer.OutputFormat
ปัจจุบัน
MP4 เป็นรูปแบบเอาต์พุตเดียวที่รองรับและขณะนี้ MediaMuxer
รองรับ
สตรีมเสียงครั้งละ 1 รายการและ/หรือ 1 สตรีมเท่านั้น
MediaMuxer
ได้รับการออกแบบมาให้ทำงานกับ MediaCodec
เป็นส่วนใหญ่
เพื่อให้คุณสามารถประมวลผลวิดีโอผ่าน MediaCodec
จากนั้นบันทึก
ออกเป็นไฟล์ MP4 จนถึง MediaMuxer
คุณยังสามารถใช้ MediaMuxer
ร่วมกับ MediaExtractor
เพื่อดำเนินการได้อีกด้วย
แก้ไขสื่อได้โดยไม่ต้องเข้ารหัสหรือถอดรหัส
ความคืบหน้าในการเล่นและการสครับสำหรับ RemoteControlClient
ใน Android 4.0 (API ระดับ 14) ระบบได้เพิ่ม RemoteControlClient
ลงใน
เปิดใช้งานตัวควบคุมการเล่นสื่อจากไคลเอ็นต์รีโมตคอนโทรล เช่น ตัวควบคุมที่มีใน
ล็อกหน้าจอ ขณะนี้ Android 4.3 ช่วยให้ตัวควบคุมดังกล่าวแสดงการเล่น
ตำแหน่งและการควบคุมสำหรับการสครับ ถ้าคุณเปิดใช้งานรีโมตคอนโทรลสำหรับ
แอปสื่อที่มี API ของ RemoteControlClient
คุณจะสามารถอนุญาตการเล่น
โดยใช้อินเทอร์เฟซใหม่ 2 แบบ
ก่อนอื่น คุณต้องเปิดใช้แฟล็ก FLAG_KEY_MEDIA_POSITION_UPDATE
โดยส่งต่อไปที่
setTransportControlsFlags()
จากนั้นจึงใช้อินเทอร์เฟซใหม่ 2 รายการต่อไปนี้
RemoteControlClient.OnGetPlaybackPositionListener
- รวมถึง Callback
onGetPlaybackPosition()
ที่ขอตำแหน่งปัจจุบัน ของสื่อเมื่อรีโมตคอนโทรลจำเป็นต้องอัปเดตความคืบหน้าใน UI RemoteControlClient.OnPlaybackPositionUpdateListener
- รวมถึง Callback
onPlaybackPositionUpdate()
ที่ จะบอกรหัสเวลาใหม่สำหรับสื่อของคุณแก่แอปของคุณเมื่อผู้ใช้สครับการเล่นด้วย UI ของรีโมตคอนโทรลเมื่ออัปเดตการเล่นด้วยตำแหน่งใหม่แล้ว ให้โทรหา
setPlaybackState()
เพื่อระบุ สถานะ ตำแหน่ง และความเร็วการเล่นใหม่
เมื่อกำหนดอินเทอร์เฟซเหล่านี้แล้ว คุณจะตั้งค่าอินเทอร์เฟซสำหรับ RemoteControlClient
ได้โดยเรียกใช้ setOnGetPlaybackPositionListener()
และ
setPlaybackPositionUpdateListener()
ตามลำดับ
กราฟิก
การรองรับ OpenGL ES 3.0
Android 4.3 เพิ่มอินเทอร์เฟซ Java และการสนับสนุนในตัวสำหรับ OpenGL ES 3.0 ฟังก์ชันใหม่ที่สำคัญ ที่มีให้ใน OpenGL ES 3.0 รวมถึง
- การเร่งเอฟเฟกต์ภาพขั้นสูง
- การบีบอัดพื้นผิว ETC2/EAC คุณภาพสูงเป็นฟีเจอร์มาตรฐาน
- ภาษาการแรเงา GLSL ES เวอร์ชันใหม่ที่รองรับจำนวนเต็มและการรองรับจุดทศนิยม 32 บิต
- การแสดงภาพพื้นผิวขั้นสูง
- การกำหนดขนาดพื้นผิวและรูปแบบบัฟเฟอร์สำหรับการแสดงภาพที่เป็นมาตรฐานที่กว้างขึ้น
อินเทอร์เฟซ Java สำหรับ OpenGL ES 3.0 บน Android ให้มาพร้อมกับ GLES30
เมื่อใช้ OpenGL ES 3.0 โปรดประกาศในไฟล์ Manifest ที่มีเมธอด
<uses-feature>
และแอตทริบิวต์ android:glEsVersion
เช่น
<manifest> <uses-feature android:glEsVersion="0x00030000" /> ... </manifest>
และอย่าลืมระบุบริบท OpenGL ES โดยเรียก setEGLContextClientVersion()
กำลังส่ง 3
เป็นเวอร์ชัน
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการใช้ OpenGL ES รวมถึงวิธีตรวจสอบอุปกรณ์ที่รองรับ เวอร์ชัน OpenGL ES ระหว่างรันไทม์ โปรดดูคู่มือ API OpenGL ES
Mipmapping สำหรับทรัพยากรที่ถอนออกได้
การใช้ Mipmap เป็นแหล่งที่มาสำหรับบิตแมปหรือที่ถอนออกได้เป็นวิธีง่ายๆ ในการเสนอ รูปภาพที่มีคุณภาพและสเกลภาพที่หลากหลาย ซึ่งจะเป็นประโยชน์อย่างยิ่งหากคุณคาดว่า ภาพที่จะปรับขนาดขณะแสดงภาพเคลื่อนไหว
Android 4.2 (API ระดับ 17) เพิ่มการรองรับ Mipmaps ใน Bitmap
คลาส - Android จะสลับรูปภาพ Mip ใน Bitmap
เมื่อคุณ
ระบุซอร์สของ Mipmap และเปิดใช้ setHasMipMap()
ขณะนี้ใน Android 4.3 คุณสามารถเปิดใช้ mipmaps สำหรับออบเจ็กต์ BitmapDrawable
ได้เช่นกัน โดยจัดทำเนื้อหา mipmap และ
การตั้งค่าแอตทริบิวต์ android:mipMap
ในไฟล์ทรัพยากรบิตแมปหรือโดยการเรียกใช้ hasMipMap()
อินเทอร์เฟซผู้ใช้
ดูการวางซ้อน
คลาส ViewOverlay
ใหม่จะมีเลเยอร์โปร่งใสที่ด้านบนของ
View
ที่คุณสามารถเพิ่มเนื้อหาที่เป็นภาพ ซึ่งจะไม่มีผลกับ
ลำดับชั้นของเลย์เอาต์ คุณสามารถรับ ViewOverlay
สำหรับ View
ใดก็ได้เมื่อโทรไปที่ getOverlay()
การวางซ้อน
จะมีขนาดและตำแหน่งเดียวกับมุมมองโฮสต์เสมอ (มุมมองที่ใช้สร้างมุมมองนี้)
ซึ่งทำให้คุณสามารถเพิ่มเนื้อหาที่ปรากฏด้านหน้ามุมมองโฮสต์ แต่ขยายไม่ได้
ขอบเขตของมุมมองโฮสต์นั้น
การใช้ ViewOverlay
จะมีประโยชน์อย่างยิ่งเมื่อคุณต้องการสร้าง
ภาพเคลื่อนไหว เช่น การเลื่อนมุมมองออกนอกคอนเทนเนอร์ หรือย้ายรายการไปรอบๆ หน้าจอ
โดยไม่ส่งผลต่อลำดับชั้นการแสดงผล อย่างไรก็ตาม เนื่องจากพื้นที่ใช้สอยของโฆษณาซ้อนทับ
จำกัดเฉพาะพื้นที่เดียวกับมุมมองโฮสต์ ถ้าคุณต้องการทำให้มุมมองเคลื่อนไหวออกมาด้านนอก
ตำแหน่งในเค้าโครง คุณต้องใช้การวางซ้อนจากมุมมองหลักที่มี
และขอบเขตของเลย์เอาต์
เมื่อคุณสร้างโฆษณาซ้อนทับสำหรับมุมมองวิดเจ็ต เช่น Button
คุณจะ
สามารถเพิ่มวัตถุ Drawable
รายการลงในการวางซ้อนโดยเรียก
add(Drawable)
หากคุณเรียกใช้ getOverlay()
สำหรับมุมมองเลย์เอาต์ เช่น RelativeLayout
ออบเจ็กต์ที่แสดงผลเป็น ViewGroupOverlay
ViewGroupOverlay
ชั้นเรียนเป็นคลาสย่อย
ของ ViewOverlay
ที่ให้คุณเพิ่ม View
ได้ด้วย
ออบเจ็กต์โดยการเรียกใช้ add(View)
หมายเหตุ: เนื้อหาที่ถอนออกได้และมุมมองทั้งหมดที่คุณเพิ่มไปยังการวางซ้อน เป็นภาพเท่านั้น โดยจะไม่ได้รับเหตุการณ์โฟกัสหรืออินพุต
ตัวอย่างเช่น โค้ดต่อไปนี้ทำให้มุมมองเคลื่อนไหวไปทางขวาด้วยการวางมุมมอง ในการวางซ้อนของมุมมองระดับบนสุด แล้วแสดงภาพเคลื่อนไหวการแปลในมุมมองนั้น
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();
เลย์เอาต์ขอบเขตแบบออปติคัล
สำหรับมุมมองที่มีภาพพื้นหลัง 9 จุด ตอนนี้คุณสามารถระบุได้ว่าควร อยู่ในแนวเดียวกับมุมมองใกล้เคียงบนพื้นฐานของ "ออปติคัล" ขอบเขตของภาพพื้นหลังมากกว่า มากกว่า "คลิป" ขอบเขตของมุมมอง
ตัวอย่างเช่น รูปที่ 1 และ 2 แต่ละรายการแสดงเลย์เอาต์เหมือนกัน แต่เวอร์ชันในรูปที่ 1 คือ โดยใช้ขอบเขตคลิป (ลักษณะการทำงานเริ่มต้น) ในขณะที่รูปที่ 2 ใช้ขอบเขตแบบออปติคัล เนื่องจาก รูปภาพ 9 เส้นที่ใช้สำหรับปุ่ม และกรอบรูปมีระยะห่างจากขอบรอบขอบ ดูเหมือนจะไม่ปรับเข้าหากันหรือข้อความเมื่อใช้ขอบเขตของคลิป
หมายเหตุ: ภาพหน้าจอในรูปที่ 1 และ 2 จะมีข้อความ "แสดง ขอบเขตของเลย์เอาต์" เปิดใช้การตั้งค่าสำหรับนักพัฒนาซอฟต์แวร์แล้ว ในแต่ละมุมมอง เส้นสีแดงจะแสดงถึงเส้นแสง ขอบ เส้นสีฟ้าแสดงถึงขอบเขตของคลิป และสีชมพูหมายถึงขอบ
หากต้องการปรับมุมมองตามขอบเขตแสง ให้ตั้งค่าแอตทริบิวต์ android:layoutMode
เป็น "opticalBounds"
ในเลย์เอาต์หลักรายการใดรายการหนึ่ง เช่น
<LinearLayout android:layoutMode="opticalBounds" ... >
เพื่อให้สามารถใช้งานได้ ภาพ 9 จุดที่ใช้กับพื้นหลังของมุมมองของคุณต้องระบุ ขอบเขตแบบออปติคัลที่ใช้เส้นสีแดงที่ด้านล่างและด้านขวาของไฟล์ 9 แพตช์ (ตาม แสดงในรูปที่ 3) เส้นสีแดงจะระบุพื้นที่ที่ควรลบออกจาก ขอบเขตของคลิป ออกจากขอบเขตแบบออปติคัลของรูปภาพ
เมื่อคุณเปิดใช้ขอบเขตออปติคัลสำหรับ ViewGroup
ในเลย์เอาต์
มุมมองสืบทอดจะสืบทอดโหมดการออกแบบขอบเขตออปติคัล เว้นแต่ว่าคุณจะลบล้างโหมดนี้สำหรับกลุ่มตาม
การตั้งค่า android:layoutMode
เป็น "clipBounds"
องค์ประกอบเค้าโครงทั้งหมดยังเป็นไปตาม
ขอบเขตการมองเห็นของเด็กๆ แล้วปรับขอบเขตของตัวเองตามขอบเขตทางแสงของ
ยอดดูภายในวิดีโอเหล่านั้น แต่องค์ประกอบการออกแบบ (คลาสย่อยของ ViewGroup
)
ปัจจุบันยังไม่รองรับขอบเขตแบบออปติคัลสำหรับรูปภาพ 9 จุดที่ใช้กับพื้นหลังของตนเอง
หากคุณสร้างข้อมูลพร็อพเพอร์ตี้ที่กำหนดเองโดยการแยกประเภทย่อย View
, ViewGroup
หรือคลาสย่อยใดๆ ของข้อมูลพร็อพเพอร์ตี้ดังกล่าว ข้อมูลพร็อพเพอร์ตี้ของคุณจะสืบทอดลักษณะการทำงานขอบเขตออปติคัลเหล่านี้
หมายเหตุ: วิดเจ็ตทั้งหมดที่ธีม Holo รองรับได้รับการอัปเดตแล้ว
ที่มีขอบเขตออปติคัล รวมถึง Button
, Spinner
EditText
และอื่นๆ คุณจึงได้รับประโยชน์ทันทีโดยการตั้งค่า
แอตทริบิวต์ android:layoutMode
เป็น "opticalBounds"
หากแอปใช้ธีม Holo
(Theme.Holo
, Theme.Holo.Light
ฯลฯ)
หากต้องการระบุขอบเขตแบบออปติคัลสำหรับรูปภาพ 9 เส้นของคุณเองด้วยเครื่องมือวาด 9 เส้น ให้กด "ควบคุม" ค้างไว้ คลิกพิกเซลเส้นขอบ
ภาพเคลื่อนไหวสำหรับค่าสี่เหลี่ยมผืนผ้า
ตอนนี้คุณสามารถสร้างภาพเคลื่อนไหวระหว่างค่า Rect
2 ค่าด้วย RectEvaluator
ใหม่ ชั้นเรียนใหม่นี้เป็นการปรับใช้ TypeEvaluator
ที่คุณสามารถส่งไปยัง ValueAnimator.setEvaluator()
ได้
การแนบหน้าต่างและโฟกัส Listener
ก่อนหน้านี้ หากคุณต้องการฟังเมื่อมุมมองแนบ/หลุดออกจากหน้าต่าง หรือ
เมื่อโฟกัสเปลี่ยนไป คุณต้องลบล้างคลาส View
เพื่อ
ใช้ onAttachedToWindow()
และ onDetachedFromWindow()
หรือ onWindowFocusChanged()
ตามลำดับ
หากต้องการรับเหตุการณ์ที่แนบและถอดออก ให้ใช้ ViewTreeObserver.OnWindowAttachListener
และตั้งค่าเป็นมุมมอง
addOnWindowAttachListener()
และหากต้องการรับเหตุการณ์ที่ต้องการสมาธิ คุณสามารถใช้ ViewTreeObserver.OnWindowFocusChangeListener
และตั้งค่าเป็นข้อมูลพร็อพเพอร์ตี้ที่มี
addOnWindowFocusChangeListener()
รองรับโอเวอร์สแกนทีวี
คุณเปิดใช้โอเวอร์สแกนได้เพื่อให้แอปเต็มหน้าจอทีวีทุกเครื่อง
เลย์เอาต์ของแอปคุณ โหมดโอเวอร์สแกนจะกำหนดด้วยแฟล็ก FLAG_LAYOUT_IN_OVERSCAN
ซึ่งคุณสามารถเปิดใช้ด้วยธีมแพลตฟอร์มต่างๆ ได้ เช่น
Theme_DeviceDefault_NoActionBar_Overscan
หรือโดยการเปิดใช้
สไตล์ windowOverscan
ในธีมที่กำหนดเอง
การวางแนวหน้าจอ
<activity>
screenOrientation
ของแท็ก
ปัจจุบันแอตทริบิวต์รองรับค่าเพิ่มเติม เพื่อให้เป็นไปตามความต้องการของผู้ใช้สำหรับการหมุนเวียนอัตโนมัติ
"userLandscape"
- ทำงานเหมือนกับ
"sensorLandscape"
เว้นแต่ผู้ใช้ปิดใช้การหมุนอัตโนมัติ อุปกรณ์จะล็อกในแนวแนวนอนปกติและไม่พลิก "userPortrait"
- ทำงานเหมือนกับ
"sensorPortrait"
เว้นแต่ผู้ใช้ปิดใช้การหมุนอัตโนมัติ โทรศัพท์จะล็อกในแนวตั้งตามปกติ และจะไม่พลิกกลับ "fullUser"
- ทำงานเหมือนกับ
"fullSensor"
และอนุญาตให้หมุนได้ทั้ง 4 ทิศทาง ยกเว้น หากผู้ใช้ปิดใช้การหมุนอัตโนมัติ ระบบจะล็อกตามการวางแนวที่ผู้ใช้ต้องการ
นอกจากนี้ คุณยังประกาศ "locked"
เพื่อล็อกการวางแนวของแอปได้ด้วย
การวางแนวหน้าจอปัจจุบัน
ภาพเคลื่อนไหวการหมุน
ช่อง rotationAnimation
ใหม่ใน
WindowManager
ให้คุณเลือกภาพเคลื่อนไหว 1 แบบจาก 3 แบบ
ที่ต้องการใช้เมื่อระบบเปลี่ยนการวางแนวหน้าจอ ภาพเคลื่อนไหวทั้ง 3 แบบมีดังนี้
หมายเหตุ: ภาพเคลื่อนไหวเหล่านี้จะพร้อมใช้งานเมื่อคุณตั้งค่ากิจกรรมให้ใช้ "เต็มหน้าจอ" ซึ่งคุณสามารถเปิดใช้กับธีมอย่างเช่น Theme.Holo.NoActionBar.Fullscreen
ตัวอย่างเช่น ต่อไปนี้เป็นวิธีเปิดใช้ "ครอสเฟด" ภาพเคลื่อนไหว:
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); ... }
ข้อมูลจากผู้ใช้
เซ็นเซอร์ประเภทใหม่
เซ็นเซอร์ TYPE_GAME_ROTATION_VECTOR
ใหม่ช่วยให้คุณตรวจจับการหมุนของอุปกรณ์ได้โดยไม่ต้องกังวลเกี่ยวกับสัญญาณรบกวนแม่เหล็ก TYPE_GAME_ROTATION_VECTOR
ไม่เหมือนกับเซ็นเซอร์ TYPE_ROTATION_VECTOR
ตรงที่ไม่อ้างอิงทางแม่เหล็กเหนือ
เซ็นเซอร์ TYPE_GYROSCOPE_UNCALIBRATED
และ TYPE_MAGNETIC_FIELD_UNCALIBRATED
ใหม่ให้ข้อมูลดิบของเซ็นเซอร์โดยไม่มี
การประเมินการให้อคติ ซึ่งก็คือ TYPE_GYROSCOPE
และ TYPE_MAGNETIC_FIELD
ที่มีอยู่
เซ็นเซอร์ให้ข้อมูลเซ็นเซอร์ที่พิจารณาการให้น้ำหนักพิเศษโดยประมาณจากเครื่องวัดการหมุนและเหล็กแข็ง
ในอุปกรณ์ตามลำดับ ขณะที่โหมด "ไม่ได้ปรับเทียบ" ใหม่ จะมีเวอร์ชันเซ็นเซอร์เหล่านี้
ข้อมูลดิบของเซ็นเซอร์ และเสนอค่าการให้น้ำหนักโดยประมาณแยกต่างหาก เซ็นเซอร์เหล่านี้ช่วยให้คุณ
ระบุการปรับเทียบข้อมูลเซ็นเซอร์ที่คุณกำหนดเอง โดยการปรับปรุงการให้น้ำหนักพิเศษโดยประมาณด้วย
ข้อมูลภายนอก
บริการฟังการแจ้งเตือน
Android 4.3 เพิ่มคลาสบริการใหม่ NotificationListenerService
ซึ่งทำให้แอปของคุณสามารถรับข้อมูลเกี่ยวกับการแจ้งเตือนใหม่เมื่อมีการโพสต์โดยระบบ
หากปัจจุบันแอปของคุณใช้ API บริการการช่วยเหลือพิเศษเพื่อเข้าถึงการแจ้งเตือนของระบบ คุณควรอัปเดตแอปให้ใช้ API เหล่านี้แทน
Contacts Provider
การค้นหา "รายชื่อติดต่อ"
การค้นหาใหม่ของผู้ให้บริการรายชื่อติดต่อชื่อ Contactables.CONTENT_URI
เป็นวิธีที่มีประสิทธิภาพในการรับ Cursor
หนึ่งรายการที่มีอีเมลและหมายเลขโทรศัพท์ทั้งหมดที่เป็นของรายชื่อติดต่อทั้งหมดที่ตรงกับคำค้นหาที่ระบุ
การค้นหาเดลต้ารายชื่อติดต่อ
มีการเพิ่ม API ใหม่ไปยัง Contacts Provider ที่จะช่วยให้คุณค้นหาการเปลี่ยนแปลงล่าสุดในข้อมูลติดต่อได้อย่างมีประสิทธิภาพ ก่อนหน้านี้ แอปของคุณจะได้รับการแจ้งเตือนเมื่อมีการเปลี่ยนแปลงบางอย่างในข้อมูลรายชื่อติดต่อ แต่คุณไม่ทราบแน่ชัดว่ามีอะไรเปลี่ยนแปลงบ้าง และจะต้องดึงข้อมูลรายชื่อติดต่อทั้งหมด จากนั้นทำซ้ำผ่านรายชื่อเหล่านั้นเพื่อดูการเปลี่ยนแปลง
หากต้องการติดตามการเปลี่ยนแปลงในการแทรกและอัปเดต ตอนนี้คุณสามารถใส่พารามิเตอร์ CONTACT_LAST_UPDATED_TIMESTAMP
ลงในส่วนที่เลือกเพื่อค้นหาเฉพาะรายชื่อติดต่อที่มีการเปลี่ยนแปลงตั้งแต่ครั้งล่าสุดที่คุณค้นหาผู้ให้บริการได้แล้ว
หากต้องการติดตามว่ารายชื่อติดต่อใดถูกลบแล้ว ตารางใหม่ ContactsContract.DeletedContacts
จะแสดงบันทึกรายชื่อติดต่อที่ถูกลบไปแล้ว (แต่รายชื่อติดต่อที่ลบแต่ละรายการจะเก็บไว้ในตารางนี้ในระยะเวลาจำกัด) คุณสามารถใช้พารามิเตอร์การเลือกใหม่ นั่นคือ CONTACT_DELETED_TIMESTAMP
ได้เช่นเดียวกับ CONTACT_LAST_UPDATED_TIMESTAMP
เพื่อตรวจสอบว่ารายชื่อติดต่อใดถูกลบไปตั้งแต่ครั้งล่าสุดที่คุณค้นหาผู้ให้บริการ นอกจากนี้ ตารางยังมี DAYS_KEPT_MILLISECONDS
คงที่ซึ่งมีจำนวนวัน (เป็นมิลลิวินาที) ที่จะเก็บรักษาบันทึกไว้
นอกจากนี้ ผู้ให้บริการรายชื่อติดต่อจะประกาศการดำเนินการ CONTACTS_DATABASE_CREATED
เมื่อผู้ใช้
ล้างพื้นที่เก็บข้อมูลของรายชื่อติดต่อโดยใช้เมนูการตั้งค่าระบบ ซึ่งช่วยสร้าง
ฐานข้อมูล Contacts Provider โดยมีจุดประสงค์เพื่อส่งสัญญาณให้แอปทราบว่าจำเป็นต้องยกเลิกการติดต่อทั้งหมด
ข้อมูลที่จัดเก็บไว้ และโหลดซ้ำด้วยข้อความค้นหาใหม่
สำหรับโค้ดตัวอย่างที่ใช้ API เหล่านี้เพื่อตรวจสอบการเปลี่ยนแปลงในรายชื่อติดต่อ โปรดดูใน ApiDemos ตัวอย่างที่มีอยู่ในการดาวน์โหลดตัวอย่าง SDK
การแปล
ปรับปรุงการรองรับข้อความแบบ 2 ทิศทาง
Android เวอร์ชันก่อนหน้ารองรับภาษาและเลย์เอาต์แบบขวาไปซ้าย (RTL)
แต่บางครั้งก็จัดการข้อความที่มีทิศทางแบบผสมไม่ถูกต้อง Android 4.3 จึงเพิ่ม BidiFormatter
API ที่ช่วยให้คุณจัดรูปแบบข้อความที่มีทิศทางตรงกันข้ามได้อย่างเหมาะสม
เนื้อหาโดยไม่ทำให้ส่วนใดของเนื้อหาดูไม่เป็นระเบียบ
เช่น เมื่อต้องการสร้างประโยคที่มีตัวแปรสตริง เช่น "หรือคุณหมายถึง
15 Bay Street, Laurel, CA?" โดยปกติแล้วคุณจะส่งแหล่งข้อมูลสตริงที่แปลแล้วและตัวแปรไปยัง
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);
อย่างไรก็ตาม ถ้าภาษาเป็นภาษาฮีบรู สตริงรูปแบบจะมีลักษณะดังนี้
月 יבריורी ל 15 Bay Street Laurel แคลิฟอร์เนีย
ไม่ถูกต้องเนื่องจาก "15" ควรอยู่บนถนน "Bay Street" วิธีแก้ไขคือใช้ BidiFormatter
และเมธอด unicodeWrap()
ตัวอย่างเช่น โค้ดด้านบนจะเป็นดังนี้
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));
โดยค่าเริ่มต้น unicodeWrap()
จะใช้เมธอด
การประเมินทิศทางของการประมาณทิศทางแรกอย่างแม่นยำ ซึ่งอาจทําให้เกิดข้อผิดพลาดหาก
สัญญาณสำหรับทิศทางของข้อความไม่ได้แสดงถึงทิศทางที่เหมาะสมสำหรับเนื้อหาโดยรวม
หากจำเป็น คุณสามารถระบุวิธีการเรียนรู้แบบอื่นโดยการส่งผ่านค่าคงที่ TextDirectionHeuristic
ค่าใดค่าหนึ่งจาก TextDirectionHeuristics
ไปยัง unicodeWrap()
หมายเหตุ: API ใหม่เหล่านี้จะพร้อมใช้งานสำหรับเวอร์ชันก่อนหน้าด้วยเช่นกัน
ของ Android ผ่านทางการสนับสนุนของ Android
ไลบรารี ที่มีคลาส BidiFormatter
และ API ที่เกี่ยวข้อง
บริการการช่วยเหลือพิเศษ
จัดการเหตุการณ์สําคัญ
ตอนนี้ AccessibilityService
สามารถรับการติดต่อกลับสำหรับ
เหตุการณ์การป้อนข้อมูลที่สำคัญด้วยเมธอด Callback onKeyEvent()
วิธีนี้จะช่วยให้บริการการช่วยเหลือพิเศษสามารถจัดการอินพุตสำหรับ
อุปกรณ์อินพุตที่อิงตามแป้น เช่น แป้นพิมพ์ และแปลเหตุการณ์เหล่านั้นเป็นการทำงานพิเศษที่
ก่อนหน้านี้จะทำได้ด้วยการป้อนข้อมูลด้วยการสัมผัสหรือปุ่มบังคับทิศทางของอุปกรณ์เท่านั้น
เลือกข้อความและคัดลอก/วาง
ตอนนี้ AccessibilityNodeInfo
มี API ที่อนุญาตให้
AccessibilityService
สำหรับเลือก ตัด คัดลอก และวาง
ข้อความในโหนด
ในการระบุการเลือกข้อความที่จะตัดหรือคัดลอก บริการการเข้าถึงสามารถใช้
การดำเนินการ, ACTION_SET_SELECTION
, ผ่าน
แล้วเลือกตำแหน่งเริ่มต้นและสิ้นสุดด้วย ACTION_ARGUMENT_SELECTION_START_INT
และ ACTION_ARGUMENT_SELECTION_END_INT
หรือคุณสามารถเลือกข้อความ โดยย้ายตำแหน่งเคอร์เซอร์โดยใช้
การดำเนินการ ACTION_NEXT_AT_MOVEMENT_GRANULARITY
(ก่อนหน้านี้ใช้เพียงการย้ายตำแหน่งเคอร์เซอร์เท่านั้น) และเพิ่มอาร์กิวเมนต์ ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
จากนั้นคุณสามารถตัดหรือคัดลอกด้วย ACTION_CUT
ACTION_COPY
แล้ววางในภายหลังด้วย
ACTION_PASTE
หมายเหตุ: API ใหม่เหล่านี้จะพร้อมใช้งานสำหรับเวอร์ชันก่อนหน้าด้วยเช่นกัน
ของ Android ผ่านทางการสนับสนุนของ Android
คลัง โดยมีAccessibilityNodeInfoCompat
ประกาศฟีเจอร์การช่วยเหลือพิเศษ
เริ่มตั้งแต่ Android 4.3 บริการการช่วยเหลือพิเศษจะต้องประกาศความสามารถในการเข้าถึง
ในไฟล์ข้อมูลเมตาเพื่อใช้ฟีเจอร์การช่วยเหลือพิเศษบางอย่าง หากความสามารถนั้นไม่ใช่
ที่ระบุในไฟล์ข้อมูลเมตา ฟีเจอร์นั้นจะไม่มีการดำเนินการ หากต้องการประกาศบริการของคุณ
ความสามารถในการเข้าถึง คุณต้องใช้แอตทริบิวต์ XML ที่สอดคล้องกับ
"ความสามารถ" ค่าคงที่ใน AccessibilityServiceInfo
ตัวอย่างเช่น หากบริการไม่ได้ขอความสามารถ flagRequestFilterKeyEvents
ก็จะไม่ได้รับเหตุการณ์สำคัญ
การทดสอบและการแก้ไขข้อบกพร่อง
การทดสอบ UI อัตโนมัติ
คลาส UiAutomation
ใหม่มี API ที่ให้คุณจำลองผู้ใช้ได้
การดำเนินการสำหรับการทดสอบอัตโนมัติ การใช้ AccessibilityService
API ของแพลตฟอร์มจะทำให้UiAutomation
API ช่วยให้คุณตรวจสอบเนื้อหาบนหน้าจอและแทรกแป้นพิมพ์และเหตุการณ์การแตะได้ตามต้องการ
หากต้องการรับอินสแตนซ์ของ UiAutomation
ให้เรียกใช้ Instrumentation.getUiAutomation()
อยู่ในคำสั่งซื้อ
คุณต้องใส่ตัวเลือก -w
พร้อมกับคำสั่ง instrument
เพื่อให้ดำเนินการนี้ได้
เมื่อเรียกใช้ InstrumentationTestCase
จาก adb shell
เมื่อใช้อินสแตนซ์ UiAutomation
คุณจะดำเนินเหตุการณ์ที่กำหนดเองเพื่อทดสอบได้
แอปของคุณด้วยการเรียกใช้ executeAndWaitForEvent()
ส่ง Runnable
เพื่อดำเนินการ ระยะหมดเวลา
ระยะเวลาสำหรับการดำเนินการ และการใช้งานอินเทอร์เฟซ UiAutomation.AccessibilityEventFilter
คุณจะได้รับการติดต่อทางโทรศัพท์ภายในการใช้งาน UiAutomation.AccessibilityEventFilter
ซึ่งช่วยให้คุณสามารถกรองเหตุการณ์ที่คุณสนใจ และกำหนดความสำเร็จหรือ
ของกรอบการทดสอบที่ระบุไม่สำเร็จ
หากต้องการสังเกตเหตุการณ์ทั้งหมดระหว่างการทดสอบ ให้สร้างการใช้งาน UiAutomation.OnAccessibilityEventListener
และส่งไปยัง setOnAccessibilityEventListener()
อินเทอร์เฟซของ Listener ของคุณจะได้รับการเรียกไปยัง onAccessibilityEvent()
ทุกครั้งที่เกิดเหตุการณ์ขึ้น โดยได้รับออบเจ็กต์ AccessibilityEvent
ที่อธิบายเหตุการณ์
มีการดำเนินการอื่นๆ อีกหลายอย่างที่ API ของ UiAutomation
แสดง
ในระดับที่ต่ำมาก เพื่อกระตุ้นการพัฒนาเครื่องมือทดสอบ UI เช่น uiautomator ตัวอย่างเช่น
UiAutomation
ยังสามารถ:
- แทรกเหตุการณ์อินพุต
- เปลี่ยนการวางแนวของหน้าจอ
- ถ่ายภาพหน้าจอ
และที่สำคัญที่สุดคือสำหรับเครื่องมือทดสอบ UI ที่ UiAutomation
API ทำงาน
ข้ามขอบเขตของแอปพลิเคชัน ซึ่งต่างจากใน Instrumentation
เหตุการณ์ Systrace สำหรับแอป
Android 4.3 เพิ่มคลาส Trace
ด้วย 2 วิธีแบบคงที่ ได้แก่
beginSection()
และ endSection()
ซึ่งช่วยให้คุณกำหนดบล็อกโค้ดที่จะรวมไว้กับรายงาน systrace ได้ โดยการสร้าง
ส่วนของโค้ดที่ตรวจสอบย้อนกลับได้ในแอปของคุณ บันทึกของ systrace จะแสดงรายละเอียดเพิ่มเติม
การวิเคราะห์ตำแหน่งที่เกิดการชะลอตัวภายในแอป
สําหรับข้อมูลเกี่ยวกับการใช้เครื่องมือ Systrace โปรดอ่านการวิเคราะห์การแสดงผลและประสิทธิภาพด้วย Systrace
ความปลอดภัย
แหล่งเก็บคีย์ Android สำหรับคีย์ส่วนตัวของแอป
ตอนนี้ Android มีผู้ให้บริการรักษาความปลอดภัยสำหรับ Java ที่กำหนดเองใน KeyStore
ที่เรียกว่า Android Key Store ซึ่งให้คุณสร้างและบันทึกคีย์ส่วนตัวที่
แอปของคุณจะมองเห็นและนำไปใช้ได้ หากต้องการโหลดคีย์สโตร์ Android ให้ส่งบัตร
"AndroidKeyStore"
ถึง KeyStore.getInstance()
ในการจัดการข้อมูลเข้าสู่ระบบส่วนตัวของแอปใน Android Key Store ให้สร้างคีย์ใหม่ด้วย
KeyPairGenerator
ด้วย KeyPairGeneratorSpec
แรก
รับอินสแตนซ์ของ KeyPairGenerator
โดยการเรียกใช้ getInstance()
จากนั้นโทร
initialize()
ส่งอินสแตนซ์
KeyPairGeneratorSpec
ซึ่งคุณใช้ได้ใน
KeyPairGeneratorSpec.Builder
สุดท้าย รับ KeyPair
ด้วยการโทรหา generateKeyPair()
ที่เก็บข้อมูลเข้าสู่ระบบฮาร์ดแวร์
ขณะนี้ Android รองรับพื้นที่เก็บข้อมูลแบบฮาร์ดแวร์สำหรับ KeyChain
แล้ว
ข้อมูลเข้าสู่ระบบของคุณ เพื่อเพิ่มความปลอดภัยโดยทำให้คีย์ไม่สามารถใช้ดึงข้อมูลได้ กล่าวคือ ครั้งเดียว
คีย์จะอยู่ในแหล่งเก็บคีย์ที่สนับสนุนด้วยฮาร์ดแวร์ (องค์ประกอบความปลอดภัย, TPM หรือ TrustZone) คีย์ดังกล่าวสามารถใช้เพื่อ
การดำเนินการเข้ารหัส แต่ไม่สามารถส่งออกเนื้อหาของคีย์ส่วนตัวได้ แม้แต่เคอร์เนลของระบบปฏิบัติการ
เข้าถึงเนื้อหาคีย์นี้ไม่ได้ แม้ว่าอุปกรณ์ที่ใช้ Android บางรุ่นจะไม่รองรับพื้นที่เก็บข้อมูลบน
คุณสามารถตรวจสอบขณะรันไทม์ว่าพื้นที่เก็บข้อมูลที่ใช้ฮาร์ดแวร์พร้อมใช้งานหรือไม่โดยการเรียกใช้
KeyChain.IsBoundKeyAlgorithm()
การประกาศไฟล์ Manifest
ฟีเจอร์ที่จำเป็นที่ต้องประกาศ
ตอนนี้ <uses-feature>
รองรับค่าต่อไปนี้แล้ว
องค์ประกอบเพื่อให้มั่นใจได้ว่าแอปของคุณจะติดตั้งเฉพาะในอุปกรณ์ที่มีฟีเจอร์
ที่แอปของคุณต้องใช้
FEATURE_APP_WIDGETS
- ประกาศว่าแอปของคุณมีวิดเจ็ตแอปและควรติดตั้งเฉพาะในอุปกรณ์ที่
ใส่หน้าจอหลักหรือตำแหน่งที่คล้ายกัน ซึ่งผู้ใช้สามารถฝังวิดเจ็ตของแอปได้
ตัวอย่าง
<uses-feature android:name="android.software.app_widgets" android:required="true" />
FEATURE_HOME_SCREEN
- ประกาศว่าแอปของคุณทำหน้าที่เหมือนมาแทนที่หน้าจอหลัก และควรติดตั้งเฉพาะใน
อุปกรณ์ที่สนับสนุนแอปหน้าจอหลักของบุคคลที่สาม
ตัวอย่าง
<uses-feature android:name="android.software.home_screen" android:required="true" />
FEATURE_INPUT_METHODS
- ประกาศว่าแอปของคุณมีวิธีป้อนข้อมูลที่กำหนดเอง (แป้นพิมพ์ที่สร้างด้วย
InputMethodService
) และควรติดตั้งบนอุปกรณ์ที่ สนับสนุนวิธีการป้อนข้อมูลของบุคคลที่สาม ตัวอย่าง<uses-feature android:name="android.software.input_methods" android:required="true" />
FEATURE_BLUETOOTH_LE
- ประกาศว่าแอปของคุณใช้ API บลูทูธพลังงานต่ำ และควรติดตั้งในอุปกรณ์เท่านั้น
ที่สามารถสื่อสารกับอุปกรณ์อื่นๆ ผ่านบลูทูธพลังงานต่ำได้
ตัวอย่าง
<uses-feature android:name="android.software.bluetooth_le" android:required="true" />
สิทธิ์ของผู้ใช้
ตอนนี้ <uses-permission>
รองรับค่าต่อไปนี้แล้ว
เพื่อประกาศ
ที่แอปของคุณต้องใช้เพื่อเข้าถึง API บางอย่าง
BIND_NOTIFICATION_LISTENER_SERVICE
- จำเป็นสำหรับการใช้
NotificationListenerService
API ใหม่ SEND_RESPOND_VIA_MESSAGE
- ต้องระบุเพื่อรับ
ACTION_RESPOND_VIA_MESSAGE
Intent
สำหรับมุมมองโดยละเอียดของการเปลี่ยนแปลง API ทั้งหมดใน Android 4.3 โปรดดูที่ รายงานความแตกต่างของ API