ميزات 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). تذكر أن جعل تطبيقك خفيفًا وأكثر كفاءة يعود بالفائدة على جمهورك بالكامل، بغض النظر عن الجهاز.

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

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

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

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

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

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

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

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

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

الإشعارات

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

  • بإمكان التطبيقات الآن إصدار تنبيه صوتي للتنبيه مرة واحدة في الثانية فقط. ولا يتم وضع أصوات التنبيهات التي تتجاوز هذا المعدّل في قائمة الانتظار ويتم فقدانها. ولا يؤثّر هذا التغيير في جوانب أخرى من سلوك الإشعارات، ولا تزال رسائل الإشعارات يتم نشرها على النحو المتوقّع.
  • لا يمكن استخدام NotificationListenerService وConditionProviderService على الأجهزة ذات ذاكرة الوصول العشوائي المنخفضة التي تعمل بنظام التشغيل 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 قابل للأجزاء، يمكنك تمريره بسهولة إلى عملية أخرى من خلال AIDL.

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

واجهة برمجة تطبيقات BackgroundColors

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