ממשקי API של Android 4.3

רמת ה-API: 18

Android 4.3 (JELLY_BEAN_MR2) הוא עדכון לגרסה של Jelly Bean שמציע תכונות חדשות למשתמשים ולאפליקציה מפתחים. במסמך הזה מתוארות המבוא ממשקי API חדשים.

כמפתחי אפליקציות, עליכם להוריד את תמונת המערכת של Android 4.3 ופלטפורמת ה-SDK מ-SDK Manager. בהקדם האפשרי. אם אין לכם מכשיר עם Android 4.3 שבו תוכלו לבדוק את האפליקציה, תוכלו להשתמש בתמונת המערכת של Android 4.3 כדי לבדוק את האפליקציה במכונה וירטואלית ל-Android. לאחר מכן בניית האפליקציות שלך מול פלטפורמת Android 4.3 כדי להתחיל להשתמש ממשקי ה-API העדכניים ביותר.

עדכון רמת ה-API המטורגטת

כדי לבצע אופטימיזציה טובה יותר של האפליקציה למכשירים שבהם פועלת מערכת Android 4.3, צריך להגדיר את targetSdkVersion לערך "18", להתקין אותו בתמונת מערכת של Android 4.3, לבדוק אותו ואז לפרסם עדכון עם השינוי הזה.

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

בספריית התמיכה של Android אפשר למצוא גם ממשקי API שונים, ואפשר להטמיע אותם חדשות בגרסאות ישנות של הפלטפורמה.

מידע נוסף על אופן הפעולה של רמות ה-API זמין במאמר מה זה API? רמה?

שינויים חשובים בהתנהגות

אם פרסמת בעבר אפליקציה ל-Android, ייתכן שהאפליקציה יושפעו משינויים ב-Android 4.3.

אם האפליקציה משתמשת באובייקטים מרומזים של כוונות...

יכול להיות שהאפליקציה לא תפעל בצורה תקינה בסביבת פרופיל מוגבלת.

יכול להיות שמשתמשים בסביבה של פרופיל מוגבל לא כל האפליקציות הרגילות ל-Android זמינות. לדוגמה, פרופיל מוגבל יכול לכלול דפדפן האינטרנט ואפליקציית המצלמה מושבתים. לכן, אסור לאפליקציה להניח אילו אפליקציות זמינות, כי אם תפעילו את startActivity() בלי לוודא אם יש אפליקציה זמינה לטיפול ב-Intent, האפליקציה עשויה לקרוס בפרופיל מוגבל.

כשמשתמשים בכוונה משתמעת, תמיד צריך לוודא שיש אפליקציה שזמינה לטיפול בכוונה באמצעות קריאה ל-resolveActivity() או ל-queryIntentActivities(). לדוגמה:

Kotlin

val intent = Intent(Intent.ACTION_SEND)
...
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show()
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);
...
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show();
}

אם האפליקציה שלכם תלויה בחשבונות...

יכול להיות שהאפליקציה תתנהג בצורה לא תקינה בסביבה של פרופיל מוגבל.

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

אם ברצונך למנוע לחלוטין שימוש באפליקציה שלך בפרופילים מוגבלים מפני האפליקציה תלויה בפרטי החשבון שמכילים מידע רגיש. יש לציין את המאפיין android:requiredAccountType במניפסט <application> לרכיב מסוים.

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

אם האפליקציה שלכם משתמשת ב-VideoView…

יכול להיות שהסרטון יוצג בגודל קטן יותר ב-Android 4.3.

בגרסאות קודמות של Android, הווידג'ט VideoView חישב באופן שגוי את הערך "wrap_content" עבור layout_height ו-layout_width כזהה ל-"match_parent". לכן, למרות שהגודל או הרוחב של "wrap_content" מספקים בעבר את פריסת הסרטון הרצויה, הדבר עלול להוביל לסרטון קטן בהרבה ב-Android 4.3 ואילך. כדי לפתור את הבעיה, מחליפים את הערך "wrap_content" בערך "match_parent" ומוודאים שהסרטון מופיע כצפוי ב-Android 4.3 וגם בגרסאות ישנות יותר.

פרופילים מוגבלים

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

ממשק המשתמש שמאפשר למשתמשים לשלוט בהגבלות שיצרתם מנוהל על ידי אפליקציית ההגדרות של המערכת. כדי שהגדרות ההגבלה של האפליקציה יוצגו למשתמשים: עליך להצהיר על ההגבלות שהאפליקציה שלך מספקת על ידי יצירת BroadcastReceiver שמקבל את ה-Intent ACTION_GET_RESTRICTION_ENTRIES. המערכת מפעילה את הכוונה הזו כדי לשלוח שאילתה את כל האפליקציות בהתאם להגבלות הזמינות, ואז יוצר את ממשק המשתמש כדי לאפשר למשתמש הראשי לנהל את ההגבלות לכל פרופיל מוגבל.

בשיטה onReceive() של שלך, BroadcastReceiver, עליך ליצור RestrictionEntry לכל הגבלה שהאפליקציה שלך מספקת. כל RestrictionEntry מגדיר שם, תיאור של הגבלה ו סוגי הנתונים הבאים:

  • TYPE_BOOLEAN עבור הגבלה שהיא נכון או לא נכון.
  • TYPE_CHOICE עבור הגבלה שחלה עליה אפשרויות מרובות שאינן יכולות להתקיים בו-זמנית (בחירות של לחצן בחירה).
  • TYPE_MULTI_SELECT עבור הגבלה עם כמה אפשרויות שאינן מחייבות בחירה אחת בלבד (אפשרויות בתיבות סימון).

לאחר מכן צריך להזין את כל האובייקטים של RestrictionEntry ב-ArrayList ולהוסיף אותם לתוצאה של מקלט השידור כערך של עוד EXTRA_RESTRICTIONS_LIST.

המערכת יוצרת את ממשק המשתמש עבור הגבלות האפליקציה באפליקציית ההגדרות, ושומרת כל הגבלה באמצעות המפתח הייחודי שסיפקתם לכל RestrictionEntry לאובייקט. כשהמשתמש פותח את האפליקציה, אפשר לבצע שאילתה לגבי הגבלות נוכחיות באמצעות קריאה ל-getApplicationRestrictions(). הפונקציה מחזירה Bundle שמכיל את צמדי המפתח/ערך של כל הגבלה שהגדרתם באמצעות אובייקטי RestrictionEntry.

אם רוצים לספק הגבלות ספציפיות יותר שלא ניתן לטפל בהן באמצעות ערך בוליאני, וערכי שאלות אמריקאיות, אז תוכלו ליצור פעילות שבה המשתמש יכול לציין ולאפשר למשתמשים לפתוח את הפעילות הזו דרך הגדרות ההגבלה. בנגן השידור, צריך לכלול את הנתון הנוסף EXTRA_RESTRICTIONS_INTENT בתוצאה Bundle. האפשרות הנוספת הזו חייבת לציין Intent שמציין את המחלקה Activity שרוצים להפעיל (משתמשים ב-method‏ putParcelable() כדי להעביר את EXTRA_RESTRICTIONS_INTENT עם ה-intent). כשהמשתמש הראשי מזין את הפעילות שלכם כדי להגדיר הגבלות בהתאמה אישית, לאחר מכן, הפעילות חייבת להחזיר תוצאה שמכילה את ערכי ההגבלה בתוספת באמצעות אחד מקש EXTRA_RESTRICTIONS_LIST או EXTRA_RESTRICTIONS_BUNDLE, בהתאם למה שמציינים RestrictionEntry אובייקטים או צמדי מפתח/ערך, בהתאמה.

תמיכה בחשבונות בפרופיל מוגבל

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

  • מתן גישה לחשבונות של הבעלים מפרופיל מוגבל

    כדי לקבל גישה לחשבון מפרופיל מוגבל, צריך להוסיף את המאפיין android:restrictedAccountType לתג <application>:

    <application ...
        android:restrictedAccountType="com.example.account.type" >

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

  • להשבית פונקציונליות מסוימת כשאי אפשר לשנות חשבונות.

    אם אתם רוצים להשתמש בחשבונות, אבל אתם לא דורשים אותם בחשבון הראשי של האפליקציה. פונקציונליות שמאפשרת לבדוק את זמינות החשבון ולהשבית תכונות כשהן לא זמינות. קודם צריך לבדוק אם יש חשבון קיים זמין. אם לא, יש אפשרות ליצור חשבון חדש על ידי קריאה אל getUserRestrictions() ולבדוק את תוספת DISALLOW_MODIFY_ACCOUNTS בתוצאה. אם הוא true, עליכם להשבית כל פונקציונליות של האפליקציה שדורשת גישה לחשבונות. לדוגמה:

    Kotlin

    val um = context.getSystemService(Context.USER_SERVICE) as UserManager
    val restrictions: Bundle = um.userRestrictions
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }

    Java

    UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    Bundle restrictions = um.getUserRestrictions();
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }

    הערה: במקרה הזה, לא להצהיר על מאפיינים חדשים בקובץ המניפסט.

  • השבתת האפליקציה אם אין גישה לחשבונות פרטיים

    אם חשוב במקום זאת שהאפליקציה לא תהיה זמינה לפרופילים מוגבלים, האפליקציה תלויה במידע אישי רגיש בחשבון (ובגלל שפרופילים מוגבלים כרגע אין אפשרות להוסיף חשבונות חדשים), להוסיף המאפיין android:requiredAccountType לתג <application>:

    <application ...
        android:requiredAccountType="com.example.account.type" >

    לדוגמה, אפליקציית Gmail משתמשת במאפיין הזה כדי להשבית את עצמה בפרופילים מוגבלים, כי כתובת האימייל האישית של הבעלים לא אמורה להיות זמינה לפרופילים מוגבלים.

  • תקשורת אלחוטית וקישוריות

    Bluetooth עם צריכת אנרגיה נמוכה (Smart Ready)

    ב-Android יש עכשיו תמיכה ב-Bluetooth עם צריכת אנרגיה נמוכה (LE) באמצעות ממשקי API חדשים ב-android.bluetooth. בעזרת ממשקי ה-API החדשים, אפשר ליצור אפליקציות ל-Android שמתקשרות עם ציוד היקפי עם Bluetooth אנרגיה נמוכה, כמו מוניטורים של קצב הלב ושעוני הליכה.

    כי Bluetooth LE היא תכונת חומרה שלא זמינה בכל המכשירים מכשירים מבוססי Android, חובה להצהיר בקובץ המניפסט על <uses-feature> רכיב עבור "android.hardware.bluetooth_le":

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

    אם אתם כבר מכירים את ממשקי ה-API של Bluetooth Classic ב-Android, שימו לב שיש כמה הבדלים בשימוש בממשקי ה-API של Bluetooth LE. הדבר החשוב ביותר הוא שיש עכשיו כיתת BluetoothManager שאפשר להשתמש בה לביצוע פעולות ברמה גבוהה כמו רכישה של BluetoothAdapter, קבלת רשימה של מכשירים, ובדיקת המצב של המכשיר. לדוגמה, כך מקבלים עכשיו את הערך של BluetoothAdapter:

    Kotlin

    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    bluetoothAdapter = bluetoothManager.adapter

    Java

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();

    כדי למצוא ציוד היקפי עם Bluetooth LE, צריך להפעיל את startLeScan() ב-BluetoothAdapter ולהעביר אותו של הממשק BluetoothAdapter.LeScanCallback. כשמתאם ה-Bluetooth מזהה ציוד היקפי של Bluetooth LE, ההטמעה של BluetoothAdapter.LeScanCallback מקבלת קריאה לשיטה onLeScan(). השיטה הזו מספקת אובייקט BluetoothDevice שמייצג את המכשיר שזוהה, את ערך ה-RSSI של המכשיר ואת מערך הבייטים שמכיל את רשומת הפרסום של המכשיר.

    אם רוצים לסרוק רק סוגים ספציפיים של ציוד היקפי, אפשר במקום זאת להפעיל את startLeScan() ולכלול מערך של אובייקטים מסוג UUID שמציינים את שירותי ה-GATT שהאפליקציה תומכת בהם.

    הערה: אפשר לסרוק רק מכשירי Bluetooth LE או מכשירי Bluetooth רגילים באמצעות ממשקי API קודמים. אי אפשר לחפש בו-זמנית מכשירי Bluetooth LE ומכשירי Bluetooth רגילים.

    כדי להתחבר להתקן היקפי של Bluetooth LE, צריך להפעיל את connectGatt() באובייקט BluetoothDevice המתאים, ולהעביר לו הטמעה של BluetoothGattCallback. היישום של BluetoothGattCallback מקבל קריאה חוזרת לגבי הקישוריות עם המכשיר ואירועים אחרים. במהלך הקריאה החוזרת (callback) של onConnectionStateChange() תוכלו להתחיל לתקשר עם המכשיר, אם השיטה מעבירה את הערך STATE_CONNECTED כמצב החדש.

    כדי לגשת לתכונות Bluetooth במכשיר, האפליקציה צריכה לבקש הרשאות מסוימות של משתמשי Bluetooth. מידע נוסף זמין במדריך ה-API של Bluetooth Low Energy.

    מצב חיפוש נקודות Wi-Fi בלבד

    כשמערכת Android מנסה לזהות את המיקום של המשתמש, היא עשויה להשתמש ב-Wi-Fi כדי לקבוע את המיקום על ידי סריקת נקודות גישה בקרבת מקום. אבל בדרך כלל המשתמשים משביתים את ה-Wi-Fi לחסוך בצריכת הסוללה, וכתוצאה מכך יתקבלו נתוני מיקום פחות מדויקים. מערכת Android כוללת עכשיו מצב סריקה בלבד שמאפשר ל-Wi-Fi של המכשיר לסרוק נקודות גישה כדי לקבל את המיקום בלי להתחבר לנקודת גישה, וכך לצמצם באופן משמעותי את השימוש בסוללה.

    אם אתם רוצים לקבל את המיקום של המשתמש אבל ה-Wi-Fi כבוי כרגע, תוכלו לבקש מהמשתמש להפעיל את מצב הסריקה בלבד של Wi-Fi. לשם כך, צריך להפעיל את startActivity() עם הפעולה ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE.

    הגדרת Wi-Fi

    ממשקי ה-API החדשים של WifiEnterpriseConfig מאפשרים לשירותים שמיועדים לארגונים להגדיר תצורה של Wi-Fi במכשירים מנוהלים באופן אוטומטי.

    תגובה מהירה לשיחות נכנסות

    החל מ-Android 4.0, התכונה נקראת 'תגובה מהירה' מאפשרת למשתמשים להשיב שיחות באמצעות הודעת טקסט מיידית בלי לענות לשיחה או לבטל את הנעילה של המכשיר. עד עכשיו, ההודעות המהירות האלה תמיד טופלו על ידי אפליקציית Messaging שמוגדרת כברירת מחדל. עכשיו כל אפליקציה יכולה להצהיר על היכולת שלה לטפל בהודעות האלה על ידי יצירת Service עם מסנן אינטנט ל-ACTION_RESPOND_VIA_MESSAGE.

    כשהמשתמש משיב לשיחה נכנסת בתשובה מהירה, אפליקציית הטלפון שולחת את הכוונה ACTION_RESPOND_VIA_MESSAGE עם URI שמתאר את הנמען (המבצע של הקריאה) ואת הנתון הנוסף EXTRA_TEXT עם ההודעה שהמשתמש רוצה לשלוח. כשהשירות מקבל את הכוונה, הוא צריך לספק ההודעה ולהפסיק את עצמה מיד (לא אמורה להיות פעילות באפליקציה).

    כדי לקבל את הכוונה הזו, עליך להצהיר על ההרשאה SEND_RESPOND_VIA_MESSAGE.

    מולטימדיה

    שיפורים של Mediaחלץ' וב-MediaCodec

    עכשיו קל יותר לכתוב ב-Android מודעה דינמית סטרימינג בנגני HTTP (DASH) בהתאם לתקן ISO/IEC 23009-1, באמצעות ממשקי API קיימים ב-MediaCodec וב-MediaExtractor. המסגרת שבבסיס ממשקי ה-API האלה עודכנה והיא תומכת ניתוח של קובצי MP4 מקוטעים, אבל האפליקציה שלך עדיין אחראית לניתוח המטא-נתונים של MPD ומעבירים את כל השידורים החיים אל MediaExtractor.

    אם רוצים להשתמש ב-DASH עם תוכן מוצפן, חשוב לשים לב שהשיטה getSampleCryptoInfo() מחזירה את המטא-נתונים MediaCodec.CryptoInfo שמתארים את המבנה של כל דגימת מדיה מוצפנת. כמו כן, השיטה getPsshInfo() נוספה אל MediaExtractor כדי שתוכלו לגשת למטא-נתונים של PSSH בשביל מדיה ב-DASH. השיטה הזו מחזירה מפה של אובייקטים מסוג UUID לבייטים, כאשר UUID מציין את סכמת הקריפטו והבייטים הם הנתונים הספציפיים לסכמה הזו.

    DRM למדיה

    הכיתה החדשה MediaDrm מספקת פתרון מודולרי לניהול זכויות דיגיטלי (DRM) בתוכן המדיה שלכם, על ידי הפרדה בין הבעיות שקשורות ל-DRM לבין הפעלת המדיה. עבור הפרדת ה-API הזו מאפשרת להפעיל תוכן בהצפנת Widevine מבלי שיהיה צורך כדי להשתמש בפורמט המדיה של Widevine. פתרון DRM זה תומך גם ב-DASH Common Encryption כדי יכולים להשתמש במגוון סכמות DRM בתוכן הסטרימינג שלכם.

    אפשר להשתמש ב-MediaDrm כדי לקבל הודעות אטומות של בקשת מפתח ועיבוד הודעות לתגובת מפתח מהשרת עבור קבלת רישיונות והקצאה. האפליקציה שלכם אחראית לטיפול בתקשורת הרשת עם השרתים. הכיתה MediaDrm מספקת רק את היכולת ליצור ולעבד את ההודעות.

    ממשקי ה-API של MediaDrm מיועדים לשימוש בשילוב עם ממשקי API של MediaCodec שהושקו ב-Android 4.1 (רמת API 16), כולל MediaCodec לקידוד ופענוח של התוכן, MediaCrypto לטיפול בתוכן מוצפן ו-MediaExtractor לחילוץ והדמייה של התוכן.

    קודם צריך ליצור אובייקטים של MediaExtractor ו-MediaCodec. לאחר מכן תוכלו לגשת ל-UUID שמזהה את הסכימה של DRM, בדרך כלל מהמטא-נתונים בתוכן, ולהשתמש בו כדי ליצור מופע של אובייקט MediaDrm באמצעות ה-constructor שלו.

    קידוד וידאו מ-Surface

    ב-Android 4.1 (API ברמה 16) נוספה הכיתה MediaCodec לקידוד ולפענוח ברמה נמוכה של תוכן מדיה. בעת קידוד וידאו, נדרש עבור Android 4.1 את המדיה באמצעות מערך ByteBuffer, אבל ב-Android 4.3 אפשר עכשיו להשתמש ב-Surface כקלט למקודד. לדוגמה, כך אפשר לקודד קלט מקובץ וידאו קיים או באמצעות פריימים שנוצרו מ-OpenGL ES.

    כדי להשתמש ב-Surface כקלט למקודד, צריך קודם להפעיל את הפקודה configure() בשביל MediaCodec. אחר כך צריך להתקשר אל createInputSurface() כדי לקבל את ה-Surface שבו אפשר לשדר את המדיה.

    לדוגמה, אפשר להשתמש ב-Surface הנתון כחלון ל-OpenGL את ההקשר על ידי העברתו אל eglCreateWindowSurface(). ואז, בזמן עיבוד פני השטח, צריך לקרוא לפונקציה eglSwapBuffers() כדי להעביר את המסגרת אל MediaCodec.

    כדי להתחיל בקידוד, יש להפעיל את start() במכשיר MediaCodec. בסיום, צריך להתקשר אל signalEndOfInputStream() כדי לסיים את הקידוד, וקוראים לפונקציה release() Surface.

    ערבוב מדיה

    המחלקה החדשה של MediaMuxer מאפשרת ריבוב בין שידור אודיו אחד וזרם וידאו אחד. ממשקי ה-API האלה משמשים כמקבילה לכיתה MediaExtractor שנוספה ב-Android 4.2 לצורך ביטול המרובולקס (demuxing) של מדיה.

    פורמטים נתמכים של פלט מוגדרים ב-MediaMuxer.OutputFormat. נכון לעכשיו, MP4 הוא פורמט הפלט היחיד שנתמך, וכרגע יש תמיכה ב-MediaMuxer שידור אודיו אחד בלבד ו/או שידור וידאו אחד בכל פעם.

    MediaMuxer מיועד בעיקר לעבודה עם MediaCodec, כך שתוכלו לבצע עיבוד וידאו דרך MediaCodec ולאחר מכן לשמור את הפלט בקובץ MP4 דרך MediaMuxer. אפשר גם להשתמש ב-MediaMuxer בשילוב עם MediaExtractor כדי לערוך מדיה בלי צורך בקידוד או בפענוח.

    התקדמות ההפעלה ובחירת המיקום (scrub) עבור RemoteControlClient

    ב-Android 4.0 (רמת API 14), השדה RemoteControlClient נוסף אל להפעיל פקדי הפעלת מדיה מלקוחות שלטים רחוקים, כמו הפקדים הזמינים מסך הנעילה. ב-Android 4.3 יש עכשיו אפשרות לפקדים כאלה להציג את מיקום ההפעלה ואת הפקדים להחלפת קטע ההפעלה. אם הפעלתם שלט רחוק עבור אפליקציית מדיה עם ממשקי ה-API של RemoteControlClient, ואז אפשר יהיה להפעיל את הסרטון בחירת המיקום (scrubing) על ידי יישום שני ממשקים חדשים.

    קודם כול, צריך להעביר את הדגל FLAG_KEY_MEDIA_POSITION_UPDATE ל-setTransportControlsFlags() כדי להפעיל אותו.

    לאחר מכן מטמיעים את שני הממשקים החדשים הבאים:

    RemoteControlClient.OnGetPlaybackPositionListener
    הקריאה החוזרת (callback) onGetPlaybackPosition(), שמבקשת את המיקום הנוכחי של המדיה כשהשלט הרחוק צריך לעדכן את ההתקדמות בממשק המשתמש שלו.
    RemoteControlClient.OnPlaybackPositionUpdateListener
    הקריאה החוזרת (callback) onPlaybackPositionUpdate(), שמספקת לאפליקציה את קוד הזמן החדש של המדיה כשהמשתמש מפסיק את ההפעלה באמצעות ממשק המשתמש של השלט הרחוק.

    לאחר עדכון ההפעלה במיקום החדש, צריך לקרוא ל-setPlaybackState() כדי לציין המצב, המיקום והמהירות החדשים של ההפעלה.

    כאשר הממשקים האלה מוגדרים, אפשר להגדיר אותם עבור RemoteControlClient על ידי קריאה ל-setOnGetPlaybackPositionListener() setPlaybackPositionUpdateListener(), בהתאמה.

    גרפיקה

    תמיכה ב-OpenGL ES 3.0

    מערכת Android 4.3 כוללת ממשקי Java ותמיכה מובנית ב-OpenGL ES 3.0. פונקציונליות חדשה חשובה שסופק ב-OpenGL ES 3.0 כולל:

    • האצה של אפקטים חזותיים מתקדמים
    • דחיסת טקסטורות ETC2/EAC באיכות גבוהה כתכונה סטנדרטית
    • גרסה חדשה של שפת ההצללה GLSL ES עם תמיכה במספרים שלמים ובנקודות צפות של 32 ביט
    • רינדור טקסטורות מתקדם
    • סטנדרטיזציה רחבה יותר של גודל המרקם ופורמטים של מאגר נתונים זמני לעיבוד

    ממשק Java ל-OpenGL ES 3.0 ב-Android מסופק באמצעות GLES30. כשמשתמשים ב-OpenGL ES 3.0, חשוב להצהיר על כך בקובץ המניפסט באמצעות התג <uses-feature> והמאפיין android:glEsVersion. לדוגמה:

    <manifest>
        <uses-feature android:glEsVersion="0x00030000" />
        ...
    </manifest>

    וחשוב לזכור לציין את ההקשר של OpenGL ES באמצעות קריאה ל-setEGLContextClientVersion(), להעביר את 3 כגרסה.

    מידע נוסף על השימוש ב-OpenGL ES, כולל הוראות לבדיקה של גרסת OpenGL ES הנתמכת במכשיר בזמן הריצה, זמין במדריך API של OpenGL ES.

    מיפוי Mip לפריטי drawable

    שימוש ב-Mipmap כמקור למפת סיביות (bitmap) או לשרטוט גרפי הוא דרך פשוטה לספק תמונה איכותית וגדלים שונים של תמונות, שיכולים להיות שימושיים במיוחד אם מצפים תמונה שצריך לשנות את גודלה במהלך אנימציה.

    ב-Android 4.2 (רמת API 17) נוספה תמיכה במיפויי מפות בBitmap כיתה – מערכת Android מחליפה את תמונות ה-mip ב-Bitmap לאחר סיפק מקור Mipmap והפעלת את setHasMipMap(). ב-Android 4.3 אפשר עכשיו להפעיל מפות Mipmap גם עבור אובייקט BitmapDrawable, על ידי הוספה של נכס Mipmap הגדרת המאפיין android:mipMap בקובץ משאב של מפת סיביות (bitmap) או באמצעות קריאה ל-hasMipMap().

    ממשק משתמש

    הצגת שכבות-על

    הכיתה החדשה ViewOverlay מספקת שכבה שקופה מעל View, שבה אפשר להוסיף תוכן חזותי, והיא לא משפיעה על היררכיית הפריסה. אפשר לקבל ViewOverlay לכל View על ידי חיוג למספר getOverlay(). לשכבת-העל תמיד יש את אותו גודל ומיקום כמו של תצוגת המארח (התצוגה שממנה היא נוצרה), כך שתוכלו להוסיף תוכן שיופיע מול תצוגת המארח, אבל לא תוכלו להרחיב את גבולות תצוגת המארח.

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

    כשיוצרים שכבת-על לתצוגת ווידג'ט כמו Button, יכול להוסיף Drawable אובייקטים לשכבת-העל באמצעות קריאה add(Drawable). אם קוראים לפונקציה getOverlay() לתצוגת פריסה, כמו RelativeLayout, האובייקט המוחזר הוא ViewGroupOverlay. הכיתה ViewGroupOverlay היא Subclass של ViewOverlay שמאפשרת גם להוסיף אובייקטים מסוג View באמצעות קריאה ל-add(View).

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

    לדוגמה, הקוד הבא יוצר אנימציה של תצוגה שמחליקת ימינה על ידי הצבת התצוגה בשכבת-העל של תצוגת ההורה, ואז לבצע אנימציית תרגום בתצוגה הזו:

    Kotlin

    val view: View? = findViewById(R.id.view_to_remove)
    val container: ViewGroup? = view?.parent as ViewGroup
    
    container?.apply {
        overlay.add(view)
        ObjectAnimator.ofFloat(view, "translationX", right.toFloat())
                .start()
    }

    Java

    View view = findViewById(R.id.view_to_remove);
    ViewGroup container = (ViewGroup) view.getParent();
    container.getOverlay().add(view);
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight());
    anim.start();

    פריסת גבולות אופטיים

    בתצוגות שמכילות תמונות רקע מסוג nine-patch, עכשיו אפשר לציין שהן צריכות להיות מותאמות לתצוגות שכנות על סמך הגבולות 'האופטיים' של תמונה הרקע, ולא על סמך הגבולות 'החתוכים' של התצוגה.

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

    הערה: בצילום המסך שבאיורים 1 ו-2 יש את הכיתוב "Show" גבולות הפריסה" הגדרת המפתח מופעלת. בכל תצוגה, קווים אדומים מציינים את הגבולות האופטיים, קווים כחולים מציינים את הגבולות של הקליפ וקווים ורודיים מציינים את השוליים.

    איור 1. פריסה לפי גבולות הקליפ (ברירת המחדל).

    איור 2. פריסה באמצעות גבולות אופטיים.

    כדי ליישר את התצוגות על סמך גבולות הראייה שלהן, מגדירים את המאפיין android:layoutMode לערך "opticalBounds" באחד מהפריסות של ההורה. לדוגמה:

    <LinearLayout android:layoutMode="opticalBounds" ... >

    איור 3. תצוגה מוגדלת של התמונה של לחצן Holo עם תשע משבצות עם גבולות אופטיים.

    כדי שהשיטה הזו תפעל, בתמונות nine-patch שמוגדרות ברקע התצוגות צריך לציין את הגבולות האופטיים באמצעות קווים אדומים בחלק התחתון ובצד השמאלי של קובץ nine-patch (כפי שמוצג באיור 3). הקווים האדומים מציינים את האזור שצריך להחסיר מגבולות הקליפ, כדי להשאיר את הגבולות האופטיים של התמונה.

    כשמפעילים גבולות אופטיים ל-ViewGroup בפריסה, כל תצוגות הצאצאים יורשות את מצב הפריסה של גבולות אופטיים, אלא אם מבטלים את ההגדרה הזו לקבוצה על ידי הגדרת android:layoutMode ל-"clipBounds". כל רכיבי הפריסה את הגבולות האופטיים של תפיסות הילדים שלהם, תוך התאמת הגבולות שלהם על סמך הגבולות האופטיים את הצפיות שבהן. עם זאת, רכיבי פריסה (תת-כיתות של ViewGroup) לא תומכים כרגע בגבולות אופטיים לתמונות nine-patch שחלות על רקע משלהם.

    אם יוצרים תצוגה מותאמת אישית על ידי יצירה של תת-סוג של View,‏ ViewGroup או של תת-סוגים שלהם, התצוגה תירש את ההתנהגויות האלה שקשורות לקישורים אופטיים.

    הערה: כל הווידג'טים שנתמכים בעיצוב Holo עודכנו עם גבולות אופטיים, כולל Button,‏ Spinner,‏ EditText ועוד. לכן, אם האפליקציה שלכם משתמשת בנושא Holo (Theme.Holo,‏ Theme.Holo.Light וכו'), תוכלו ליהנות מהיתרונות באופן מיידי על ידי הגדרת המאפיין android:layoutMode לערך "opticalBounds".

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

    אנימציה לערכים של Rect

    עכשיו אפשר להוסיף אנימציה בין שני ערכים של Rect עם הערך החדש RectEvaluator. הכיתה החדשה היא יישום של TypeEvaluator שאפשר להעביר ל-ValueAnimator.setEvaluator().

    צירוף חלונות והתמקדות ב-listener

    בעבר, אם רצית להאזין לאירועים שבהם התצוגה מצורפת/מופרדת מהחלון או כשהמיקוד שלה משתנה, היה עליך לשנות את הגדרת ברירת המחדל של הכיתה View כדי להטמיע את onAttachedToWindow() ו-onDetachedFromWindow(), או את onWindowFocusChanged(), בהתאמה.

    עכשיו, כדי לקבל אירועים של צירוף ולנתק, אפשר במקום זאת להטמיע את ViewTreeObserver.OnWindowAttachListener ולהגדיר אותו בתצוגה באמצעות addOnWindowAttachListener(). כדי לקבל אירועי התמקדות, אפשר להטמיע את ViewTreeObserver.OnWindowFocusChangeListener ולהגדיר אותו בתצוגה באמצעות addOnWindowFocusChangeListener().

    תמיכה ב-overscan בטלוויזיה

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

    כיוון המסך

    המאפיין screenOrientation של התג <activity> תומך עכשיו בערכים נוספים כדי לכבד את העדפת המשתמש בנושא רוטציה אוטומטית:

    "userLandscape"
    ההתנהגות זהה לזו של "sensorLandscape", אלא אם המשתמש משבית את הסיבוב האוטומטי, ואז המסך נעול בכיוון הרגיל לרוחב ולא יתהפך.
    "userPortrait"
    התנהגות זהה לזו של "sensorPortrait", אלא אם המשתמש משבית את הסיבוב האוטומטי אז הוא ננעל בפריסה לאורך הרגיל ולא מתהפך.
    "fullUser"
    ההתנהגות זהה לזו של "fullSensor" ומאפשרת סיבוב בכל ארבעת הכיוונים, אלא אם המשתמש משבית את הסיבוב האוטומטי, ואז המסך נעול בכיוון המועדף על המשתמש.

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

    אנימציות של סיבוב

    השדה החדש rotationAnimation בקובץ WindowManager מאפשר לבחור באחת משלוש אנימציות שרוצים להשתמש בהן כשהמערכת מחליפה את כיוון המסך. שלוש האנימציות הן:

    הערה: האנימציות האלה זמינות רק אם הגדרתם שהפעילות תופעל במצב 'מסך מלא'. אפשר להפעיל את המצב הזה בעזרת עיצובים כמו Theme.Holo.NoActionBar.Fullscreen.

    לדוגמה, כך מפעילים את האנימציה 'מעבר הדרגתי':

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val params: WindowManager.LayoutParams = window.attributes
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE
        window.attributes = params
        ...
    }

    Java

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
        getWindow().setAttributes(params);
        ...
    }

    קלט של משתמשים

    סוגי חיישנים חדשים

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

    החיישנים החדשים של TYPE_GYROSCOPE_UNCALIBRATED ו-TYPE_MAGNETIC_FIELD_UNCALIBRATED מספקים נתוני חיישנים גולמיים ללא בנוגע להערכות הטיה. כלומר, הערכים הקיימים TYPE_GYROSCOPE ו-TYPE_MAGNETIC_FIELD חיישנים מספקים נתוני חיישנים שלוקחים בחשבון את ההטיה המשוערת מסחף הג'יירו וברזל קשה במכשיר, בהתאמה. לעומת זאת, הגרסאות החדשות "לא מתואמות" של החיישנים האלה מספקות את נתוני החיישן הגולמיים ומציעות את ערכי ההטיה המשוערים בנפרד. החיישנים האלה מאפשרים לכם לספק כיול מותאם אישית משלכם לנתוני החיישן על ידי שיפור הטיה המשוערת באמצעות נתונים חיצוניים.

    האזנה להתראות

    ב-Android 4.3 נוספה רמת שירות חדשה, NotificationListenerService, שמאפשרת לאפליקציה לקבל מידע על התראות חדשות כשהן מתפרסמות על ידי המערכת.

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

    ניהול אנשי הקשר

    שאילתה עבור 'contactables'

    השאילתה החדשה של ספק אנשי הקשר, Contactables.CONTENT_URI, מספקת דרך יעילה לקבל Cursor אחד שמכיל את כל כתובות האימייל ומספרי הטלפון השייכים לכל אנשי הקשר שתואמים לשאילתה שצוינה.

    שאילתה לגבי דלתא של אנשי קשר

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

    כדי לעקוב אחר שינויים בהוספות ובעדכונים, עכשיו אפשר לכלול את הפרמטר CONTACT_LAST_UPDATED_TIMESTAMP כשבוחרים להריץ שאילתות רק על אנשי הקשר שהשתנו מאז הפעם האחרונה שהרצתם שאילתות עם הספק.

    כדי לעקוב אחרי אנשי הקשר שנמחקו, הטבלה החדשה ContactsContract.DeletedContacts מציגה יומן של אנשי קשר שנמחקו (אבל כל איש קשר שנמחק נשמר בטבלה הזו לפרק זמן מוגבל). בדומה ל-CONTACT_LAST_UPDATED_TIMESTAMP, אפשר להשתמש בפרמטר הבחירה החדש, CONTACT_DELETED_TIMESTAMP כדי לבדוק אילו אנשי קשר נמחקו מאז הפעם האחרונה ששאלת את הספק. הטבלה מכילה גם את הקבוע DAYS_KEPT_MILLISECONDS שמכיל את מספר הימים (במיליסקונדים) שבהם יומן האירועים יישמר.

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

    כדי למצוא קוד לדוגמה שמשתמש בממשקי ה-API האלה כדי לבדוק שינויים באנשי הקשר, אפשר לעיין בדוגמה של ApiDemos שזמינה בהורדה של דוגמאות ל-SDK.

    התאמה לשוק המקומי

    תמיכה משופרת בטקסט דו-כיווני

    הגרסאות הקודמות של Android תומכות בשפות ובפריסה מימין לשמאל (RTL), אבל לפעמים לא מטפלים כראוי בטקסט בכיוונים מעורבים. לכן ב-Android 4.3 נוספים ממשקי ה-API של BidiFormatter שעוזרים לעצב כראוי טקסט עם כיוון נגדי. בלי לערבב חלקים ממנו.

    לדוגמה, כשרוצים ליצור משפט עם משתנה מחרוזת, כמו "האם התכוונת ל-15 Bay Street, Laurel, CA?", בדרך כלל מעבירים משאב מחרוזת מותאם לשפה והמשתנה אל String.format():

    Kotlin

    val suggestion = String.format(resources.getString(R.string.did_you_mean), address)

    Java

    Resources res = getResources();
    String suggestion = String.format(res.getString(R.string.did_you_mean), address);

    עם זאת, אם הלוקאל הוא עברית, המחרוזת המפורמטת תופיע כך:

    האם התכוונת ל 15 Bay Street, Laurel, CA?

    זה שגוי כי המספר '15' צריך להיות מימין לשם 'Bay Street'. הפתרון הוא להשתמש ב-BidiFormatter וב-method unicodeWrap(). לדוגמה, הקוד שלמעלה הופך ל:

    Kotlin

    val bidiFormatter = BidiFormatter.getInstance()
    val suggestion = String.format(
            resources.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address)
    )

    Java

    Resources res = getResources();
    BidiFormatter bidiFormatter = BidiFormatter.getInstance();
    String suggestion = String.format(res.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address));

    כברירת מחדל, unicodeWrap() משתמש בהערכה ההיוריסטית של כיוון חזק ראשון, שעלולה להוביל לשגיאות אם האות הראשון של כיוון הטקסט לא מייצג את הכיוון המתאים לתוכן כולו. אם צריך, אפשר לציין שיטת חיפוש אחרת על ידי העברת אחד מהקבועים TextDirectionHeuristic מ-TextDirectionHeuristics ל-unicodeWrap().

    הערה: ממשקי ה-API החדשים האלה זמינים גם לגרסאות קודמות. של Android דרך התמיכה של Android ספרייה, עם המחלקה BidiFormatter וממשקי API קשורים.

    שירותי נגישות

    טיפול באירועים מרכזיים

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

    בחירת טקסט והעתקה/הדבקה

    עכשיו יש ב-AccessibilityNodeInfo ממשקי API שמאפשרים AccessibilityService כדי לבחור, לגזור, להעתיק ולהדביק של הטקסט בצומת.

    כדי לציין את הטקסט שנבחר לחיתוך או להעתקה, שירות הנגישות יכול להשתמש בפעולה החדשה ACTION_SET_SELECTION, ולהעביר את המיקום ההתחלתי והסופי של הבחירה באמצעות ACTION_ARGUMENT_SELECTION_START_INT ו-ACTION_ARGUMENT_SELECTION_END_INT. לחלופין, אפשר לבחור טקסט על ידי שינוי מיקום הסמן באמצעות הפעולה הקיימת ACTION_NEXT_AT_MOVEMENT_GRANULARITY (לשעבר רק להזזת מיקום הסמן) והוספת הארגומנט ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN.

    לאחר מכן אפשר לגזור או להעתיק באמצעות ACTION_CUT, ACTION_COPY, ולאחר מכן מדביקים באמצעות ACTION_PASTE.

    הערה: ממשקי ה-API החדשים האלה זמינים גם לגרסאות קודמות. של Android דרך התמיכה של Android ספרייה, עם AccessibilityNodeInfoCompat בכיתה.

    הצהרה על תכונות נגישות

    החל מגרסה 4.3 של Android, שירותי נגישות צריכים להצהיר על יכולות הנגישות בקובץ המטא-נתונים שלהם כדי להשתמש בתכונות נגישות מסוימות. אם לא מבקשים את היכולת בקובץ המטא-נתונים, התכונה תהיה no-op. כדי להצהיר על יכולות הנגישות של השירות, צריך להשתמש במאפייני XML שתואמים למשתני הקבועים השונים של 'יכולת' בכיתה AccessibilityServiceInfo.

    לדוגמה, אם שירות מסוים לא מבקש את היכולת flagRequestFilterKeyEvents, הוא לא יקבל אירועים מרכזיים.

    בדיקה וניפוי באגים

    בדיקה אוטומטית של ממשק המשתמש

    בכיתה החדשה UiAutomation יש ממשקי API שמאפשרים לדמות משתמשים פעולות לאוטומציה של בדיקות. באמצעות ממשקי ה-API של AccessibilityService בפלטפורמה, UiAutomation ממשקי API מאפשרים לבדוק את תוכן המסך ולהחדיר אירועים שרירותיים של מקלדת ומגע.

    כדי לקבל מופע של UiAutomation, קוראים ל-Instrumentation.getUiAutomation(). כדי שהפעולה הזו תפעל, צריך לציין את האפשרות -w עם הפקודה instrument כשמריצים את InstrumentationTestCase מ-adb shell.

    באמצעות המופע UiAutomation, אפשר להריץ אירועים שרירותיים כדי לבדוק את האפליקציה. לשם כך, קוראים ל-executeAndWaitForEvent(), מעבירים לו Runnable לביצוע, פרק זמן לתפוגה של הפעולה והטמעה של ממשק UiAutomation.AccessibilityEventFilter. במסגרת ההטמעה של UiAutomation.AccessibilityEventFilter תתקבל שיחה שמאפשר לסנן את האירועים שמעניינים אתכם ולקבוע את מידת ההצלחה או או כשל בתרחיש בדיקה נתון.

    כדי לצפות בכל האירועים במהלך בדיקה, יוצרים הטמעה של UiAutomation.OnAccessibilityEventListener ומעבירים אותה אל setOnAccessibilityEventListener(). לאחר מכן ממשק ה-listener מקבל קריאה ל-onAccessibilityEvent() בכל פעם שאירוע מתרחש, קבלת אובייקט AccessibilityEvent שמתאר את האירוע.

    יש מגוון פעולות אחרות שממשקי ה-API של UiAutomation חושפים ברמה נמוכה מאוד כדי לעודד פיתוח של כלים לבדיקה של ממשק המשתמש, כמו uiautomator. לדוגמה, UiAutomation יכול גם:

    • החדרת אירועי קלט
    • שינוי כיוון המסך
    • יצירת צילומי מסך

    הדבר החשוב ביותר מבחינת כלים לבדיקת ממשק המשתמש, ממשקי ה-API של UiAutomation פועלים מעבר לגבולות האפליקציה, שלא כמו בגבולות ה-Instrumentation.

    אירועי Systrace לאפליקציות

    Android 4.3 מוסיף את המחלקה Trace באמצעות שתי שיטות סטטיות, beginSection() וגם endSection(), שמאפשרות להגדיר בלוקים של קוד שייכללו בדוח ה-systrace. כשיוצרים באפליקציה קטעים של קוד שניתן לעקוב אחריהם, יומני systrace מספקים ניתוח מפורט הרבה יותר של המקומות שבהם מתרחש האיטון באפליקציה.

    מידע על השימוש בכלי Systrace זמין במאמר ניתוח התצוגה והביצועים באמצעות Systrace.

    אבטחה

    מאגר מפתחות של Android למפתחות פרטיים של אפליקציות

    מערכת Android מציעה עכשיו ספק אבטחה בהתאמה אישית של Java בKeyStore שנקראת Android Key Store, שמאפשרת ליצור ולשמור מפתחות פרטיים ניתנים לצפייה ולשימוש באפליקציה שלך בלבד. כדי לטעון את 'חנות המפתחות של Android', מעבירים "AndroidKeyStore" עד KeyStore.getInstance().

    כדי לנהל את פרטי הכניסה הפרטיים של האפליקציה ב-Android Key Store, יוצרים מפתח חדש באמצעות KeyPairGenerator עם KeyPairGeneratorSpec. קודם צריך לקבל מופע של KeyPairGenerator באמצעות קריאה ל-getInstance(). ואז להתקשר initialize(), מעבירים אותה מופע של KeyPairGeneratorSpec, ואפשר לקבל באמצעותו KeyPairGeneratorSpec.Builder. לבסוף, צריך להתקשר למספר generateKeyPair() כדי לקבל את KeyPair.

    אחסון פרטי כניסה לחומרה

    עכשיו יש ב-Android תמיכה גם באחסון שמגובה בחומרה למכשיר KeyChain שלך וכך להגביר את האבטחה בכך שהמפתחות לא יהיו זמינים לחילוץ. כלומר, פעם אחת מפתחות נמצאים בחנות מפתחות שמגובת בחומרה (אלמנט מאובטח, TPM או TrustZone), אפשר להשתמש בהם פעולות קריפטוגרפיות אבל לא ניתן לייצא את חומר המפתח הפרטי. אפילו לליבת מערכת ההפעלה אין גישה לחומר המפתח הזה. לא כל המכשירים מבוססי Android תומכים באחסון חומרה, אפשר לבדוק בזמן הריצה אם אחסון בגיבוי חומרה זמין באמצעות התקשרות KeyChain.IsBoundKeyAlgorithm()

    הצהרות במניפסט

    תכונות נדרשות שאפשר להצהיר עליהן

    עכשיו יש תמיכה בערכים הבאים ברכיב <uses-feature>, כדי שתוכלו לוודא שהאפליקציה מותקנת רק במכשירים שמספקים את התכונות הנדרשות לה.

    FEATURE_APP_WIDGETS
    הצהרה על כך שהאפליקציה מספקת ווידג'ט של אפליקציה, ויש להתקין אותה רק במכשירים שכוללים מסך בית או מיקום דומה שבו המשתמשים יכולים להטמיע ווידג'טים של אפליקציות. דוגמה:
    <uses-feature android:name="android.software.app_widgets" android:required="true" />
    FEATURE_HOME_SCREEN
    הצהרה שהאפליקציה פועלת כתחליף למסך הבית ושצריך להתקין אותה רק מכשירים שתומכים באפליקציות של צד שלישי במסך הבית. דוגמה:
    <uses-feature android:name="android.software.home_screen" android:required="true" />
    FEATURE_INPUT_METHODS
    הצהרה על כך שהאפליקציה מספקת שיטת קלט בהתאמה אישית (מקלדת שנוצרה באמצעות InputMethodService), וצריכה להיות מותקנת רק במכשירים שתומכים בשיטות קלט של צד שלישי. דוגמה:
    <uses-feature android:name="android.software.input_methods" android:required="true" />
    FEATURE_BLUETOOTH_LE
    הצהרה שהאפליקציה שלך משתמשת בממשקי Bluetooth עם צריכת אנרגיה נמוכה ושצריך להתקין אותה רק במכשירים שיכולים לתקשר עם מכשירים אחרים באמצעות Bluetooth Low Energy. דוגמה:
    <uses-feature android:name="android.software.bluetooth_le" android:required="true" />

    הרשאות משתמשים

    הערכים הבאים נתמכים עכשיו ב<uses-permission> להצהרה ההרשאות שנדרשות לאפליקציה כדי לגשת לממשקי API מסוימים.

    BIND_NOTIFICATION_LISTENER_SERVICE
    חובה להשתמש בממשקי ה-API החדשים של NotificationListenerService.
    SEND_RESPOND_VIA_MESSAGE
    נדרש כדי לקבל את ACTION_RESPOND_VIA_MESSAGE בכוונה טובה.

    כדי לראות תצוגה מפורטת של כל השינויים ב-API ב-Android 4.3, אפשר לעיין בדוח ההבדלים ב-API.