שפת AIDL מבוססת באופן רופף על שפת Java. הקבצים מציינים חוזה ממשק וקבועים וסוגי נתונים שונים שמשמשים בחוזה הזה.
חבילה
כל קובץ AIDL מתחיל בחבילה אופציונלית שתואמת לשמות החבילות בקצוות העורפי השונים. הצהרה על חבילה נראית כך:
package my.package;
בדומה ל-Java, קובצי AIDL חייבים להיות במבנה תיקיות שתואם לחבילה שלהם. קבצים עם חבילה my.package
חייבים להיות בתיקייה my/package/
.
סוגים
בקובצי AIDL יש הרבה מקומות שבהם אפשר לציין את הסוגים. רשימה מדויקת של הסוגים שנתמכים בשפת AIDL מופיעה במאמר סוגי הקצוות העורפי של AIDL.
הערות
כמה חלקים מהשפה של AIDL תומכים בהערות. רשימה של הערות ואיפה אפשר להחיל אותן מפורטת במאמר הערות ב-AIDL.
ייבוא
כדי להשתמש בסוגים שמוגדרים בממשקים אחרים, קודם צריך להוסיף יחסי תלות במערכת ה-build. במודולים cc_*
ו-java_*
Sog, שבהם נעשה שימוש בקובצי .aidl
ישירות במסגרת srcs
בגרסאות build של פלטפורמת Android, אפשר להוסיף ספריות באמצעות השדה aidl: { include_dirs: ... }
. מידע נוסף על ייבוא באמצעות aidl_interface
זמין כאן.
ייבוא נראה כך:
import some.package.Foo; // explicit import
כשמייבאים סוג באותה החבילה, אפשר להשמיט את החבילה. עם זאת, השמטת החבילה עלולה להוביל לשגיאות ייבוא לא ברורות כשמציינים סוגים ללא חבילה ומכניסים אותם למרחב השמות הגלובלי (בדרך כלל צריך להקצות לכל הסוגים מרחב שמות):
import Foo; // same as my.package.Foo
הגדרת סוגים
בדרך כלל, קובצי AIDL מגדירים סוגים שמשמשים כממשק.
ממשקים
דוגמה לממשק AIDL:
interface ITeleport {
// Location defined elsewhere
void teleport(Location baz, float speed);
String getName();
// ITeleportCallback defined elsewhere
void methodWithCallback(ITeleportCallback callback);
// ITeleportSession defined elsewhere
ITeleportSession getASubInterface();
}
ממשק מגדיר אובייקט עם סדרה של שיטות. השיטות יכולות להיות oneway
(oneway void doFoo()
) או סינכרוניות. אם ממשק מוגדר בתור oneway
(oneway interface ITeleport {...}
), כל השיטות בו הן oneway
באופן סמלי. שיטות חד-כיווניות מופעלות באופן אסינכרוני ולא ניתן להחזיר בהן תוצאה. שיטות חד-כיווניות מאותו חוט לאותו מקשר (binder) גם מתבצעות ברצף (אבל יכול להיות שבחוטים שונים). במאמר ניהול שרשור של קצות עורפי של AIDL מוסבר איך מגדירים את השרשור.
בעזרת Binder אפשר לשתף ממשקים רבים ואובייקטים של Binder באמצעות ממשקי Binder. ממשקי AIDL משתמשים לעיתים קרובות בקריאות חזרה (callbacks) כחלק מבקריאות ל-method, כמו ב-ITeleportCallback
בדוגמה הקודמת. אפשר לעשות שימוש חוזר באובייקטים של קריאה חוזרת בין קריאות לאותה שיטה או בין קריאות לשיטות שונות. שימוש נפוץ נוסף בסוגי ממשקים הוא להחזרת ממשקי משנה או אובייקטים של סשנים משיטות, כמו השיטה with ITeleportSession
בדוגמה הקודמת. ההטמעה הזו מאפשרת להכניס לתוך קופסה ממשקי API שונים, ברמת ה-API או על סמך מצב בסביבת זמן הריצה. לדוגמה, סשן עשוי לייצג את הבעלות על משאב מסוים. כשמעבירים ממשקים כמה פעמים או מחזירים אותם ללקוח או לשרת שמהם הם הגיעו, הם תמיד שומרים על השוויון של ההצבעה של אובייקט הקישור הבסיסי.
שיטות יכולות לכלול אפס ארגומנטים או יותר. ארגומנטים לשיטות יכולים להיות in
, out
או inout
. למידע על ההשפעה של השינוי הזה על סוגי ארגומנטים, ראו כיווניות של קצוות עורפיים של AIDL.
Parcelables
Parcelables בהתאמה אישית לקצוות עורפיים של AIDL
ב-Android מגרסה 10 ואילך יש תמיכה בהגדרות של Parcelable ישירות ב-AIDL. סוג ה-Parcelable הזה נקרא Parcelable מובנה. למידע נוסף על הקשר בין קוד AIDL מובנה לקוד AIDL יציב במהדר AIDL ובמערכת ה-build שלנו, ראו קוד AIDL מובנה לעומת קוד AIDL יציב.
לדוגמה:
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
איגודים
ב-Android מגרסה 12 ואילך יש תמיכה בהצהרות על איחודים מתויגים. לדוגמה:
package my.package;
import my.package.FooSettings;
import my.package.BarSettings;
union Settings {
FooSettings fooSettings;
BarSettings barSettings;
@utf8InCpp String str;
int number;
}
לפרטים ספציפיים לקצה העורפי, ראו איחודים לקצה העורפי של AIDL.
טיפוסים בני מנייה (enum)
ב-Android מגרסה 11 ואילך יש תמיכה בהצהרות על ערכים מוגדרים מראש. לדוגמה:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
הצהרות מסוג בתוך רכיב
ב-Android מגרסה 13 ואילך יש תמיכה בהצהרות מסוג מקונן. לדוגמה:
package my.package;
import my.package.Baz;
interface IFoo {
void doFoo(Baz.Nested nested); // defined in my/package/Baz.aidl
void doBar(Bar bar); // defined below
parcelable Bar { ... } // nested type definition
}
קבועים
ממשקי AIDL, רכיבי Parcelable וישויות איחוד בהתאמה אישית יכולים גם להכיל ערכים קבועים של מחרוזות ומספרים שלמים, כמו:
const @utf8InCpp String HAPPY = ":)";
const String SAD = ":(";
const byte BYTE_ME = 1;
const int ANSWER = 6 * 7;
ביטויים קבועים
אפשר לציין קבועים, גדלים של מערכי AIDL ומערכי enumerators באמצעות ביטויים קבועים. ביטויים יכולים להוסיף סוגריים כדי לבצע פעולות בקינון. אפשר להשתמש בערכים של ביטוי קבוע עם ערכים אינטגרליים או עם ערכים צפים.
ליטרלים של true
ו-false
מייצגים ערכים בוליאניים. ערכים עם .
אבל ללא סיומת, כמו 3.8
, נחשבים כערכים כפולים. לערכים צפים יש סיומת f
, למשל 2.4f
. ערך אינטגרלי עם הסיומת l
או L
מציין ערך באורך של 64 ביט. אחרת, הערכים של האינטגרלים מקבלים את הסוג הקטן ביותר עם סימן לשמירת הערך, בין 8 ביט (בייט), 32 ביט (int) ו-64 ביט (long). לכן, 256
נחשב כ-int
, אבל הערך של 255 + 1
חורג מ-byte
0
. ערכים הקסדצימליים, כמו 0x3
, מפורשים קודם בתור הסוג הקטן ביותר ללא סימן שמאפשר לשמור על הערך בין 32 ל-64 סיביות, ולאחר מכן מפורשים מחדש בתור ערכים ללא סימן. לכן, הערך של 0xffffffff
הוא int
-1
. החל מ-Android 13, אפשר להוסיף את הסיומת u8
למשתני קבועים, כמו 3u8
, כדי לייצג ערך byte
. הסיומת הזו חשובה כדי שחישוב כמו 0xffu8 * 3
יפורש כ--3
מסוג byte
, בעוד ש-0xff * 3
הוא 765
מסוג int
.
לאופרטורים הנתמכים יש סמנטיקה של C++ ו-Java. האופרטורים הבינאריים הם || && | ^ & == != < > <= >= << >> + - * / %
, מהנמוכה לגבוהה. אופרטורים חד-ערך הם + - ! ~
.