ספק היומן הוא מאגר של אירועי היומן של המשתמש. ממשק ה-API של ספק היומן מאפשר לבצע שאילתות, להוסיף, לעדכן ולמחוק פעולות על יומנים, אירועים, משתתפים, תזכורות וכו'.
אפליקציות ומתאמי סנכרון יכולים להשתמש בממשק ה-API של ספק היומן. הכללים משתנים בהתאם לסוג התוכנית שמבצעת את הקריאות. המסמך הזה מתמקד בעיקר בשימוש ב- Calendar Provider API כאפליקציה. במאמר מתאמי סנכרון מוסבר על ההבדלים בין מתאמי הסנכרון.
בדרך כלל, כדי לקרוא או לכתוב נתוני יומן, המניפסט של אפליקציה לכלול את ההרשאות המתאימות, שמתוארות בקטע הרשאות. כדי לבצע פעולות נפוצות בקלות רבה יותר, ספק יומן Google מציע קבוצה של כוונות, כפי שמתואר במאמר כוונות ביומן Google. הכוונות האלה מפנות את המשתמשים לאפליקציית יומן Google כדי להוסיף, להציג ולערוך אירועים. המשתמש יוצר אינטראקציה עם אפליקציית יומן Google ואז חוזר לאפליקציה המקורית. לכן האפליקציה שלכם לא צריכה לבקש הרשאות, והיא לא צריכה לספק ממשק משתמש כדי לצפות באירועים או ליצור אירועים.
יסודות
ספקי תוכן שומרים נתונים ומאפשרים לאפליקציות לגשת אליהם. ספקי התוכן שמוצעים על ידי פלטפורמת Android (כולל ספק היומן) חושפים בדרך כלל נתונים כקבוצה של טבלאות שמבוססות על מודל של מסד נתונים יחסיים, שבו כל שורה היא רשומה וכל עמודה היא נתונים מסוג ומשמעות מסוימים. באמצעות ה-API של ספק היומן, אפליקציות מתאמי סנכרון יכולים לקבל גישה לקריאה/כתיבה לטבלאות של מסדי הנתונים נתוני היומן של המשתמש.
כל ספק תוכן חושף URI ציבורי (עטוף כאובייקט Uri
) שמזהה באופן ייחודי את קבוצת הנתונים שלו. ספק תוכן ששולט
מספר קבוצות נתונים (מספר טבלאות) חושף URI נפרד לכל אחת מהן. הכול
מזהי URI של ספקים מתחילים במחרוזת 'content:// '. הזה
מזהה את הנתונים כנשלטים על ידי ספק תוכן. ספק היומן מגדיר קבועים למזהי ה-URI של כל אחת מהכיתות (טבלאות) שלו. מזהי ה-URI האלה הם בפורמט <class>.CONTENT_URI
. עבור
לדוגמה, Events.CONTENT_URI
.
באיור 1 מוצג ייצוג גרפי של מודל הנתונים של ספק יומן Google. מוצגות בה הטבלאות הראשיות והשדות שמקשרים ביניהן.
למשתמש יכולים להיות כמה יומנים, וניתן לשייך יומנים שונים לסוגים שונים של חשבונות (יומן Google, Exchange וכן הלאה).
ה-CalendarContract
מגדיר את מודל הנתונים של מידע שקשור ליומן ולאירועים. הנתונים האלה מאוחסנים במספר טבלאות, שמפורטות בהמשך.
טבלה (מחלקה) | תיאור |
---|---|
בטבלה הזו מאוחסנים הפרטים הספציפיים ליומן. כל שורה בטבלה הזו כוללת את הפרטים של יומן יחיד, כמו שם, צבע, מידע לסנכרון וכן הלאה. | |
CalendarContract.Events |
בטבלה הזו נשמרים הפרטים הספציפיים לאירוע. כל שורה בטבלה הזו מכילה את המידע על אירוע אחד – לדוגמה, שם האירוע, המיקום, שעת ההתחלה, שעת הסיום וכו'. האירוע יכול להתרחש פעם אחת או לחזור על עצמו כמה פעמים. המשתתפים, התזכורות והמאפיינים המורחבים מאוחסנים בטבלאות נפרדות.
לכל אחד מהם יש EVENT_ID
שמפנה אל _ID בטבלת האירועים. |
CalendarContract.Instances |
בטבלה הזו מופיעים שעת ההתחלה ושעת הסיום של כל אירוע. כל שורה בטבלה הזו מייצג אירוע אחד של אירוע. לאירועים חד-פעמיים יש מיפוי של 1:1 של מופעים לאירועים. במקרה של אירועים חוזרים, המערכת מסמנת באופן אוטומטי כמה שורות שנוצרו בהתאם למספר חזרות של אותו אירוע. |
CalendarContract.Attendees |
בטבלה הזו שמורים הפרטים של המשתתפים (האורחים) באירוע. כל שורה מייצגת אורח אחד באירוע. היא מציינת את סוג האורח ואת תגובת הנוכחות שלו לאירוע. |
CalendarContract.Reminders |
בטבלה הזו נשמרים נתוני ההתראות. כל שורה מייצגת התראה אחת לגבי אירוע.
לאירוע הזה יכולות להיות מספר תזכורות. המספר המקסימלי של תזכורות לכל אירוע מצוין בשדה MAX_REMINDERS , שמוגדר על ידי מתאם הסנכרון שבבעלותו היומן הנתון. התזכורות מפורטות לפי מספר הדקות לפני האירוע, ויש להן שיטה שקובעת איך המשתמש יקבל התראה. |
ממשק ה-API של ספק יומן Google תוכנן להיות גמיש וחזק. ב חשוב לספק חוויית משתמש טובה להגן על תקינות היומן והנתונים שבו. לכן, ריכזנו כאן כמה דברים שכדאי לזכור כשמשתמשים ב-API:
- הוספה, עדכון והצגה של אירועים ביומן. כדי להוסיף, לשנות ולקרוא אירועים ישירות מספק היומן, צריך את ההרשאות המתאימות. עם זאת, אם אתם לא מפתחים אפליקציית יומן או מתאם סנכרון מלאים, אין צורך לבקש את ההרשאות האלה. במקום זאת, אפשר להשתמש בכוונות (intents) שנתמכות באפליקציית יומן Google ל-Android כדי להעביר את פעולות הקריאה והכתיבה לאפליקציה הזו. כשמשתמשים בכוונות, האפליקציה שולחת את המשתמשים לאפליקציית היומן כדי לבצע את הפעולה הרצויה בטופס שמולא מראש. אחרי שמסיימים, הם מוחזרים לבקשה. על ידי תכנון האפליקציה שלכם לביצוע פעולות נפוצות באמצעות יומן Google, אתם מספקים למשתמשים ממשק משתמש עקבי וחזק. זו הגישה המומלצת. למידע נוסף, ראה יומן Google Intents.
- מתאמי סנכרון. מתאם סנכרון מסנכרן את נתוני היומן
במכשיר של המשתמש באמצעות שרת אחר או מקור נתונים אחר. ב
CalendarContract.Calendars
והקבוצהCalendarContract.Events
טבלאות, יש עמודות ששמורות לשימוש במתאמי הסנכרון. הספק והאפליקציות לא אמורים לשנות אותם. למעשה, הם לא גלויים אלא אם ניגשים אליהם כמתאם סנכרון. מידע נוסף על מתאמי סנכרון זמין במאמר מתאמי סנכרון.
הרשאות משתמשים
כדי לקרוא נתוני יומן, האפליקציה צריכה לכלול את ההרשאה READ_CALENDAR
בקובץ המניפסט שלה. הוא
חייב לכלול את ההרשאה WRITE_CALENDAR
למחיקה, להוספה או לעדכון של נתוני היומן:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"...> <uses-sdk android:minSdkVersion="14" /> <uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" /> ... </manifest>
טבלת היומנים
הטבלה CalendarContract.Calendars
מכילה פרטים של יומנים ספציפיים. אפשר לכתוב בעמודות הבאות של יומנים גם באפליקציה וגם במתאם סנכרון.
לרשימה המלאה של השדות הנתמכים:
מסמך עזר של CalendarContract.Calendars
.
קבוע | תיאור |
---|---|
NAME |
שם היומן. |
CALENDAR_DISPLAY_NAME |
השם של היומן הזה שיוצג למשתמש. |
VISIBLE |
ערך בוליאני שמציין אם היומן נבחר להצגה. הערך 0 מציין שלא צריך להציג אירועים שמשויכים ליומן הזה. הערך 1 מציין שאירועים שמשויכים ליומן הזה צריכים להופיע. הערך הזה משפיע על יצירת השורות בטבלה CalendarContract.Instances . |
SYNC_EVENTS |
ערך בוליאני שמציין אם יש לסנכרן את היומן ולוודא שהוא מכיל אירועים שמאוחסנים במכשיר. הערך 0 מציין שלא מסנכרנים את היומן הזה ולא שומרים את האירועים שלו במכשיר. הערך 1 מציין שצריך לסנכרן את האירועים ביומן הזה ולאחסן את האירועים במכשיר. |
הכללת סוג חשבון לכל הפעולות
אם שולחים שאילתה על Calendars.ACCOUNT_NAME
, צריך לכלול גם
Calendars.ACCOUNT_TYPE
בבחירה. הסיבה לכך היא שחשבון נתון
נחשב לייחודי רק בהינתן ACCOUNT_NAME
ACCOUNT_TYPE
. ACCOUNT_TYPE
הוא המחרוזת שתואמת ל-
לאימות החשבון שנעשה בו שימוש כשהחשבון נרשם אצל
AccountManager
. יש גם חשבון מסוג מיוחד
נקרא ACCOUNT_TYPE_LOCAL
למשך
יומנים שלא משויכים לחשבון של המכשיר.
חשבונות ACCOUNT_TYPE_LOCAL
לא מסתנכרנים.
שליחת שאילתה ליומן
הנה דוגמה שמראה איך לאחזר את היומנים שבבעלות אדם מסוים
משתמש. כדי לפשט את הדוגמה, פעולת השאילתה מוצגת בשרשור של ממשק המשתמש ('השרשור הראשי'). בפועל, יש לעשות זאת באופן אסינכרוני
במקום בשרשור הראשי. לדיון נוסף, אפשר להיכנס
Loaders (מטענים). אם אתם לא רק קוראים את הנתונים אלא משנים אותם, תוכלו לעיין במאמר AsyncQueryHandler
.
Kotlin
// Projection array. Creating indices for this array instead of doing // dynamic lookups improves performance. private val EVENT_PROJECTION: Array<String> = arrayOf( CalendarContract.Calendars._ID, // 0 CalendarContract.Calendars.ACCOUNT_NAME, // 1 CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, // 2 CalendarContract.Calendars.OWNER_ACCOUNT // 3 ) // The indices for the projection array above. private const val PROJECTION_ID_INDEX: Int = 0 private const val PROJECTION_ACCOUNT_NAME_INDEX: Int = 1 private const val PROJECTION_DISPLAY_NAME_INDEX: Int = 2 private const val PROJECTION_OWNER_ACCOUNT_INDEX: Int = 3
Java
// Projection array. Creating indices for this array instead of doing // dynamic lookups improves performance. public static final String[] EVENT_PROJECTION = new String[] { Calendars._ID, // 0 Calendars.ACCOUNT_NAME, // 1 Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;
בחלק הבא של הדוגמה, נרכיב את השאילתה. הבחירה קובעת את הקריטריונים לשאילתה. בדוגמה הזו, השאילתה מחפשת
יומנים שכוללים את ACCOUNT_NAME
"hera@example.com", אל ACCOUNT_TYPE
'com.example', וגם OWNER_ACCOUNT
"hera@example.com". אם אתם רוצים לראות את כל היומנים של המשתמש
צפה, ולא רק ביומנים שבבעלות המשתמש, יש להשמיט את OWNER_ACCOUNT
.
השאילתה מחזירה אובייקט Cursor
שאפשר להשתמש בו כדי לעבור על קבוצת התוצאות שהוחזרה על ידי שאילתת מסד הנתונים. לדיון נוסף לגבי שימוש בשאילתות בספקי תוכן,
למידע נוסף, ראו ספקי תוכן.
Kotlin
// Run query val uri: Uri = CalendarContract.Calendars.CONTENT_URI val selection: String = "((${CalendarContract.Calendars.ACCOUNT_NAME} = ?) AND (" + "${CalendarContract.Calendars.ACCOUNT_TYPE} = ?) AND (" + "${CalendarContract.Calendars.OWNER_ACCOUNT} = ?))" val selectionArgs: Array<String> = arrayOf("hera@example.com", "com.example", "hera@example.com") val cur: Cursor = contentResolver.query(uri, EVENT_PROJECTION, selection, selectionArgs, null)
Java
// Run query Cursor cur = null; ContentResolver cr = getContentResolver(); Uri uri = Calendars.CONTENT_URI; String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" + Calendars.ACCOUNT_TYPE + " = ?) AND (" + Calendars.OWNER_ACCOUNT + " = ?))"; String[] selectionArgs = new String[] {"hera@example.com", "com.example", "hera@example.com"}; // Submit the query and get a Cursor object back. cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);
בקטע הבא משתמשים בסמן כדי לעבור דרך קבוצת התוצאות. הפונקציה משתמשת בערכי הקבועים שהוגדרו בתחילת הדוגמה כדי להחזיר את הערכים של כל שדה.
Kotlin
// Use the cursor to step through the returned records while (cur.moveToNext()) { // Get the field values val calID: Long = cur.getLong(PROJECTION_ID_INDEX) val displayName: String = cur.getString(PROJECTION_DISPLAY_NAME_INDEX) val accountName: String = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX) val ownerName: String = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX) // Do something with the values... }
Java
// Use the cursor to step through the returned records while (cur.moveToNext()) { long calID = 0; String displayName = null; String accountName = null; String ownerName = null; // Get the field values calID = cur.getLong(PROJECTION_ID_INDEX); displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX); accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX); ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX); // Do something with the values... ... }
שינוי יומן
כדי לבצע עדכון של יומן, אפשר לספק את _ID
של היומן כמזהה שמצורף ל-Uri (withAppendedId()
) או כפריט הבחירה הראשון. הבחירה
צריך להתחיל ב-"_id=?"
,
selectionArg
צריך להיות _ID
של היומן.
אפשר לבצע עדכונים גם על ידי קידוד המזהה ב-URI. בדוגמה הזו משנים את שם התצוגה של לוח שנה באמצעות הגישה (withAppendedId()
):
Kotlin
const val DEBUG_TAG: String = "MyActivity" ... val calID: Long = 2 val values = ContentValues().apply { // The new display name for the calendar put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar") } val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Calendars.CONTENT_URI, calID) val rows: Int = contentResolver.update(updateUri, values, null, null) Log.i(DEBUG_TAG, "Rows updated: $rows")
Java
private static final String DEBUG_TAG = "MyActivity"; ... long calID = 2; ContentValues values = new ContentValues(); // The new display name for the calendar values.put(Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar"); Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID); int rows = getContentResolver().update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows);
הוספת יומן
יומנים מנוהלים בעיקר על ידי מתאם סנכרון,
צריך להוסיף יומנים חדשים רק כמתאם סנכרון. ברוב המקרים, אפליקציות יכולות לבצע רק שינויים שטחיים בלוחות השנה, כמו שינוי השם המוצג. אם אפליקציה צריכה ליצור יומן מקומי, היא יכולה לעשות זאת על ידי ביצוע ההוספה של היומן כמתאם סנכרון, באמצעות ACCOUNT_TYPE
של ACCOUNT_TYPE_LOCAL
.
ACCOUNT_TYPE_LOCAL
הוא סוג חשבון מיוחד של יומנים שלא משויכים לחשבון מכשיר. יומנים מהסוג הזה לא מסונכרנים עם שרת. במאמר מתאמי סנכרון מוסבר על מתאמי סנכרון.
טבלת אירועים
הטבלה CalendarContract.Events
מכילה פרטים
לאירועים נפרדים. כדי להוסיף, לעדכן או למחוק אירועים, יש צורך באפליקציה
לכלול את ההרשאה WRITE_CALENDAR
קובץ מניפסט.
אפשר לכתוב בעמודות הבאות של Events גם באפליקציה וגם במתאם לסנכרון. רשימה מלאה של השדות הנתמכים מופיעה בחומר העזר בנושא CalendarContract.Events
.
קבוע | תיאור |
---|---|
CALENDAR_ID |
_ID של היומן שאליו האירוע שייך. |
ORGANIZER |
כתובת האימייל של מארגן האירוע (הבעלים) של האירוע. |
TITLE |
שם האירוע. |
EVENT_LOCATION |
המיקום שבו מתקיים האירוע. |
DESCRIPTION |
תיאור האירוע. |
DTSTART |
השעה שבה האירוע מתחיל, באלפיות השנייה לפי שעון UTC, מאז תחילת התקופה של זמן המערכת. |
DTEND |
השעה שבה האירוע מסתיים באלפיות שנייה (UTC) מאז תחילת התקופה. |
EVENT_TIMEZONE |
אזור הזמן של האירוע. |
EVENT_END_TIMEZONE |
אזור הזמן של שעת הסיום של האירוע. |
DURATION |
משך האירוע בפורמט RFC5545.
לדוגמה, ערך של "PT1H" מציין שהאירוע
אמור להימשך שעה אחת, וערך של "P2W" מציין
של שבועיים. |
ALL_DAY |
הערך 1 מציין שהאירוע הזה נמשך כל היום, כפי שמוגדר על ידי אזור הזמן המקומי. הערך 0 מציין שמדובר באירוע רגיל שיכול להתחיל ולהסתיים בכל שלב במהלך היום. |
RRULE |
כלל החזרה של פורמט האירוע. לדוגמה, "FREQ=WEEKLY;COUNT=10;WKST=SU" . טיפים נוספים לאופטימיזציה מפורטים
דוגמאות נוספות כאן. |
RDATE |
תאריכי החזרה של האירוע.
בדרך כלל משתמשים ב-RDATE יחד עם RRULE כדי להגדיר קבוצה מצטברת של מופעים חוזרים. מידע נוסף זמין במפרט RFC5545. |
AVAILABILITY |
אם האירוע נספר כזמן תפוס או כזמן פנוי שאפשר לתזמן מחדש. |
GUESTS_CAN_MODIFY |
האם האורחים יכולים לשנות את האירוע. |
GUESTS_CAN_INVITE_OTHERS |
האם האורחים יכולים להזמין אורחים אחרים. |
GUESTS_CAN_SEE_GUESTS |
אם האורחים יוכלו לראות את רשימת הנוכחים. |
הוספת אירועים
כשהאפליקציה מוסיפה אירוע חדש, מומלץ להשתמש ב-Intent INSERT
, כפי שמתואר במאמר שימוש ב-Intent להוספת אירוע. עם זאת, אם צריך, אפשר להוסיף אירועים ישירות. בקטע הזה נסביר איך לבצע
הזה.
אלו הכללים להוספת אירוע חדש:
- חובה לכלול את
CALENDAR_ID
ו-DTSTART
. - חובה לכלול
EVENT_TIMEZONE
. כדי לקבל רשימה של מזהי אזורי הזמן המותקנים במערכת, משתמשים ב-getAvailableIDs()
. חשוב לזכור שהכלל הזה לא חל אם מוסיפים אירוע באמצעות הכוונהINSERT
, כפי שמתואר בקטע שימוש בכוונה כדי להוסיף אירוע. בתרחיש כזה, מערכת GA4 מספקת אזור זמן שמוגדר כברירת מחדל. - באירועים לא חוזרים, צריך לכלול את הערך
DTEND
. - באירועים חוזרים, עליך לכלול
DURATION
בנוסף ל-RRULE
או ל-RDATE
. שימו לב שהכלל הזה לא חל אם מוסיפים אירוע באמצעות הכוונהINSERT
, כפי שמתואר במאמר שימוש בכוונה כדי להוסיף אירוע. בתרחיש כזה, אפשר להשתמש ב-RRULE
בשילוב עםDTSTART
ו-DTEND
, ואפליקציית יומן Google תמיר אותו לאורך זמן באופן אוטומטי.
דוגמה להוספת אירוע. הפעולה הזו מתבצעת בשרשור של ממשק המשתמש כדי לפשט את התהליך. בפועל, כדאי לבצע הוספות ועדכונים בשרשור אסינכרוני כדי להעביר את הפעולה לשרשור ברקע. למידע נוסף, ראו AsyncQueryHandler
.
Kotlin
val calID: Long = 3 val startMillis: Long = Calendar.getInstance().run { set(2012, 9, 14, 7, 30) timeInMillis } val endMillis: Long = Calendar.getInstance().run { set(2012, 9, 14, 8, 45) timeInMillis } ... val values = ContentValues().apply { put(CalendarContract.Events.DTSTART, startMillis) put(CalendarContract.Events.DTEND, endMillis) put(CalendarContract.Events.TITLE, "Jazzercise") put(CalendarContract.Events.DESCRIPTION, "Group workout") put(CalendarContract.Events.CALENDAR_ID, calID) put(CalendarContract.Events.EVENT_TIMEZONE, "America/Los_Angeles") } val uri: Uri = contentResolver.insert(CalendarContract.Events.CONTENT_URI, values) // get the event ID that is the last element in the Uri val eventID: Long = uri.lastPathSegment.toLong() // // ... do something with event ID // //
Java
long calID = 3; long startMillis = 0; long endMillis = 0; Calendar beginTime = Calendar.getInstance(); beginTime.set(2012, 9, 14, 7, 30); startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2012, 9, 14, 8, 45); endMillis = endTime.getTimeInMillis(); ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(Events.DTSTART, startMillis); values.put(Events.DTEND, endMillis); values.put(Events.TITLE, "Jazzercise"); values.put(Events.DESCRIPTION, "Group workout"); values.put(Events.CALENDAR_ID, calID); values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles"); Uri uri = cr.insert(Events.CONTENT_URI, values); // get the event ID that is the last element in the Uri long eventID = Long.parseLong(uri.getLastPathSegment()); // // ... do something with event ID // //
הערה: בדוגמה הזו אפשר לראות איך מתבצע תיעוד מזהה האירוע אחרי היצירה שלו. זו הדרך הקלה ביותר לקבל מזהה אירוע. לעיתים קרובות צריך את מזהה האירוע כדי לבצע פעולות אחרות ביומן – לדוגמה, כדי להוסיף משתתפים או תזכורות לאירוע.
אירועי עדכון
אם האפליקציה מבקשת לאפשר למשתמש לערוך אירוע, מומלץ
שמשתמשים ב-Intent EDIT
, כמו
שמתואר במאמר שימוש בכוונת רכישה כדי לערוך אירוע.
עם זאת, אם צריך, אפשר לערוך אירועים ישירות. כדי לבצע עדכון של
אירוע, ניתן לספק את _ID
של
את האירוע כמזהה מצורף ל-URI (withAppendedId()
)
או כפריט הבחירה הראשון.
הבחירה צריכה להתחיל ב-"_id=?"
, והראשון
הערך selectionArg
צריך להיות _ID
של האירוע. אפשר גם לבצע עדכונים באמצעות בחירה ללא מזהה. כאן יש דוגמה לעדכון
אירוע. שם האירוע ישתנה באמצעות
withAppendedId()
גישה:
Kotlin
val DEBUG_TAG = "MyActivity" ... val eventID: Long = 188 ... val values = ContentValues().apply { // The new title for the event put(CalendarContract.Events.TITLE, "Kickboxing") } val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val rows: Int = contentResolver.update(updateUri, values, null, null) Log.i(DEBUG_TAG, "Rows updated: $rows")
Java
private static final String DEBUG_TAG = "MyActivity"; ... long eventID = 188; ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); Uri updateUri = null; // The new title for the event values.put(Events.TITLE, "Kickboxing"); updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = cr.update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows);
מחיקת אירועים
אפשר למחוק אירוע לפי _ID
שלו כמזהה מצורף ב-URI, או באמצעות
בחירה רגילה. אם משתמשים במזהה שצורף, אי אפשר גם לבחור אפשרות.
יש שתי גרסאות של המחיקה: כאפליקציה וכמתאם סנכרון.
מחיקה באמצעות אפליקציה מגדירה את העמודה נמחקה ל-1. הדגל הזה שמציין
את מתאם הסנכרון שבו השורה נמחקה ושצריך למחוק את הפעולה הזו
הופץ לשרת. מחיקה של מתאם סנכרון תסיר את האירוע
את מסד הנתונים ואת כל הנתונים שמשויכים אליו. הנה דוגמה לאפליקציה
מחיקת אירוע דרך _ID
שלו:
Kotlin
val DEBUG_TAG = "MyActivity" ... val eventID: Long = 201 ... val deleteUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val rows: Int = contentResolver.delete(deleteUri, null, null) Log.i(DEBUG_TAG, "Rows deleted: $rows")
Java
private static final String DEBUG_TAG = "MyActivity"; ... long eventID = 201; ... ContentResolver cr = getContentResolver(); Uri deleteUri = null; deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = cr.delete(deleteUri, null, null); Log.i(DEBUG_TAG, "Rows deleted: " + rows);
טבלת המשתתפים
כל שורה בטבלה CalendarContract.Attendees
מייצג משתתף יחיד או אורח באירוע. קריאה ל-query()
מחזירה רשימה של המשתתפים באירוע עם EVENT_ID
הנתון.
הערך של EVENT_ID
חייב להתאים ל-_ID
של אירוע מסוים.
בטבלה הבאה מפורטים השדות שאפשר לכתוב בהם. כשמוסיפים משתתפים חדשים, צריך לכלול את כולם
חוץ מ-ATTENDEE_NAME
.
קבוע | תיאור |
---|---|
EVENT_ID |
מזהה האירוע. |
ATTENDEE_NAME |
השם של המשתתף. |
ATTENDEE_EMAIL |
כתובת האימייל של המשתתף. |
ATTENDEE_RELATIONSHIP |
הקשר של המשתתף לאירוע. אחת מהאפשרויות: |
ATTENDEE_TYPE |
סוג המשתתף. אחת מהאפשרויות: |
ATTENDEE_STATUS |
סטטוס ההשתתפות של המשתתף. אחת מהאפשרויות: |
הוספת משתתפים
בדוגמה הבאה אפשר להוסיף משתתף יחיד לאירוע. חשוב לזכור שהשדה EVENT_ID
הוא שדה חובה:
Kotlin
val eventID: Long = 202 ... val values = ContentValues().apply { put(CalendarContract.Attendees.ATTENDEE_NAME, "Trevor") put(CalendarContract.Attendees.ATTENDEE_EMAIL, "trevor@example.com") put( CalendarContract.Attendees.ATTENDEE_RELATIONSHIP, CalendarContract.Attendees.RELATIONSHIP_ATTENDEE ) put(CalendarContract.Attendees.ATTENDEE_TYPE, CalendarContract.Attendees.TYPE_OPTIONAL) put( CalendarContract.Attendees.ATTENDEE_STATUS, CalendarContract.Attendees.ATTENDEE_STATUS_INVITED ) put(CalendarContract.Attendees.EVENT_ID, eventID) } val uri: Uri = contentResolver.insert(CalendarContract.Attendees.CONTENT_URI, values)
Java
long eventID = 202; ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(Attendees.ATTENDEE_NAME, "Trevor"); values.put(Attendees.ATTENDEE_EMAIL, "trevor@example.com"); values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE); values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL); values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED); values.put(Attendees.EVENT_ID, eventID); Uri uri = cr.insert(Attendees.CONTENT_URI, values);
טבלת תזכורות
כל שורה בטבלה CalendarContract.Reminders
מייצגת תזכורת אחת לאירוע. קריאה ל-query()
מחזירה רשימה של תזכורות לאירוע עם הערך של EVENT_ID
.
בטבלה הבאה מפורטים השדות שאפשר לשנות בהתראות. צריך לכלול את כולם כשמוסיפים תזכורת חדשה. חשוב לזכור שהמתאמים לסנכרון מציינים את סוגי התזכורות שהם תומכים בהם בטבלה CalendarContract.Calendars
. צפייה
ALLOWED_REMINDERS
אפשר לקבל פרטים נוספים.
קבוע | תיאור |
---|---|
EVENT_ID |
מזהה האירוע. |
MINUTES |
הדקות לפני האירוע שבו התזכורת צריכה לפעול. |
METHOD |
שיטת ההתראה, כפי שהוגדר בשרת. אחת מהאפשרויות: |
הוספת תזכורות
הדוגמה הזו מוסיפה תזכורת לאירוע. התזכורת מופעלת 15 דקות לפני האירוע.
Kotlin
val eventID: Long = 221 ... val values = ContentValues().apply { put(CalendarContract.Reminders.MINUTES, 15) put(CalendarContract.Reminders.EVENT_ID, eventID) put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT) } val uri: Uri = contentResolver.insert(CalendarContract.Reminders.CONTENT_URI, values)
Java
long eventID = 221; ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(Reminders.MINUTES, 15); values.put(Reminders.EVENT_ID, eventID); values.put(Reminders.METHOD, Reminders.METHOD_ALERT); Uri uri = cr.insert(Reminders.CONTENT_URI, values);
טבלת המכונות
הטבלה CalendarContract.Instances
מכילה את הערך
את שעת ההתחלה והסיום של האירוע. כל שורה בטבלה הזו מייצגת אירוע יחיד. לא ניתן לכתוב בטבלת המופעים
מאפשרים להריץ שאילתות על אירועי אירועים.
בטבלה הבאה מפורטים כמה מהשדות שאפשר להריץ עליהם שאילתות למכונה מסוימת. הערה: אזור הזמן מוגדר לפי KEY_TIMEZONE_TYPE
ו-KEY_TIMEZONE_INSTANCES
.
קבוע | תיאור |
---|---|
BEGIN |
שעת ההתחלה של המכונה, באלפיות השנייה לפי שעון UTC. |
END |
שעת הסיום של המכונה, באלפיות השנייה לפי שעון UTC. |
END_DAY |
יום הסיום היוליאני של המכונה, ביחס לזמן ביומן תחום. |
END_MINUTE |
הדקה האחרונה של המופע, נמדדת מחצות באזור הזמן של היומן. |
EVENT_ID |
ה-_ID של האירוע עבור המופע הזה. |
START_DAY |
יום ההתחלה היוליאני של המכונה, ביחס לאזור הזמן של היומן. |
START_MINUTE |
דקת ההתחלה של המכונה, נמדדת מחצות, ביחס לאזור הזמן של יומן Google. |
שליחת שאילתה לטבלת המכונות
כדי להריץ שאילתה בטבלה Instances, צריך לציין טווח זמן לשאילתה ב-URI. בדוגמה הזו, ל-CalendarContract.Instances
יש גישה לשדה TITLE
דרך הטמעת הממשק CalendarContract.EventsColumns
.
במילים אחרות, הערך של TITLE
מוחזר דרך תצוגה של מסד נתונים, ולא באמצעות שאילתה לטבלה הגולמית CalendarContract.Instances
.
Kotlin
const val DEBUG_TAG: String = "MyActivity" val INSTANCE_PROJECTION: Array<String> = arrayOf( CalendarContract.Instances.EVENT_ID, // 0 CalendarContract.Instances.BEGIN, // 1 CalendarContract.Instances.TITLE // 2 ) // The indices for the projection array above. const val PROJECTION_ID_INDEX: Int = 0 const val PROJECTION_BEGIN_INDEX: Int = 1 const val PROJECTION_TITLE_INDEX: Int = 2 // Specify the date range you want to search for recurring // event instances val startMillis: Long = Calendar.getInstance().run { set(2011, 9, 23, 8, 0) timeInMillis } val endMillis: Long = Calendar.getInstance().run { set(2011, 10, 24, 8, 0) timeInMillis } // The ID of the recurring event whose instances you are searching // for in the Instances table val selection: String = "${CalendarContract.Instances.EVENT_ID} = ?" val selectionArgs: Array<String> = arrayOf("207") // Construct the query with the desired date range. val builder: Uri.Builder = CalendarContract.Instances.CONTENT_URI.buildUpon() ContentUris.appendId(builder, startMillis) ContentUris.appendId(builder, endMillis) // Submit the query val cur: Cursor = contentResolver.query( builder.build(), INSTANCE_PROJECTION, selection, selectionArgs, null ) while (cur.moveToNext()) { // Get the field values val eventID: Long = cur.getLong(PROJECTION_ID_INDEX) val beginVal: Long = cur.getLong(PROJECTION_BEGIN_INDEX) val title: String = cur.getString(PROJECTION_TITLE_INDEX) // Do something with the values. Log.i(DEBUG_TAG, "Event: $title") val calendar = Calendar.getInstance().apply { timeInMillis = beginVal } val formatter = SimpleDateFormat("MM/dd/yyyy") Log.i(DEBUG_TAG, "Date: ${formatter.format(calendar.time)}") }
Java
private static final String DEBUG_TAG = "MyActivity"; public static final String[] INSTANCE_PROJECTION = new String[] { Instances.EVENT_ID, // 0 Instances.BEGIN, // 1 Instances.TITLE // 2 }; // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; private static final int PROJECTION_TITLE_INDEX = 2; ... // Specify the date range you want to search for recurring // event instances Calendar beginTime = Calendar.getInstance(); beginTime.set(2011, 9, 23, 8, 0); long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); Cursor cur = null; ContentResolver cr = getContentResolver(); // The ID of the recurring event whose instances you are searching // for in the Instances table String selection = Instances.EVENT_ID + " = ?"; String[] selectionArgs = new String[] {"207"}; // Construct the query with the desired date range. Uri.Builder builder = Instances.CONTENT_URI.buildUpon(); ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query cur = cr.query(builder.build(), INSTANCE_PROJECTION, selection, selectionArgs, null); while (cur.moveToNext()) { String title = null; long eventID = 0; long beginVal = 0; // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); // Do something with the values. Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } }
כוונות ביומן
לאפליקציה שלכם לא נדרשות הרשאות כדי לקרוא ולכתוב נתוני יומן. האפליקציה יכולה להשתמש באובייקטים של Intent שנתמכים על ידי אפליקציית יומן Google ב-Android כדי לבצע פעולות קריאה וכתיבה באפליקציה הזו. בטבלה הבאה מפורטים ה-Intents שנתמכים על ידי ספק היומן:
פעולה | URI | תיאור | תוספות |
---|---|---|---|
VIEW |
CalendarContract.CONTENT_URI
לדוגמה, לשימוש ב-Intent הזה, ראו שימוש בכוונות להצגת נתוני יומן.
|
פותחים את היומן לשעה שצוינה ב-<ms_since_epoch> . |
ללא. |
Events.CONTENT_URI
לדוגמה, לשימוש ב-Intent הזה, ראו שימוש בכוונות להצגת נתוני יומן.
|
הצגת האירוע שצוין על ידי <event_id> . |
CalendarContract.EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_END_TIME |
|
EDIT |
Events.CONTENT_URI
דוגמה לשימוש ב-Intent הזה מופיעה במאמר שימוש בכוונת רכישה כדי לערוך אירוע.
|
עורכים את האירוע שצוין ב-<event_id> . |
CalendarContract.EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_END_TIME |
EDIT INSERT |
Events.CONTENT_URI .
דוגמה לשימוש בכוונה הזו מופיעה במאמר שימוש בכוונה כדי להוסיף אירוע.
|
יוצרים אירוע. | כל אחת מהתוספות המפורטות בטבלה שבהמשך. |
בטבלה הבאה מפורטים הנתונים הנוספים של הכוונה שנתמכים על ידי ספק היומן:
Intent Extra | תיאור |
---|---|
Events.TITLE |
שם לאירוע. |
CalendarContract.EXTRA_EVENT_BEGIN_TIME |
שעת ההתחלה של האירוע באלפיות השנייה מתחילת התקופה של זמן המערכת. |
CalendarContract.EXTRA_EVENT_END_TIME |
שעת הסיום של האירוע, במיליוניות השנייה מתחילת התקופה של זמן המערכת. |
CalendarContract.EXTRA_EVENT_ALL_DAY |
ערך בוליאני שמציין שאירוע הוא כל היום. הערך יכול להיות true או false . |
Events.EVENT_LOCATION |
המיקום של האירוע. |
Events.DESCRIPTION |
תיאור האירוע. |
Intent.EXTRA_EMAIL |
כתובות אימייל של האנשים שברצונך להזמין כרשימה מופרדת בפסיקים. |
Events.RRULE |
כלל החזר האירוע. |
Events.ACCESS_LEVEL |
האם האירוע הוא פרטי או ציבורי. |
Events.AVAILABILITY |
אם האירוע נחשב לזמן תפוס או לזמן פנוי שאפשר לתזמן בו פגישה. |
בסעיפים הבאים מוסבר איך להשתמש בכוונות האלה.
שימוש בכוונה (intent) להוספת אירוע
שימוש ב-Intent INSERT
מאפשר לאפליקציה להעביר את המשימה של הוספת האירוע ליומן Google עצמו.
בשיטה הזו, האפליקציה שלך לא צריכה אפילו לכלול את ההרשאה WRITE_CALENDAR
בקובץ המניפסט.
כשמשתמשים מריצים אפליקציה שמשתמשת בגישה הזו, האפליקציה שולחת
אותם ליומן Google כדי לסיים את הוספת האירוע. ב-Intent INSERT
משתמשים בשדות נוספים כדי
לאכלס מראש בטופס את פרטי האירוע ביומן. לאחר מכן, המשתמשים יוכלו לבטל את האירוע, לערוך את הטופס לפי הצורך או לשמור את האירוע ביומן שלהם.
הנה קטע קוד שמתזמנ אירוע ב-19 בינואר 2012 מ-7:30 עד 8:30. חשוב לשים לב לפרטים הבאים לגבי קטע הקוד:
- מצוין בה
Events.CONTENT_URI
בתור ה-Uri. - הוא משתמש בשדות הנוספים
CalendarContract.EXTRA_EVENT_BEGIN_TIME
ו-CalendarContract.EXTRA_EVENT_END_TIME
כדי לאכלס מראש את הטופס בשעת האירוע. הערכים של הזמנים האלה חייבים להיות לפי שעון UTC באלפיות השנייה מתחילת התקופה. - הוא משתמש בשדה הנוסף
Intent.EXTRA_EMAIL
כדי לספק רשימה של מוזמנים שמופרדת בפסיקים, לפי כתובת האימייל.
Kotlin
val startMillis: Long = Calendar.getInstance().run { set(2012, 0, 19, 7, 30) timeInMillis } val endMillis: Long = Calendar.getInstance().run { set(2012, 0, 19, 8, 30) timeInMillis } val intent = Intent(Intent.ACTION_INSERT) .setData(CalendarContract.Events.CONTENT_URI) .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis) .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis) .putExtra(CalendarContract.Events.TITLE, "Yoga") .putExtra(CalendarContract.Events.DESCRIPTION, "Group class") .putExtra(CalendarContract.Events.EVENT_LOCATION, "The gym") .putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY) .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com") startActivity(intent)
Java
Calendar beginTime = Calendar.getInstance(); beginTime.set(2012, 0, 19, 7, 30); Calendar endTime = Calendar.getInstance(); endTime.set(2012, 0, 19, 8, 30); Intent intent = new Intent(Intent.ACTION_INSERT) .setData(Events.CONTENT_URI) .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis()) .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis()) .putExtra(Events.TITLE, "Yoga") .putExtra(Events.DESCRIPTION, "Group class") .putExtra(Events.EVENT_LOCATION, "The gym") .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY) .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com"); startActivity(intent);
שימוש בכוונה לערוך אירוע
אפשר לעדכן אירוע ישירות, כפי שמתואר בקטע עדכון אירועים. עם זאת, שימוש ב-Intent EDIT
מאפשר לאפליקציה שאין לה הרשאה להעביר את עריכת האירועים לאפליקציית יומן Google.
כשהמשתמשים מסיימים לערוך את האירוע ביומן, הם מוחזרים לאפליקציה המקורית.
הנה דוגמה ל-Intent שמגדיר כותרת לאירוע מסוים ומאפשרת למשתמשים לערוך את האירוע ביומן.
Kotlin
val eventID: Long = 208 val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val intent = Intent(Intent.ACTION_EDIT) .setData(uri) .putExtra(CalendarContract.Events.TITLE, "My New Title") startActivity(intent)
Java
long eventID = 208; Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); Intent intent = new Intent(Intent.ACTION_EDIT) .setData(uri) .putExtra(Events.TITLE, "My New Title"); startActivity(intent);
שימוש בכוונות כדי להציג נתונים מהיומן
לספק היומן יש שתי דרכים שונות להשתמש ב-Intent VIEW
:
- כדי לפתוח את יומן Google בתאריך מסוים.
- כדי להציג אירוע.
דוגמה לאופן שבו פותחים את היומן לתאריך מסוים:
Kotlin
val startMillis: Long ... val builder: Uri.Builder = CalendarContract.CONTENT_URI.buildUpon() .appendPath("time") ContentUris.appendId(builder, startMillis) val intent = Intent(Intent.ACTION_VIEW) .setData(builder.build()) startActivity(intent)
Java
// A date-time specified in milliseconds since the epoch. long startMillis; ... Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon(); builder.appendPath("time"); ContentUris.appendId(builder, startMillis); Intent intent = new Intent(Intent.ACTION_VIEW) .setData(builder.build()); startActivity(intent);
הדוגמה הבאה מראה איך לפתוח אירוע לצפייה:
Kotlin
val eventID: Long = 208 ... val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val intent = Intent(Intent.ACTION_VIEW).setData(uri) startActivity(intent)
Java
long eventID = 208; ... Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); Intent intent = new Intent(Intent.ACTION_VIEW) .setData(uri); startActivity(intent);
מתאמי סנכרון
יש הבדלים קלים בלבד באופן שבו אפליקציה ומתאמת סנכרון ניגשים לספק היומן:
- מתאם סנכרון צריך לציין שהוא מתאם סנכרון על ידי הגדרה של
CALLER_IS_SYNCADAPTER
לערךtrue
. - מתאם סנכרון צריך לספק
ACCOUNT_NAME
ו-ACCOUNT_TYPE
כפרמטרים של שאילתות ב-URI. - למתאם סנכרון יש גישת כתיבה ליותר עמודות מאשר לאפליקציה או לווידג'ט.
לדוגמה, אפליקציה יכולה לשנות רק כמה מאפיינים של יומן, כמו השם, שם התצוגה, הגדרת החשיפה והאפשרות לסנכרן את היומן. לשם השוואה, מתאם סנכרון יכול לגשת לא רק לעמודות האלה, אלא לעמודות רבות אחרות,
כגון צבע היומן, אזור זמן, רמת גישה, מיקום וכן הלאה.
עם זאת, מתאם סנכרון מוגבל ל-
ACCOUNT_NAME
ול-ACCOUNT_TYPE
שצוינו בו.
הנה שיטה עוזרת שניתן להשתמש בה כדי להחזיר URI לשימוש עם מתאם סנכרון:
Kotlin
fun asSyncAdapter(uri: Uri, account: String, accountType: String): Uri { return uri.buildUpon() .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true") .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, account) .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, accountType).build() }
Java
static Uri asSyncAdapter(Uri uri, String account, String accountType) { return uri.buildUpon() .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true") .appendQueryParameter(Calendars.ACCOUNT_NAME, account) .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); }