תכונות וממשקי API של Android 8.1

ב-Android 8.1 (רמת API‏ 27) יש מגוון תכונות ויכולות חדשות למשתמשים ולמפתחים. במסמך הזה נסקור את החידושים למפתחים.

(Go edition)‏ Android Oreo‏

Android Go היא היוזמה שלנו לאופטימיזציה של חוויית השימוש ב-Android מיליארדי אנשים נכנסים לאינטרנט בכל העולם. החל מגרסה 8.1 של Android, אנחנו הופכים את Android לפלטפורמה מעולה למכשירים ברמה בסיסית. התכונות בהגדרה של Android Oreo (מהדורת Go) כוללות:

  • אופטימיזציות של זיכרון שיפור השימוש בזיכרון בפלטפורמה כדי לוודא שהאפליקציות יפעלו ביעילות במכשירים עם זיכרון RAM בנפח 1GB או פחות.
  • אפשרויות טירגוט גמישות קבועים חדשים של מאפייני חומרה שמאפשרים לכם לטרגט את הפצת האפליקציות שלכם למכשירים רגילים או למכשירים עם נפח זיכרון RAM נמוך דרך Google Play.
  • Google Play. כל האפליקציות יהיו זמינות במכשירים עם מערכת ההפעלה Android Oreo (מהדורת Go), אבל ב-Google Play יוצגו אפליקציות שהמפתחים ביצעו בהן אופטימיזציה ספציפית כדי לספק חוויה מעולה למיליארד אנשים, בהתאם להנחיות ליצירת אפליקציות למיליארד אנשים.

עדכנו את ההנחיות בנושא פיתוח אפליקציות למיליארד משתמשים, והוספנו הנחיות נוספות לאופטימיזציה של האפליקציה למכשירים עם Android Oreo (מהדורת Go). רוב המפתחים יכולים לבצע אופטימיזציה של קובץ ה-APK הקיים או להשתמש בתכונה 'מספר חבילות APK' של Google Play כדי לטרגט גרסה של קובץ ה-APK למכשירים עם נפח זיכרון RAM נמוך. זו הדרך הטובה ביותר להתכונן למכשירים עם Android Oreo (מהדורת Go). חשוב לזכור שהפקודה אפליקציה קלים ויעילים יותר שיועילו לכל הקהל, בלי קשר למכשיר.

ממשק API של רשתות נוירונים

‏Neural Networks API מספק חישוב ומסקנה מואצים למסגרות של למידת מכונה במכשיר, כמו TensorFlow Lite – ספריית ה-ML של Google לפלטפורמות שונות לנייד – וגם Caffe2 ועוד. במאגר הקוד הפתוח של TensorFlow Lite תוכלו למצוא הורדות ומסמכים. TensorFlow Lite עובד עם ה-API של רשתות הנוירונים כדי להריץ מודלים כמו MobileNets, Inception v3, ו- התכונה 'תשובה מהירה' במכשיר הנייד.

עדכונים של framework למילוי אוטומטי

ב-Android 8.1 (רמת API 27) יש כמה שיפורים במילוי האוטומטי מסגרת שאפשר לשלב באפליקציות.

BaseAdapter הכיתה כוללת עכשיו את setAutofillOptions() , שמאפשרת לספק ייצוגי מחרוזות של הערכים עם מתאם בלבד. האפשרות הזו שימושית לבקרים מסוג spinner שיוצרים את הערכים באופן דינמי במודולים המתאימים. לדוגמה, אפשר להשתמש בשיטה setAutofillOptions() כדי לספק מחרוזת ייצוג של רשימת השנים שהמשתמשים יכולים לבחור כחלק תאריך התפוגה של כרטיס האשראי. שירותי המילוי האוטומטי יכולים להשתמש בייצוג מחרוזות כדי למלא כראוי את התצוגות שבהן נדרשים הנתונים.

בנוסף, הכיתה AutofillManager כוללת את השיטה notifyViewVisibilityChanged(View, int, boolean), שאפשר להפעיל כדי להודיע למסגרת על שינויים בחשיפה של תצוגה במבנה וירטואלי. יש גם עומס יתר על השיטה למבנים לא וירטואליים. עם זאת, בדרך כלל לא צריך להודיע באופן מפורש למסגרת על מבנים לא וירטואליים, כי השיטה כבר נקראת על ידי הכיתה View.

ב-Android 8.1 גם יש לשירותי המילוי האוטומטי יותר אפשרות להתאים אישית את ממשק המשתמש לשמירה יותר משתלם על ידי הוספת תמיכה ב-CustomDescription and Validator בתוך SaveInfo.

תיאורים מותאמים אישית עוזרים לשירות המילוי האוטומטי להבין מה נשמר. לדוגמה, כשהמסך מכיל כרטיס אשראי, יכול להיות שיוצג בו הלוגו של הבנק שמנפיק את כרטיס האשראי, ארבע הספרות האחרונות של מספר כרטיס האשראי ומספר התפוגה שלו. מידע נוסף זמין ב CustomDescription בכיתה.

Validator אובייקטים משמשים למניעת הצגה של ממשק המשתמש לשמירה במילוי אוטומטי כשכלי התיקוף לא מתקיים. מידע נוסף זמין ב המחלקה לאימות יחד עם מחלקות המשנה שלה, LuhnChecksumValidator ו-RegexValidator.

התראות

בגרסה 8.1 של Android יש את השינויים הבאים בהתראות:

  • עכשיו אפליקציות יכולות להשמיע צליל התראה רק פעם בשנייה. צלילי התראה שחורגים מהטווח השערים האלה לא נוספים לתור ויאבדו. השינוי הזה לא משפיע על היבטים אחרים של ההתראות הודעות ההתנהגות וההתראות עדיין יפורסמו כצפוי.
  • אין תמיכה ב-NotificationListenerService וב-ConditionProviderService במכשירי Android עם נפח RAM נמוך, שמחזירים את הערך true כשקוראים ל-ActivityManager.isLowRamDevice().

עדכון של EditText

החל מרמת API 27, ה-method EditText.getText() מחזירה Editable; בעבר הוא החזיר CharSequence. השינוי הזה הוא תואם לאחור, כפי ש-Editable מיישם CharSequence.

הממשק של Editable מספק ערך נוסף החדשה. לדוגמה, כי גם Editable יכול להחיל את הממשק Spannable, אפשר להחיל תגי עיצוב תוכן במופע של EditText.

פעולות פרוגרמטיות של גלישה בטוחה

באמצעות הטמעת WebView של Safe Browsing API, האפליקציה יכולה לזהות מתי מופע של WebView מנסה לנווט לכתובת URL ש-Google סיווגה כאיום ידוע. כברירת מחדל, ב-WebView מוצגת מודעת מעברון שמזהירה את המשתמשים מפני האיום הידוע. במסך הזה, המשתמשים יכולים לטעון את כתובת ה-URL בכל זאת או לחזור לדף קודם שהוא בטוח.

ב-Android 8.1, ניתן להגדיר באופן פרוגרמטי איך האפליקציה מגיבה לאיום ידוע:

  • אתם יכולים לקבוע אם האפליקציה תדווח על איומים ידועים ל'גלישה בטוחה'.
  • אפשר להגדיר שהאפליקציה תבצע באופן אוטומטי פעולה מסוימת, כמו חוזרים לדף הבטוח – בכל פעם שהיא נתקלת בכתובת URL שגלישה בטוחה מסווג כאיום ידוע.

הערה: כדי לקבל הגנה אופטימלית מפני איומים מוכרים, יש להמתין עד שתפעיל את הגלישה הבטוחה לפני שתפעיל ה-method loadUrl() של אובייקט WebView.

בקטעי הקוד הבאים מוסבר איך להורות למופעים של WebView באפליקציה לחזור תמיד למצב בטוח אחרי שהם נתקלים באיום ידוע:

AndroidManifest.xml

<manifest>
    <application>
        ...
        <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                   android:valu>e=&qu<ot;true">;< /
    /a>pplication
/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(), שעלולה לבזבז זיכרון כי היא מחזירה קובץ bitmap באותה רזולוציה כמו של סרטון המקור. עבור לדוגמה, פריים מסרטון באיכות 4K יהיה מפת סיביות של 16MB, הרבה יותר גדולה ממך שיזדקקו לתמונה ממוזערת.

ממשק API לזיכרון משותף

ב-Android 8.1 (API ברמה 27) נוסף ממשק API חדש בשם SharedMemory. בעזרת הכיתה הזו אפשר ליצור, למפות ולנהל מכונה אנונימית של SharedMemory. אתם מגדירים את הגנת הזיכרון על SharedMemory לקריאה ו/או כתיבה, ומכיוון SharedMemory האובייקט ניתן ל-Parcelable, ואפשר להעביר אותו בקלות לתהליך אחר באמצעות AIDL.

ממשק ה-API של SharedMemory פועל בשילוב עם השירות ASharedMemory ב-NDK. ASharedMemory מעניק גישה למתואר קובץ, שאפשר למפות אותו לקריאה ולכתיבה. זה מעולה דרך לחלוק כמויות גדולות של נתונים בין אפליקציות או בין מספר תהליכים בתוך אפליקציה אחת.

ממשק API של BackgroundColors

ב-Android 8.1‏ (API ברמה 27) הטפט הדינמי יכול לספק מידע על צבעים לממשק המשתמש של המערכת. כדי לעשות זאת, יוצרים אובייקט WallpaperColors מ-bitmap, מ-drawable או באמצעות שלושה צבעים שנבחרו באופן ידני. אפשר גם לאחזר את פרטי הצבעים האלה.

כדי ליצור WallpaperColors אובייקט, מבצעים אחת מהפעולות הבאות:

  • כדי ליצור אובייקט WallpaperColors באמצעות שלושה צבעים, יוצרים מופע של הכיתה WallpaperColors על ידי העברת הצבע הראשי, הצבע המשני והצבע השלישי. המשחק הראשי הצבע לא יכול להיות ריק.
  • כדי ליצור אובייקט WallpaperColors מ-bitmap, צריך לבצע קריאה לשיטה fromBitmap() ולהעביר את מקור ה-bitmap כפרמטר.
  • כדי ליצור WallpaperColors של אובייקט שניתן להזזה, קוראים לפונקציה fromDrawable() על ידי העברת המקור שניתן להזזה כפרמטר.

כדי לאחזר את פרטי הצבע הראשי, הצבע המשני או הצבע השלישי מהטפט, צריך להפעיל את השיטות הבאות:

כדי להודיע למערכת על שינויים משמעותיים בצבע של הטפט החי, צריך להפעיל את השיטה notifyColorsChanged(). השיטה הזו מפעילה אירוע מחזור חיים של onComputeColors(), שבו יש לכם הזדמנות לספק אובייקט WallpaperColors חדש.

כדי להוסיף אוזן לשינויי צבע, אפשר לקרוא ל-method addOnColorsChangedListener(). אפשר קוראים גם ל-method getWallpaperColors() כדי לאחזר את הצבעים הראשיים של הטפט.

עדכונים של טביעת אצבע

בכיתה FingerprintManager יש את קודי השגיאה הבאים:

  • FINGERPRINT_ERROR_LOCKOUT_PERMANENT – המשתמש ניסה יותר מדי פעמים לבטל את הנעילה של המכשיר באמצעות קורא טביעות האצבע.
  • FINGERPRINT_ERROR_VENDOR – אירעה שגיאה בקורא טביעות האצבע ספציפי לספק.

עדכוני קריפטוגרפיה

בוצעו כמה שינויים בתחום הקריפטוגרפיה ב-Android 8.1:

  • הוחלו אלגוריתמים חדשים ב-Conscrypt. הקריפטו עדיף להשתמש בהטמעה על פני טירת Bouncy הקיימת. יישום בפועל. בין האלגוריתמים החדשים:
    • 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. מידע נוסף על ההחלטה הזו זמין במאמר פוסט בבלוג האבטחה, סופית הסרת האמון באישורי WoSign ו-StartCom.