ฟีเจอร์และ API ของ Android 8.1

Android 8.1 (ระดับ API 27) เปิดตัวฟีเจอร์และความสามารถใหม่ๆ มากมายสำหรับผู้ใช้และนักพัฒนาแอป เอกสารนี้จะเน้นย้ำถึงฟีเจอร์ใหม่ๆ สำหรับนักพัฒนาแอป

Android Oreo (รุ่น Go)

Android Go เป็นโครงการริเริ่มของเราในการเพิ่มประสิทธิภาพประสบการณ์การใช้งาน Android สำหรับ ผู้คนหลายพันล้านคนทั่วโลกที่กำลังจะเข้าสู่โลกออนไลน์ ตั้งแต่ Android 8.1 เป็นต้นไป เราจะทำให้ Android เป็นแพลตฟอร์มที่ยอดเยี่ยมสำหรับอุปกรณ์ระดับเริ่มต้น ฟีเจอร์ในการกำหนดค่า Android Oreo (รุ่น Go) มีดังนี้

  • การเพิ่มประสิทธิภาพหน่วยความจำ ปรับปรุงการใช้หน่วยความจำในแพลตฟอร์มเพื่อให้มั่นใจว่าแอปจะทำงานได้อย่างมีประสิทธิภาพในอุปกรณ์ที่มี RAM 1 GB หรือน้อยกว่า
  • ตัวเลือกการกำหนดเป้าหมายที่ยืดหยุ่น ค่าคงที่ของฟีเจอร์ฮาร์ดแวร์ใหม่ เพื่อให้คุณกำหนดเป้าหมายการเผยแพร่แอปไปยังอุปกรณ์ที่มี RAM ปกติหรือต่ำผ่าน Google Play ได้
  • Google Play แม้ว่าแอปทั้งหมดจะพร้อมให้บริการในอุปกรณ์ที่ใช้ Android Oreo (รุ่น Go) แต่ Google Play จะให้การมองเห็นแก่แอปที่นักพัฒนาแอปปรับแต่งมาโดยเฉพาะ เพื่อมอบประสบการณ์การใช้งานที่ยอดเยี่ยมแก่ผู้ใช้หลายพันล้านคนตาม หลักเกณฑ์สำหรับแอปที่สร้างขึ้นเพื่อผู้ใช้หลายพันล้านคน

เราได้อัปเดต หลักเกณฑ์การสร้างแอปสำหรับผู้ใช้หลายพันล้านคน พร้อมคำแนะนำเพิ่มเติมเกี่ยวกับวิธี เพิ่มประสิทธิภาพแอปสำหรับอุปกรณ์ที่ใช้ Android Oreo (รุ่น Go) สำหรับนักพัฒนาแอปส่วนใหญ่ การเพิ่มประสิทธิภาพ APK ที่มีอยู่หรือการใช้ ฟีเจอร์ APK หลายรายการของ Google Play เพื่อกำหนดเป้าหมาย APK เวอร์ชันหนึ่งไปยังอุปกรณ์ที่มี RAM ต่ำ เป็นวิธีที่ดีที่สุดในการเตรียมพร้อมสำหรับอุปกรณ์ที่ใช้ Android Oreo (Go Edition) โปรดทราบว่าการทำให้แอป เบาและมีประสิทธิภาพมากขึ้นจะเป็นประโยชน์ต่อผู้ชมทั้งหมด ไม่ว่าจะใช้อุปกรณ์ใดก็ตาม

Neural Networks API

Neural Networks API ช่วยให้การคำนวณและการอนุมานสำหรับเฟรมเวิร์กแมชชีนเลิร์นนิงในอุปกรณ์ เช่น TensorFlow Lite ซึ่งเป็นไลบรารี ML แบบข้ามแพลตฟอร์มของ Google สำหรับอุปกรณ์เคลื่อนที่ รวมถึง Caffe2 และอื่นๆ ทำงานได้เร็วขึ้น ไปที่ที่เก็บโอเพนซอร์สของ TensorFlow Lite เพื่อดาวน์โหลดและดูเอกสาร TensorFlow Lite ทำงานร่วมกับ Neural Networks API เพื่อเรียกใช้โมเดลต่างๆ เช่น MobileNets Inception v3 และ การตอบกลับอัจฉริยะอย่างมีประสิทธิภาพในอุปกรณ์เคลื่อนที่

การอัปเดตเฟรมเวิร์กการป้อนข้อความอัตโนมัติ

Android 8.1 (ระดับ API 27) มีการปรับปรุงหลายอย่างใน Autofill Framework ที่คุณสามารถนำไปใช้ในแอปได้

ตอนนี้BaseAdapter คลาสมีเมธอด setAutofillOptions() ซึ่งช่วยให้คุณระบุการแสดงสตริงของค่าใน อแดปเตอร์ได้ ซึ่งมีประโยชน์สำหรับตัวควบคุม spinner ที่สร้างค่าในอะแดปเตอร์แบบไดนามิก เช่น คุณสามารถใช้เมธอด setAutofillOptions() เพื่อระบุการแสดงสตริง ของรายการปีที่ผู้ใช้เลือกได้เป็นส่วนหนึ่งของ วันหมดอายุของบัตรเครดิต บริการป้อนข้อความอัตโนมัติสามารถใช้การแสดงสตริง เพื่อกรอกข้อมูลในมุมมองที่ต้องใช้ข้อมูลได้อย่างเหมาะสม

นอกจากนี้ AutofillManager คลาสยังมีnotifyViewVisibilityChanged(View, int, boolean)เมธอด ที่คุณเรียกใช้เพื่อแจ้งเฟรมเวิร์กเกี่ยวกับการเปลี่ยนแปลงระดับการมองเห็นของ มุมมองในโครงสร้างเสมือนได้ นอกจากนี้ ยังมีการโอเวอร์โหลดของเมธอดสำหรับโครงสร้างที่ไม่ใช่ เสมือนด้วย อย่างไรก็ตาม โครงสร้างที่ไม่ใช่เสมือนมักไม่จำเป็นต้องให้คุณ แจ้งเฟรมเวิร์กอย่างชัดเจน เนื่องจากView คลาสเรียกใช้เมธอดนี้อยู่แล้ว

Android 8.1 ยังช่วยให้บริการป้อนข้อความอัตโนมัติปรับแต่งความสามารถในการแสดง UI การบันทึกได้มากขึ้น โดยเพิ่มการรองรับ CustomDescription and Validator ภายใน SaveInfo

คำอธิบายที่กำหนดเองมีประโยชน์ในการช่วยให้บริการป้อนข้อความอัตโนมัติชี้แจงสิ่งที่ กำลังบันทึก ตัวอย่างเช่น เมื่อหน้าจอมีบัตรเครดิต ก็อาจแสดงโลโก้ของธนาคารที่ออกบัตรเครดิต ตัวเลข 4 หลักสุดท้ายของหมายเลขบัตรเครดิต และหมายเลขวันหมดอายุ ดูข้อมูลเพิ่มเติมได้ที่ CustomDescription ชั้นเรียน

Validator ออบเจ็กต์ใช้เพื่อหลีกเลี่ยงการแสดง UI การบันทึกการป้อนข้อความอัตโนมัติเมื่อไม่เป็นไปตามเงื่อนไขของ Validator ดูข้อมูลเพิ่มเติมได้ที่คลาส Validator พร้อมด้วยคลาสย่อย LuhnChecksumValidator และ RegexValidator

การแจ้งเตือน

Android 8.1 มีการเปลี่ยนแปลงการแจ้งเตือนดังนี้

  • ตอนนี้แอปจะส่งเสียงแจ้งเตือนได้เพียงครั้งเดียวต่อวินาที ระบบจะไม่จัดคิวและจะทิ้งเสียงการแจ้งเตือนที่เกินอัตรานี้ การเปลี่ยนแปลงนี้ไม่มีผลต่อลักษณะการทำงานของการแจ้งเตือนในด้านอื่นๆ และข้อความแจ้งเตือนจะยังคงโพสต์ตามที่คาดไว้
  • NotificationListenerService และ ConditionProviderService ไม่รองรับในอุปกรณ์ Android ที่มี RAM ต่ำ ซึ่งจะแสดง true เมื่อมีการเรียกใช้ ActivityManager.isLowRamDevice()

การอัปเดต EditText

ตั้งแต่ระดับ API 27 เป็นต้นไป เมธอด EditText.getText() จะแสดง Editable ก่อนหน้านี้ จะแสดง CharSequence การเปลี่ยนแปลงนี้เข้ากันได้แบบย้อนหลัง เนื่องจาก Editable ใช้ CharSequence

Editable อินเทอร์เฟซมีฟังก์ชันเพิ่มเติมที่มีประโยชน์ ตัวอย่างเช่น เนื่องจาก Editable ยัง ใช้Spannable อินเทอร์เฟซด้วย คุณจึงใช้มาร์กอัปกับ เนื้อหาภายในอินสแตนซ์ของ EditText ได้

การดำเนินการของ Google Safe Browsing แบบเป็นโปรแกรม

การใช้ WebViewการติดตั้งใช้งาน ของ Google Safe Browsing API จะช่วยให้แอป ตรวจหาได้เมื่ออินสแตนซ์ของ WebView พยายามไปยัง URL ที่ Google จัดประเภทว่าเป็นภัยคุกคามที่ทราบ โดยค่าเริ่มต้น WebView จะแสดงโฆษณาคั่นระหว่างหน้าที่เตือนผู้ใช้ถึงภัยคุกคามที่ทราบ หน้าจอนี้จะให้ตัวเลือกแก่ผู้ใช้ในการโหลด URL ต่อไปหรือกลับไปยัง หน้าก่อนหน้าที่ปลอดภัย

ใน Android 8.1 คุณสามารถกำหนดโดยใช้โปรแกรมว่าแอปจะตอบสนองต่อภัยคุกคามที่ทราบได้อย่างไร

  • คุณควบคุมได้ว่าแอปจะรายงานภัยคุกคามที่ทราบไปยัง Google Safe Browsing หรือไม่
  • คุณตั้งค่าให้แอปดำเนินการบางอย่างโดยอัตโนมัติได้ เช่น กลับไปที่โหมดปลอดภัย ทุกครั้งที่แอปพบ URL ที่ Google Safe Browsing จัดประเภทเป็นภัยคุกคามที่ทราบ

หมายเหตุ: เพื่อการปกป้องที่ดีที่สุดจากภัยคุกคามที่ทราบแล้ว ให้รอจนกว่าคุณจะเริ่มต้นใช้งาน Google Safe Browsing ก่อนที่จะเรียกใช้เมธอด loadUrl() ของออบเจ็กต์ WebView

ข้อมูลโค้ดต่อไปนี้แสดงวิธีสั่งให้อินสแตนซ์ของ WebView ในแอปกลับไปที่โหมดปลอดภัยเสมอหลังจากพบภัยคุกคามที่รู้จัก

AndroidManifest.xml

<manifest>
    <application>
        ...
        <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                   android:value="true" />
    </application>
</manifest>

MyWebActivity.java

Kotlin

private var superSafeWebView: WebView? = null
private var safeBrowsingIsInitialized: Boolean = false

// ...

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    superSafeWebView = WebView(this).apply {
        webViewClient = MyWebViewClient()
        safeBrowsingIsInitialized = false
        startSafeBrowsing(this@SafeBrowsingActivity, { success ->
            safeBrowsingIsInitialized = true
            if (!success) {
                Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!")
            }
        })
    }
}

Java

private WebView superSafeWebView;
private boolean safeBrowsingIsInitialized;

// ...

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    superSafeWebView = new WebView(this);
    superSafeWebView.setWebViewClient(new MyWebViewClient());
    safeBrowsingIsInitialized = false;

    superSafeWebView.startSafeBrowsing(this, new ValueCallback<Boolean>() {
        @Override
        public void onReceiveValue(Boolean success) {
            safeBrowsingIsInitialized = true;
            if (!success) {
                Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!");
            }
        }
    });
}

MyWebViewClient.java

Kotlin

class MyWebViewClient : WebViewClient() {
    // Automatically go "back to safety" when attempting to load a website that
    // Safe Browsing has identified as a known threat. An instance of WebView
    // calls this method only after Safe Browsing is initialized, so there's no
    // conditional logic needed here.
    override fun onSafeBrowsingHit(
            view: WebView,
            request: WebResourceRequest,
            threatType: Int,
            callback: SafeBrowsingResponse
    ) {
        // The "true" argument indicates that your app reports incidents like
        // this one to Safe Browsing.
        callback.backToSafety(true)
        Toast.makeText(view.context, "Unsafe web page blocked.", Toast.LENGTH_LONG).show()
    }
}

Java

public class MyWebViewClient extends WebViewClient {
    // Automatically go "back to safety" when attempting to load a website that
    // Safe Browsing has identified as a known threat. An instance of WebView
    // calls this method only after Safe Browsing is initialized, so there's no
    // conditional logic needed here.
    @Override
    public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
            int threatType, SafeBrowsingResponse callback) {
        // The "true" argument indicates that your app reports incidents like
        // this one to Safe Browsing.
        callback.backToSafety(true);
        Toast.makeText(view.getContext(), "Unsafe web page blocked.",
                Toast.LENGTH_LONG).show();
    }
}

โปรแกรมแยกภาพปกวิดีโอ

คลาส MediaMetadataRetriever มีเมธอดใหม่ getScaledFrameAtTime() ซึ่งจะค้นหา เฟรมที่อยู่ใกล้กับตำแหน่งเวลาที่ระบุและแสดงผลบิตแมปที่มีสัดส่วน เดียวกันกับเฟรมต้นฉบับ แต่ปรับขนาดให้พอดีกับสี่เหลี่ยมผืนผ้าที่มีความกว้างและความสูงที่ระบุ ซึ่งมีประโยชน์สำหรับการสร้างภาพปกจากวิดีโอ

เราขอแนะนำให้ใช้วิธีนี้แทน getFrameAtTime() ซึ่งอาจทำให้หน่วยความจำหมด เนื่องจากจะแสดงผลบิตแมปที่มีความละเอียดเท่ากับวิดีโอต้นฉบับ ตัวอย่างเช่น เฟรมจากวิดีโอ 4K จะเป็นบิตแมปขนาด 16 MB ซึ่งใหญ่กว่าขนาดที่คุณต้องการสำหรับภาพปกวิดีโอมาก

Shared Memory API

Android 8.1 (ระดับ API 27) เปิดตัว SharedMemory API ใหม่ คลาสนี้ช่วยให้คุณสร้าง แมป และจัดการอินสแตนซ์ที่ไม่ระบุตัวตน SharedMemory ได้ คุณตั้งค่าการป้องกันหน่วยความจำ ในออบเจ็กต์ SharedMemory สำหรับการอ่านและ/หรือเขียน และเนื่องจากออบเจ็กต์ SharedMemory เป็น Parcelable คุณจึงส่งไปยังกระบวนการอื่นผ่าน AIDL ได้อย่างง่ายดาย

SharedMemory API ทำงานร่วมกับ ASharedMemory ใน NDK ASharedMemory ให้สิทธิ์เข้าถึง ตัวอธิบายไฟล์ ซึ่งสามารถแมปเพื่ออ่านและเขียนได้ ซึ่งเป็นวิธีที่ยอดเยี่ยม ในการแชร์ข้อมูลจำนวนมาก ระหว่างแอปหรือระหว่างกระบวนการหลายอย่างภายในแอปเดียว

WallpaperColors API

Android 8.1 (ระดับ API 27) อนุญาตให้วอลเปเปอร์เคลื่อนไหวของคุณให้ข้อมูลสีแก่ UI ของระบบได้ คุณทำได้โดยสร้างWallpaperColors ออบเจ็กต์จากบิตแมป, Drawable หรือโดยใช้สี 3 สีที่เลือกด้วยตนเอง นอกจากนี้ คุณยังดึงข้อมูลสีนี้ได้ด้วย

หากต้องการสร้างWallpaperColors ออบเจ็กต์ ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้

  • หากต้องการสร้างWallpaperColors ออบเจ็กต์โดยใช้ 3 สี ให้สร้างอินสแตนซ์ของคลาส WallpaperColors โดยส่งสีหลัก สีรอง และสีเสริม ต้องระบุสีหลัก
  • หากต้องการสร้างออบเจ็กต์ WallpaperColors จากบิตแมป ให้เรียกใช้เมธอด fromBitmap() โดยส่งแหล่งที่มาของบิตแมปเป็นพารามิเตอร์
  • หากต้องการสร้างออบเจ็กต์ WallpaperColors จาก Drawable ให้เรียกใช้เมธอด fromDrawable() โดยส่งแหล่งที่มาของ Drawable เป็นพารามิเตอร์

หากต้องการดึงรายละเอียดสีหลัก สีรอง หรือสีระดับที่ 3 จากวอลเปเปอร์ ให้เรียกใช้เมธอดต่อไปนี้

  • getPrimaryColor() จะแสดงสีที่แสดงถึงวอลเปเปอร์ได้ดีที่สุด
  • getSecondaryColor() แสดงสีที่โดดเด่นที่สุดเป็นอันดับ 2 ของวอลเปเปอร์
  • getTertiaryColor() เมธอดจะแสดงสีที่โดดเด่นเป็นอันดับ 3 ของวอลเปเปอร์

หากต้องการแจ้งระบบเกี่ยวกับการเปลี่ยนแปลงสีที่สำคัญในวอลเปเปอร์เคลื่อนไหว ให้เรียกใช้เมธอด notifyColorsChanged() เมธอดนี้จะทริกเกอร์เหตุการณ์onComputeColors()วงจร ซึ่งคุณจะมีโอกาสระบุออบเจ็กต์ WallpaperColors ใหม่

หากต้องการเพิ่ม Listener สำหรับการเปลี่ยนสี ให้เรียกใช้เมธอด addOnColorsChangedListener() คุณยังเรียกใช้เมธอด getWallpaperColors() เพื่อดึงสีหลักของวอลเปเปอร์ได้ด้วย

การอัปเดตลายนิ้วมือ

คลาส FingerprintManager ได้ เปิดตัวรหัสข้อผิดพลาดต่อไปนี้

  • FINGERPRINT_ERROR_LOCKOUT_PERMANENT – ผู้ใช้พยายามปลดล็อกอุปกรณ์โดยใช้เครื่องอ่านลายนิ้วมือหลายครั้งเกินไป
  • FINGERPRINT_ERROR_VENDOR - เกิดข้อผิดพลาดเกี่ยวกับเครื่องอ่านลายนิ้วมือที่เจาะจงผู้ให้บริการ

การอัปเดตวิทยาการเข้ารหัส

เราได้ทำการเปลี่ยนแปลงด้านการเข้ารหัสหลายอย่างใน Android 8.1 ดังนี้

  • เราได้ติดตั้งใช้งานอัลกอริทึมใหม่ใน Conscrypt ระบบจะใช้การติดตั้งใช้งาน Conscrypt ก่อนการติดตั้งใช้งาน Bouncy Castle ที่มีอยู่ อัลกอริทึมใหม่มีดังนี้
    • AlgorithmParameters:GCM
    • KeyGenerator:AES
    • KeyGenerator:DESEDE
    • KeyGenerator:HMACMD5
    • KeyGenerator:HMACSHA1
    • KeyGenerator:HMACSHA224
    • KeyGenerator:HMACSHA256
    • KeyGenerator:HMACSHA384
    • KeyGenerator:HMACSHA512
    • SecretKeyFactory:DESEDE
    • Signature:NONEWITHECDSA
  • Cipher.getParameters().getParameterSpec(IvParameterSpec.class) ใช้ไม่ได้กับอัลกอริทึมที่ใช้ GCM อีกต่อไป ให้ใช้ getParameterSpec(GCMParameterSpec.class) แทน
  • เราได้ปรับโครงสร้างคลาส Conscrypt ภายในหลายคลาสที่เชื่อมโยงกับ TLS เนื่องจากบางครั้งนักพัฒนาแอปเข้าถึงฟีเจอร์เหล่านี้โดยอ้อม เราจึงคง Shim ไว้เพื่อรองรับการใช้งานก่อนหน้านี้ แต่รายละเอียดบางอย่างมีการเปลี่ยนแปลง เช่น ก่อนหน้านี้ซ็อกเก็ตมีประเภทเป็น OpenSSLSocketImpl แต่ตอนนี้มีประเภทเป็น ConscryptFileDescriptorSocket หรือ ConscryptEngineSocket ซึ่งทั้ง 2 ประเภทนี้ขยาย OpenSSLSocketImpl
  • SSLSessionวิธีการที่ใช้ในการส่งข้อยกเว้น IllegalArgumentExceptionเมื่อส่งการอ้างอิงที่ค่าเป็น Null ตอนนี้จะส่งข้อยกเว้น NullPointerException
  • RSA KeyFactory ไม่อนุญาตให้สร้างคีย์จากอาร์เรย์ไบต์ที่มีขนาดใหญ่กว่าคีย์ที่เข้ารหัสอีกต่อไป การโทรไปยัง generatePrivate() และ generatePublic() ที่ให้ KeySpec ซึ่งโครงสร้างคีย์ไม่ได้เติม บัฟเฟอร์ทั้งหมดจะส่งผลให้เกิด InvalidKeySpecException
  • เมื่อการอ่านซ็อกเก็ตถูกขัดจังหวะเนื่องจากซ็อกเก็ตปิดอยู่ Conscrypt จะ แสดงผล -1 จากการอ่าน การอ่านในตอนนี้จะทำให้เกิดข้อผิดพลาด SocketException
  • เราได้เปลี่ยนแปลงชุดใบรับรอง CA รูท โดยส่วนใหญ่เป็นการนำใบรับรองจำนวนมากที่ล้าสมัยออก รวมถึงนำใบรับรองรูทสำหรับ WoSign และ StartCom ออกด้วย ดูข้อมูลเพิ่มเติมเกี่ยวกับการตัดสินใจนี้ได้ที่บล็อกโพสต์การรักษาความปลอดภัยของ Google การ นำความน่าเชื่อถือในใบรับรองของ WoSign และ StartCom ออกในที่สุด