דלג לתוכן הראשי

שילוב Android SDK

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

יכולות

  • קל משקל - טביעת רגל מינימלית
  • מהיר - מותאם לביצועים
  • תמיכה במצב לא מקוון - תור אירועים מבוסס SQLite
  • ניסיונות חוזרים - השהיה מעריכית בין ניסיונות לאחר כישלון
  • שליחה באצוות - שליחה יעילה באצוות (50 אירועים / 5 שניות)
  • In-App Messaging - הודעות Native ו־HTML, 5 סוגים, עם הגבלת תדירות
  • Push Notifications - Firebase Cloud Messaging (FCM)
  • גישה ממוקדת פרטיות - תואם GDPR ומכבד הסכמת משתמש
  • Android 6.0+ - תמיכה ב־API 23+

דרישות

  • Android 6.0 (API level 23) ומעלה - הרף לאחסון מוצפן במנוחה (EncryptedSharedPreferences), וגם המינימום ש-Firebase Cloud Messaging דורש
  • Kotlin 1.9.20 ומעלה
  • Gradle 8.0 ומעלה

הגדרת SDK מקומית

לבנייה מקומית, הגדירו את נתיב ה־Android SDK בקובץ local.properties:

sdk.dir=/Users/your-user/Library/Android/sdk

לחלופין, ייצאו ANDROID_HOME/ANDROID_SDK_ROOT לפני הרצת Gradle.

התקנה

Gradle (מומלץ)

הוסיפו ל־build.gradle.kts:

ה־SDK מגיע בשני artifacts. הוסיפו אחד מהם - artifact ה־UI מכיל את הבסיס, כך שלעולם אין צורך להצהיר על שניהם:

dependencies {
// הכול, כולל הצגת הודעות In-App. התחילו כאן.
implementation("io.joryio:joryio-android-ui:1.0.0")
}
dependencies {
// מעקב, זהות ופוש בלבד - ללא הצגת In-App וללא WebView מקושר. בחרו בזה אם
// האפליקציה אינה משתמשת בהודעות In-App, או אם אתם מציגים אותן בעצמכם.
implementation("io.joryio:joryio-android:1.0.0")
}

או עם Groovy (build.gradle):

dependencies {
implementation 'io.joryio:joryio-android-ui:1.0.0'
}
איזה מהם?

joryio-android-ui תלוי ב־joryio-android, כך ששורה אחת מביאה את שניהם והם לעולם לא ייצאו מסנכרון - אתם מציינים רק גרסה אחת.

קחו את artifact הבסיס לבדו כשלאפליקציה אין שימוש בהודעות In-App, או כשסקירת אבטחה מתנגדת לכך ש־WebView יהיה בר־קישור בכלל. הודעות In-App פשוט לא יוצגו; כל השאר עובד ללא שינוי.

התחלה מהירה

1. אתחול ה־SDK

במחלקת Application:

import io.joryio.sdk.Joryio
import io.joryio.sdk.JoryioConfig

class MyApplication : Application() {
override fun onCreate() {
super.onCreate()

// Initialize with your SDK key
Joryio.initialize(
context = this,
sdkKey = "jry_sdk_android_YOUR_SDK_KEY",
apiHost = "api-eu1.joryio.com"
)
}
}
מציאת מפתח SDK

מצאו את מפתח ה־SDK בלוח הבקרה של Joryio תחת Settings → Apps → [האפליקציה שלכם] → SDK Keys.

2. מעקב אירועים

// Basic event
Joryio.track("Button Tapped")

// Event with properties
Joryio.track("Product Viewed", mapOf(
"product_id" to "abc123",
"product_name" to "Wireless Headphones",
"price" to 99.99,
"category" to "Electronics"
))

// Screen view
Joryio.trackScreen("ProductDetail", mapOf(
"product_id" to "abc123"
))

3. זיהוי משתמשים

// Identify a user
Joryio.identify("user-123")
Joryio.getInstance().setAttributes(mapOf(
"email" to "user@example.com",
"name" to "John Doe",
"plan" to "premium"
))

// Set attributes later
Joryio.setAttribute("last_purchase", Date())
Joryio.incrementAttribute("lifetime_value", 99.99)

// On logout
Joryio.reset()

נתוני סשן אוטומטיים

Android SDK מעשיר אירועי Session Start בנתוני מכשיר וסביבה:

  • $device_id
  • $platform (android)
  • $manufacturer / $model
  • $os_name / $os_version / $os_sdk_int
  • $app_version / $build_number
  • $package_name
  • $screen_width / $screen_height
  • $locale
  • $language / $languages
  • $timezone
  • country (ISO-3166-1 alpha-2, נגזר מה־IP בתחילת סשן)

התראות פוש

הפעילו התראות פוש עם Firebase Cloud Messaging (FCM).

1. הוספת Firebase לפרויקט

עקבו אחרי מדריך ההתקנה של Firebase כדי להוסיף Firebase לפרויקט Android שלכם.

2. הוספת Service ל־AndroidManifest.xml

<service
android:name="io.joryio.sdk.push.JoryioFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

3. הרשמה לקבלת פוש

import com.google.firebase.messaging.FirebaseMessaging

// Get FCM token and register
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isSuccessful) {
val token = task.result
Joryio.getInstance().registerPushToken(token)
}
}

// Check if push is enabled
val isEnabled = Joryio.getInstance().isPushEnabled()

// Unregister when needed
Joryio.getInstance().unregisterPush()

4. הגדרת FCM בלוח הבקרה

כדי לשלוח התראות פוש, הגדירו את פרטי Firebase:

  1. עברו אל Settings → Apps → [האפליקציה שלכם]
  2. פתחו את הגדרות התראות הפוש
  3. העלו את קובץ ה־service account JSON של Firebase (מקונסולת Firebase: ‏Project settings → Service accounts → Generate new private key)
  4. שמרו את ההגדרה

הודעות בתוך האפליקציה (In-App Messaging)

ה־SDK מציג עבורכם הודעות In-App. לאחר האתחול, קמפיינים מתאימים מופיעים מעצמם, וחשיפות, קליקים וסגירות נמדדים אוטומטית - אין מה לחבר.

אסימוני שליחה (delivery tokens)

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

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

POST /v1/in-app/track   (no deliveryToken)
{ "success": false, "error": "A delivery token is required" }

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

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

שני סוגי תוכן

כל קמפיין מגיע באחת משתי צורות תוכן, וה־SDK מציג כל אחת מהן אחרת:

תוכןמה זהאיך זה מוצג
Nativeנתונים מובנים - כותרת, טקסט, תמונה, כפתוריםView־ים אמיתיים של Android, עם ערכת הנושא, הגופנים, המצב הכהה ו־TalkBack של האפליקציה. ללא WebView.
HTMLקוד HTML, CSS ו־JavaScript שנכתב על ידי המחברWebView בתוך ההודעה.

הפעלת הודעות HTML

הודעות HTML כבויות כברירת מחדל. הודעת HTML מריצה JavaScript שנכתב על ידי המחבר בתוך האפליקציה שלכם, ולכן ההפעלה היא החלטה של צוות האפליקציה - לא משהו שמפעילים ממערכת השיווק:

val config = JoryioConfig(
allowHtmlJsInAppMessages = true // ברירת מחדל: false
)

Joryio.initialize(
context = this,
sdkKey = "jry_sdk_android_YOUR_KEY",
apiHost = "api-eu1.joryio.com",
config = config
)

השארת ההגדרה כבויה אינה מבטלת הודעות In-App. הודעות Native ימשיכו להופיע, כי הן נתונים שהאפליקציה מציירת עם ה־View־ים שלה - ללא מפרש כלשהו. קמפייני HTML מדולגים ונרשמים ללוג, כך שאפליקציה שלא הפעילה את ההגדרה לא מציגה דבר במקום להציג הודעה שבורה.

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

השתלטות על הרינדור

הגדירו callback כדי לצייר ממשק משלכם. הוא דורס את הרינדור של ה־SDK, כך שלא תקבלו שני עותקים של ההודעה:

Joryio.getInstance().setInAppMessageCallback { campaign ->
showInAppMessage(campaign) // הממשק שלכם
}

// דווחו מה קרה - ה־SDK מודד אוטומטית רק הודעות שהוא עצמו מציג
Joryio.getInstance().trackInAppImpression(campaignId, "viewed")
Joryio.getInstance().trackInAppImpression(campaignId, "clicked")
Joryio.getInstance().trackInAppImpression(campaignId, "dismissed")

רינדור ההודעות בעצמכם

ה-SDK מצייר עבורכם הודעות Native, אבל אפשר לקחת שליטה מלאה - המקבילה ל-custom view factory:

Joryio.getInstance().setInAppMessageCallback { campaign ->
// ציירו כרצונכם
}

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

השדה campaign.content כבר מוכן - ה-Liquid מרונדר בצד השרת, ושדות Native מגיעים כטקסט רגיל (אל תעבירו אותם ל-WebView; הם אינם עוברים HTML-escape, בדיוק מפני שהם מיועדים ל-TextView). דווחו על מה שהצגתם באמצעות trackInAppImpression(campaignId, "impression" | "clicked" | "dismissed").

סוגי הודעות

ה־SDK תומך ב־5 סוגי הודעות:

  1. Modal - במרכז המסך עם רקע מוצל
  2. Banner - בראש המסך
  3. Slide-Up - התראה קטנה מלמטה
  4. Full-Screen - הודעה שתופסת את כל המסך
  5. Custom - האפליקציה קובעת את המיקום

שליחת מאפיינים

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

  • ניסיון חוזר בקריאת setAttributes הבאה, בחזרה לחזית, ולפני סנכרון in-app.
  • מקובץ - רצף קריאות הופך לבקשה אחת (חלון של 800 מילישניות). כתיבה בודדת עדיין נשלחת מיד.
  • נשמר באחסון המוצפן של הפלטפורמה (iOS Keychain, Android EncryptedSharedPreferences), כך שכתיבה שורדת סגירה של התהליך. נמחק ברגע שהשרת מאשר, ומנוקה על ידי optOut() ו-wipeData().

מאפיינים משמשים גם למיקוד in-app. פרופיל השרת הוא המקור הקובע: רק כתיבות שהשרת עוד לא אישר יכולות לגבור עליו - וזה מה שמונע משני מכשירים של אותו איש קשר לחלוק על מי הוא.

אפשרויות תצורה

התאימו את התנהגות ה־SDK עם JoryioConfig:

val config = JoryioConfig(
// Initial user ID (optional)
userId = "user-123",

// Event batching
batchSize = 50, // Events per batch
flushInterval = 5000, // Flush interval in ms (5s)

// Session management
sessionTimeout = 1800000, // Session timeout in ms (30 min)
trackSessionStart = true, // Auto-track session start

// Network retry
maxRetries = 3, // Max retry attempts

// Privacy controls
optOut = false, // Opt out of tracking
trackingConsent = TrackingConsent.GRANTED,

// Debugging
enableDebug = false, // Enable debug logging
logLevel = LogLevel.ERROR // Log level
)

Joryio.initialize(
context = this,
sdkKey = "jry_sdk_android_YOUR_KEY",
apiHost = "api-eu1.joryio.com",
config = config
)

הסכמת מעקב

enum class TrackingConsent {
GRANTED, // Full tracking allowed
PENDING, // Waiting for user decision
DENIED // User denied tracking
}

רמות לוג

enum class LogLevel {
VERBOSE, // All logs
DEBUG, // Debug and above
INFO, // Info and above
WARN, // Warnings and errors
ERROR // Errors only
}

יכולות מתקדמות

ניהול סשנים

סשנים עוקבים אוטומטית אחרי מעורבות המשתמש:

// Sessions are managed automatically with 30-minute timeout
// Get current session ID
val sessionId = Joryio.getInstance().getSessionId()

// Sessions refresh on user activity

מאפייני משתמש

// Set multiple attributes
Joryio.getInstance().setAttributes(mapOf(
"age" to 28,
"city" to "San Francisco",
"premium" to true
))

// Set single attribute
Joryio.setAttribute("language", "en")

// Increment numeric attribute
Joryio.incrementAttribute("page_views", 1)
Joryio.incrementAttribute("total_spent", 29.99)

// Remove attribute
Joryio.getInstance().unsetAttribute("temporary_flag")

בקרות פרטיות

// הפסקת איסוף. נשמר במכשיר - שורד הפעלה מחדש של האפליקציה.
Joryio.getInstance().optOut()

// Opt back in
Joryio.getInstance().optIn()

// Check opt-out status
if Joryio.getInstance().isUserOptedOut() {
print("User has opted out")
}

// מחיקת כל מה שה-SDK שמר במכשיר הזה.
// נפרד מ-optOut(): "להפסיק לאסוף" ו"למחוק את מה שכבר נאסף" הן
// בקשות שונות. זו הפעולה שנדרשת לבקשת מחיקה. היא אינה מבטלת
// הסכמה - יש לקרוא גם ל-optOut() אם זו הכוונה.
Joryio.getInstance().wipeData()

// Get identity info
val (userId, anonymousId) = Joryio.getInstance().getIdentity()
println("User: ${userId ?: "anonymous"}, Anonymous ID: $anonymousId")

מה בדיוק עושה optOut():

מפסיק איסוףכן - track, identify ו-setAttributes הופכים ללא-פעולה
שורד הפעלה מחדשכן - הדגל נשמר במכשיר ונקרא לפני כל איסוף
מוחק את מה שכבר בתורכן - אירועים בתור וכתיבות מאפיינים שלא אושרו נמחקים, לא נשלחים מאוחר יותר
מעדכן את השרתכן - מאפיין פרופיל אחד אחרון $tracking_opted_out, מאמץ מיטבי, נשלח בזמן שעוד מותר לשלוח
מוחק מידע שמורלא - יש להשתמש ב-wipeData()

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

ריקון תור ידני

// Flush events immediately
Joryio.flush()

// Useful before app termination
override fun onDestroy() {
super.onDestroy()
Joryio.flush()
}

שיטות עבודה מומלצות

1. אתחול מוקדם

אתחלו במחלקת Application:

class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Joryio.initialize(
context = this,
sdkKey = "jry_sdk_android_YOUR_KEY",
apiHost = "api-eu1.joryio.com"
)
}
}

2. מעקב אחר מסכים

השתמשו במעקב מסכים לניווט:

override fun onResume() {
super.onResume()
Joryio.trackScreen(this::class.simpleName ?: "Unknown")
}

3. טיפול בהתנתקות

תמיד אפסו בעת יציאה:

fun logout() {
// Clear user session
clearUserSession()

// Reset SDK
Joryio.reset()
}

תיעוד API

מעקב אירועים

// Track event
Joryio.track(
eventName: String,
properties: Map<String, Any?> = emptyMap()
)

// Track screen view
Joryio.trackScreen(
screenName: String,
properties: Map<String, Any?> = emptyMap()
)

// Flush events immediately
Joryio.flush()

זהות משתמש

// Identify user
Joryio.identify(
userId: String
)

// Set attributes
Joryio.getInstance().setAttributes(
attributes: UserAttributes
)

// Alias user
Joryio.alias(userId: String)

// Reset user (logout)
Joryio.reset()

// Get IDs
Joryio.getInstance().getAnonymousId(): String
Joryio.getInstance().getUserId(): String?
Joryio.getInstance().getSessionId(): String

הודעות בתוך האפליקציה

// Set message callback
Joryio.getInstance().setInAppMessageCallback { campaign ->
// Handle message display
}

// Track impressions
Joryio.getInstance().trackInAppImpression(
campaignId: String,
action: String
)

התראות פוש

// Register token
Joryio.getInstance().registerPushToken(token: String)

// Check status
Joryio.getInstance().isPushEnabled(): Boolean

// Unregister
Joryio.getInstance().unregisterPush()

פתרון תקלות

אירועים לא מופיעים

  1. ודאו שמפתח ה־SDK נכון: jry_sdk_android_*
  2. הפעילו יומני ניפוי שגיאות: enableDebug = true
  3. בדקו logcat לשגיאות
  4. ודאו הרשאות רשת ב־manifest
  5. קראו flush() לשליחה מיידית

פוש לא עובד

  1. ודאו ש־Firebase הוגדר כראוי
  2. בדקו שקובץ ה־service account JSON של Firebase הועלה ללוח הבקרה
  3. ודאו שטוקן המכשיר נרשם
  4. בדקו דרך Firebase Console קודם

שגיאות בנייה

  1. ודאו מינימום SDK גרסה 23
  2. בצעו Sync לתלויות Gradle
  3. נקו ובנו מחדש את הפרויקט

מעקב מסחר אלקטרוני

Android SDK כולל מעקב מובנה אחר מסחר אלקטרוני לאירועי מוצרים, עגלה, תשלום והזמנות. ראו את מדריך מעקב המסחר האלקטרוני המשותף לכל ה-SDKs לתיעוד המלא עם דוגמאות Kotlin.

ממשקי בדיקה ואבחון

שתי קבוצות, וההבדל ביניהן חשוב.

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

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

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

מתודהעל מה היא עונה
getQueueSize()כמה אירועים ממתינים לשליחה?
currentApiEndpoint / lastTransportErrorמול איזה שרת אנחנו עובדים, והאם הקריאה האחרונה נכשלה?

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

צעדים הבאים