ميزات Android 8.1 وواجهات برمجة التطبيقات

يقدّم Android 8.1 (المستوى 27 من واجهة برمجة التطبيقات) مجموعة متنوعة من الميزات والإمكانات الجديدة للمستخدمين والمطوّرين. يوضّح هذا المستند الميزات الجديدة للمطوّرين.

Android Oreo (إصدار Go)

إنّ Android Go عبارة عن مبادرتنا لتحسين تجربة Android لمليارات المستخدمين الذين يتصلون بالإنترنت حول العالم. نحن بصدد جعل Android نظامًا أساسيًا رائعًا للأجهزة منخفضة المواصفات، بدءًا من Android 8.1. تشمل ميزات تهيئة Android Oreo (الإصدار Go) ما يلي:

  • تحسينات الذاكرة: تم تحسين استخدام الذاكرة عبر النظام الأساسي لضمان تشغيل التطبيقات بكفاءة على الأجهزة المزوّدة بذاكرة وصول عشوائي تبلغ سعتها 1 غيغابايت أو أقل.
  • خيارات الاستهداف المرنة: ثبات ميزات الأجهزة الجديدة للسماح لك بتوزيع تطبيقاتك على الأجهزة العادية أو الأجهزة ذات ذاكرة الوصول العشوائية المنخفضة من خلال Google Play.
  • Google Play.على الرغم من أنّ جميع التطبيقات ستكون متوفّرة على الأجهزة التي تعمل بنظام Android Oreo (إصدار Go)، سيوفّر Google Play إمكانية الاطّلاع على التطبيقات التي حسّنها المطوّرون تحديدًا لتوفير تجربة رائعة لمليارات المستخدمين من خلال تصميم تطبيقات لمليارات المستخدمين من الإرشادات.

أجرينا تحديثًا على تصميم اللعبة لمليارات الإرشادات من خلال إضافة إرشادات إضافية حول كيفية تحسين تطبيقك للتوافق مع الأجهزة التي تعمل بنظام التشغيل Android Oreo (إصدار Go). بالنسبة إلى معظم مطوّري البرامج، إنّ تحسين ملف APK الحالي أو استخدام ميزة APK المتعدّدة على Google Play لاستهداف إصدار من حزمة APK للأجهزة ذات ذاكرة وصول عشوائي منخفضة هو أفضل طريقة للاستعداد للأجهزة التي تعمل بالإصدار Android Oreo (إصدار Go). تذكر أن جعل تطبيقك خفيفًا وأكثر كفاءة يعود بالفائدة على جمهورك بالكامل، بصرف النظر عن الجهاز.

واجهة برمجة تطبيقات الشبكات العصبونية

توفّر واجهة برمجة التطبيقات Neral Networks API عمليات حسابية واستنتاجية مسرَّعة عن أُطر عمل تعلُّم الآلة على الجهاز مثل TensorFlow Lite، وهي مكتبة تعلُّم الآلة من Google على منصّات متعدّدة للأجهزة الجوّالة، بالإضافة إلى Caffe2 وغير ذلك. يمكنك الانتقال إلى مستودع برنامج مفتوح المصدر لبرنامج TensorFlow Lite للاطّلاع على عمليات التنزيل والمستندات. يعمل TensorFlow Lite مع واجهة برمجة التطبيقات Neral Networks من أجل تشغيل نماذج MobileNets وInception v3 و الرد السريع بكفاءة على جهازك الجوّال.

تحديثات إطار عمل الملء التلقائي

يوفّر Android 8.1 (مستوى واجهة برمجة التطبيقات 27) العديد من التحسينات على إطار عمل الملء التلقائي الذي يمكنك دمجه في تطبيقاتك.

تشمل الفئة BaseAdapter الآن الطريقة setAutofillOptions() التي تتيح لك تقديم تمثيلات سلسلة للقيم في المعدِّل. ويفيد ذلك في عناصر تحكم التثبيت التي تنشئ القيم ديناميكيًا في المحوّلات. على سبيل المثال، يمكنك استخدام الطريقة setAutofillOptions() لتقديم سلسلة تمثيلية لقائمة السنوات التي يمكن للمستخدمين اختيارها كجزء من تاريخ انتهاء صلاحية بطاقة الائتمان. يمكن لخدمات الملء التلقائي استخدام تمثيل السلسلة لملء طرق العرض التي تتطلب البيانات بشكل مناسب.

بالإضافة إلى ذلك، تتضمّن الفئة AutofillManager طريقة notifyViewVisibilityChanged(View, int, boolean) التي يمكنك طلبها لإعلام إطار العمل بالتغييرات في مستوى ظهور الملف الشخصي في بنية افتراضية. هناك أيضًا عبء زائد على الطريقة للهياكل غير الافتراضية. مع ذلك، لا تتطلّب منك البُنى غير الافتراضية عادةً إبلاغ إطار العمل صراحةً لأنّ هذه الطريقة تستدعي فئة View.

يمنح نظام Android 8.1 أيضًا "خدمات الملء التلقائي" المزيد من القدرة على تخصيص تكلفة حفظ واجهة المستخدم من خلال إتاحة استخدام CustomDescription and Validator في SaveInfo.

الأوصاف المخصصة مفيدة لمساعدة خدمة الملء التلقائي في توضيح ما يتم حفظه؛ على سبيل المثال، عندما تحتوي الشاشة على بطاقة ائتمان، يمكن أن تعرض شعار بنك بطاقة الائتمان، وآخر أربعة أرقام من رقم بطاقة الائتمان، ورقم انتهاء صلاحيتها. لمعرفة المزيد من المعلومات، يمكنك الاطّلاع على الصف CustomDescription.

Validator يتم استخدام الكائنات لتجنب عرض واجهة المستخدم المحفوظة بالملء التلقائي عندما لا يكون شرط "أداة التحقّق" مستوفيًا. لمزيد من المعلومات، يُرجى الاطّلاع على فئة التحقّق من الصحة مع فئتها الفرعية LuhnChecksumتقيator وRegexتقيator.

الإشعارات

يتضمن Android 8.1 التغييرات التالية على الإشعارات:

  • يمكن للتطبيقات الآن إصدار تنبيه صوتي للتنبيه مرة واحدة فقط في الثانية. ولا تتم إضافة أصوات التنبيهات التي تتجاوز هذا المعدّل إلى قائمة الانتظار ويتم فقدانها. لا يؤثر هذا التغيير في جوانب أخرى من سلوك الإشعارات ولا تزال رسائل الإشعارات يتم نشرها على النحو المتوقّع.
  • لا يتوافق السمتان NotificationListenerService وConditionProviderService مع الأجهزة التي تعمل بذاكرة وصول عشوائي (RAM) منخفضة وتعمل بنظام التشغيل Android والتي تعرض الخطأ "true" عند طلب "ActivityManager.isLowRamDevice()".

تحديث EditText

بدايةً من المستوى 27 من واجهة برمجة التطبيقات، تعرض الطريقة EditText.getText() خطأ Editable، وقد كانت تعرض في السابق CharSequence. هذا التغيير متوافق مع الإصدارات السابقة، حيث ينفّذ Editable CharSequence.

توفّر واجهة Editable وظائف إضافية قيّمة. على سبيل المثال، بما أنّ Editable ينفّذ أيضًا واجهة Spannable، يمكنك تطبيق الترميز على المحتوى ضمن مثيل EditText.

إجراءات "التصفّح الآمن الآلي"

باستخدام تنفيذ WebView لواجهة برمجة تطبيقات التصفح الآمن، يمكن لتطبيقك رصد محاولات WebView الانتقال إلى عنوان URL صنّفته Google كتهديد معروف. تعرض السمة WebView تلقائيًا إعلانًا بينيًا يحذّر المستخدمين من التهديد المعروف. تتيح هذه الشاشة للمستخدمين خيار تحميل عنوان URL على أي حال أو العودة إلى صفحة سابقة آمنة.

في Android 8.1، يمكنك تحديد طريقة استجابة تطبيقك لتهديد معروف:

  • يمكنك التحكّم في ما إذا كان تطبيقك يُبلغ عن التهديدات المعروفة للتصفّح الآمن.
  • يمكنك ضبط تطبيقك لتنفيذ إجراء محدّد تلقائيًا، مثل الرجوع إلى وضع الأمان، في كل مرة يصادف فيها عنوان URL تصنِّفه ميزة "التصفّح الآمن" كتهديد معروف.

ملاحظة: للحصول على أفضل حماية من التهديدات المعروفة، انتظِر إلى أن يتم إعداد ميزة "التصفّح الآمن" قبل تفعيل طريقة 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 ميغابايت، أي أكبر بكثير من الذي تحتاجه لصورة مصغّرة.

واجهة برمجة التطبيقات للذاكرة المشتركة

يقدم Android 8.1 (المستوى 27 من واجهة برمجة التطبيقات) واجهة برمجة تطبيقات جديدة في SharedMemory. يتيح لك هذا الصف إنشاء مثيل SharedMemory وربطه وإدارته بهوية مخفية. يمكنك ضبط ميزة حماية الذاكرة على عنصر SharedMemory للقراءة و/أو الكتابة، وبما أنّ الكائن SharedMemory هو Parcelable، يمكنك بسهولة تمريره إلى عملية أخرى من خلال لغة تعريف واجهة برمجة التطبيقات (AIDL).

تتفاعل واجهة برمجة التطبيقات SharedMemory مع مرفق ASharedMemory في NDK. يتيح ASharedMemory الوصول إلى واصف الملف، والذي يمكن ربطه للقراءة والكتابة. وهي طريقة رائعة لمشاركة كميات كبيرة من البيانات بين التطبيقات أو بين عمليات متعددة داخل تطبيق واحد.

واجهة برمجة تطبيقات خلفيات الألوان

يسمح Android 8.1 (المستوى 27 من واجهة برمجة التطبيقات) للخلفية المتحركة بتقديم معلومات اللون إلى واجهة مستخدم النظام. يمكنك إجراء ذلك من خلال إنشاء كائن WallpaperColors من صورة نقطية أو ملف قابل للرسم أو باستخدام ثلاثة ألوان يتم اختيارها يدويًا. يمكنك أيضًا استرداد معلومات اللون هذه.

لإنشاء كائن WallpaperColors، يمكنك تنفيذ أحد الإجراءَين التاليَين:

  • لإنشاء كائن WallpaperColors باستخدام ثلاثة ألوان، أنشئ مثيلاً للفئة WallpaperColors بتمرير اللون الأساسي والثانوي والثالث. يجب ألا يكون اللون الأساسي فارغًا.
  • لإنشاء كائن WallpaperColors من صورة نقطية، يمكنك استدعاء الطريقة fromBitmap() من خلال تمرير مصدر الصورة النقطية كمعلمة.
  • لإنشاء كائن WallpaperColors من عنصر قابل للرسم، عليك استدعاء الطريقة fromDrawable() من خلال ضبط المصدر القابل للرسم كمَعلمة.

لاسترداد تفاصيل اللون الأساسي أو الثانوي أو الثالث من الخلفية، قم باستدعاء الطرق التالية:

  • تعرض getPrimaryColor() اللون الأكثر تمثيلاً من الناحية المرئية للخلفية.
  • يعرض getSecondaryColor() اللون الثاني الأكثر بروزًا للخلفية.
  • getTertiaryColor() يعرض اللون الثالث الأكثر بروزًا للخلفية.

لإبلاغ النظام بأي تغييرات مهمة في ألوان الخلفية المتحركة، اتصل بطريقة notifyColorsChanged(). تؤدي هذه الطريقة إلى تشغيل حدث دورة حياة onComputeColors() حيث تتوفّر لك فرصة لتوفير كائن WallpaperColors جديد.

لإضافة أداة معالجة لتغيُّرات الألوان، يمكنك استدعاء طريقة 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). ونظرًا لأن مطوّري البرامج يصلون أحيانًا إلى هذه البيانات بشكل انعكاسي، فقد تم ترك الحِزم في مكانها لإتاحة الاستخدام السابق، إلا أنّ بعض التفاصيل قد تغيّرت. على سبيل المثال، كانت المقابس في السابق من النوع OpenSSLSocketImpl، لكنها الآن من النوع ConscryptFileDescriptorSocket أو ConscryptEngineSocket، وكلاهما يمتدّ OpenSSLSocketImpl.
  • كانت طُرق SSLSession المستخدمة لعرض IllegalArgumentException عند تمرير مرجع فارغ، يتم الآن طرح NullPointerException.
  • لم يعُد RSA KeyFactory تسمح بإنشاء مفاتيح من مصفوفات بايت أكبر من المفتاح المشفّر. وتؤدي الاستدعاءات إلى generatePrivate() و generatePublic() اللتين توفران KeySpec حيث لا تملأ بنية المفتاح المخزن المؤقت بأكمله إلى InvalidKeySpecException.
  • عندما تتم مقاطعة قراءة المقبس بسبب إغلاق المقبس، يستخدم Conscrypt لعرض -1 من القراءة. عند القراءة، يتم طرح SocketException.
  • تم تغيير مجموعة شهادات CA الجذر، مع إزالة عدد كبير من الشهادات القديمة في الغالب وإزالة شهادات الجذر لـ WoSign وStartCom. لمزيد من المعلومات حول هذا القرار، يُرجى الاطّلاع على مشاركة مدونة أمان Google بعنوان الإزالة النهائية للثقة في شهادتَي WoSign وStartCom.