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

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

Android Oreo (إصدار Go)

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

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

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

Neural Networks API

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

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

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

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

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

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

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

يتم استخدام كائنات Validator لتجنُّب عرض واجهة مستخدم حفظ الملء التلقائي عندما لا يتم استيفاء شرط Validator. لمزيد من المعلومات، اطّلِع على فئة Validator وفئاتها الفرعية، LuhnChecksumValidator وRegexValidator.

الإشعارات

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

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

Shared memory API

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

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

WallpaperColors API

يتيح الإصدار 8.1 من نظام التشغيل Android (المستوى 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‏ (Google Security Blog) بعنوان الإزالة النهائية للثقة في شهادات WoSign وStartCom.