צ'אט בזמן אמת ללא פיגור הוא כאב ראש נפוץ עבור צוותי מובייל. WebSocket לא מוגדר כראוי, חיבור מחדש לא יציב, דליפות טוקן—אלה בעיות טיפוסיות שאנו רואים במהלך ביקורות. ה-SDK של Stream Chat פותר אותן, אך דורש הגדרה נכונה. עם 5 שנות ניסיון ו-20+ פרויקטי צ'אט, מתוכם 8 שהשתמשו ב-Stream Chat, אנו מבטיחים יציבות גם בחיבורים חלשים. בואו נעבור על האינטגרציה מאפס, ונקפוץ על ה"Hello World" מהתיעוד.
Stream Chat שונה מ-SendBird מבחינה ארכיטקטונית: ה-API שלו בנוי על מודל מונחה אירועים (WebSocket + מצב מונחה אירועים), וה-SDK מספק רכיבי SwiftUI/Compose מוכנים עם התאמה אישית עמוקה באמצעות subclassing ו-view factories. גודל הבינארי קטן יותר: iOS ~8 MB, Android AAR ~6 MB. ראינו לעיתים קרובות ש-SendBird מציע יותר חופש, אך Stream Chat מהיר יותר לאינטגרציה—חיסכון של עד 40% בזמן על ההתקנה הראשונית.
| קריטריונים | Stream Chat | SendBird |
|---|---|---|
| גודל SDK (iOS) | ~8 MB | ~12 MB |
| מודל API | מונחה אירועים (WebSocket) | REST + WebSocket |
| רכיבי UI מוכנים | SwiftUI, Compose, UIKit | UIKit, SwiftUI (לא כולם) |
| מטמון לא מקוון | CoreData / Room (מובנה) | נדרשת הגדרה ידנית |
| מחיר (רמה בסיסית) | $0.1/חודש לכל MAU | $0.2/חודש לכל MAU |
למה Stream Chat חוסך עד 40% מזמן הפיתוח?
רכיבי UI מוכנים מכסים 80% מההתנהגות. ה-20% הנותרים הם התאמה אישית באמצעות ViewFactory. זה מהיר יותר מאשר כתיבת צ'אט משלך מאפס עם UIKit/Compose. UI מותאם אישית מלא הגיוני רק כאשר מערכות העיצוב אינן תואמות.
אתחול וניהול טוקנים
Stream משתמש ב-JWT. הלקוח אף פעם לא מייצר טוקן בעצמו—רק השרת האחורי שלך דרך Stream Chat SDK. בשרת האחורי, הטוקן נוצר באמצעות stream_chat.create_token(user_id) (Python/Node SDK). בלקוח:
// iOS
let client = ChatClient(config: ChatClientConfig(apiKeyString: "YOUR_KEY"))
let token = try Token(rawValue: "eyJ...")
client.connectUser(userInfo: .init(id: userId), token: token) { error in
...
} // Android
val client = ChatClient.Builder("YOUR_KEY", context).build()
client.connectUser(User(id = userId), token).enqueue { result -> ... }חידוש טוקן: ה-SDK של Stream קורא ל-// iOS let client = ChatClient(config: ChatClientConfig(apiKeyString: "YOUR_KEY")) let token = try Token(rawValue: "eyJ...") client.connectUser(userInfo: .init(id: userId), token: token) { error in ... } כאשר הטוקן פג. יישם את // Android val client = ChatClient.Builder("YOUR_KEY", context).build() client.connectUser(User(id = userId), token).enqueue { result -> ... } (iOS: מבוסס TokenProvider, Android: ממשק TokenProvider)—שם, בצע בקשה ל-API שלך והחזר טוקן חדש. ללא זה, המשתמש יתנתק לאחר TTL של הטוקן.
איך ליצור ערוצים ולהירשם לאירועים?
Stream משתמש בשילוב closure כדי לזהות ערוצים. הסוגים הם TokenProvider, type:id, messaging, livestream, team—הם משפיעים על הרשאות ברירת המחדל.
// iOS: получить или создать канал 1-на-1
let channelId = ChannelId(type: .messaging, id: "user1_user2")
let controller = client.channelController(
createChannelWithId: channelId,
members: [userId, targetId],
isCurrentUserMember: true
)
controller.synchronize { error in
...
}commerce הוא הקריאה המרכזית. היא מביאה היסטוריה, נרשמת לאירועים בזמן אמת, ומסנכרנת את המצב המקומי. ללא זה, הערוץ נוצר אך אירועים לא מגיעים. באנדרואיד, זה מקביל דרך gaming.
איך להגדיר התראות push?
Stream משתמש בספק התראות משלו על גבי APNs/FCM. רישום:
// iOS — после получения APNs токена chatClient.currentUserController().addDevice(.apns(token: deviceToken)) // Android
FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
client.addDevice(Device(token = token, pushProvider = PushProvider.FIREBASE)).enqueue()
}Stream שולח אוטומטית התראות על הודעות חדשות בערוצים שהמשתמש חבר בהם. בלוח הבקרה, הגדר תבניות התראה. Deeplink—באמצעות טיפול ב-// iOS: получить или создать канал 1-на-1 let channelId = ChannelId(type: .messaging, id: "user1_user2") let controller = client.channelController( createChannelWithId: channelId, members: [userId, targetId], isCurrentUserMember: true ) controller.synchronize { error in ... } (iOS) או synchronize() (Android).
התאמה אישית של UI: שמירה על פונקציונליות
Stream מספק client.channel(channelType, channelId).create(memberIds), // iOS — после получения APNs токена chatClient.currentUserController().addDevice(.apns(token: deviceToken)) , // Android FirebaseMessaging.getInstance().token.addOnSuccessListener { token -> client.addDevice(Device(token = token, pushProvider = PushProvider.FIREBASE)).enqueue() } מהחבילה CKNNotificationInfo. ההתאמה האישית נעשית דרך RemoteMessage.data:
class CustomViewFactory: DefaultViewFactory {
func makeMessageAvatarView(for userInfo: UserAvatarData) -> some View {
// Ваш кастомный аватар
CustomAvatarView(imageUrl: userInfo.imageURL)
}
}
Utils.shared.viewFactory = CustomViewFactory()זה נקי יותר מאשר UI מותאם אישית מלא—80% מההתנהגות (החלקות, תגובות, שרשורים) מגיעה בחינם, אתה רק מתאים את המראה. UI מותאם אישית מלא הגיוני רק אם העיצוב אינו תואם למודל הרכיבים של Stream. לאנדרואיד, זה דומה: ChatChannelView ו-MessageListView ב-XML או Compose, התאמה אישית דרך MessageComposerView ו-StreamChatSwiftUI.
מטמון לא מקוון וחיבור מחדש
SDK של iOS משתמש ב-CoreData מתחת למכסה המנוע, Android משתמש ב-Room. זה מופעל אוטומטית כאשר ViewFactory בתצורה (true כברירת מחדל). כאשר הרשת משוחזרת, ה-SDK מסנכרן אוטומטית אירועים שהוחמצו באמצעות מנגנון בדיקת הבריאות של WebSocket.
מה כלול ביישום?
אנו מתעדים כל שלב ומשאירים לך קוד עובד. להלן השלבים ולוחות הזמנים.
| שלב | משך |
|---|---|
| רישום אפליקציית Stream והגדרת מפתח | יום אחד |
| יישום נקודת קצה לטוקן בשרת האחורי | יום אחד |
| אינטגרציית SDK (iOS/Android/Flutter) | 1–2 ימים |
| בחירה בין רכיבים ו-UI מותאם אישית | 0.5 יום |
| הגדרת התראות push ו-deep linking | יום אחד |
| בדיקת תרחישי חיבור מחדש/לא מקוון | יום אחד |
| תיעוד והעברת קוד | 0.5 יום |
לוחות זמנים ושלבים הבאים
עם רכיבי StreamChatSwiftUI/StreamChatUI מוכנים—3–4 ימים. UI מותאם אישית מלא על Core SDK—6–8 ימים. התמחור אישי. צור קשר לביקורת של היישום הנוכחי שלך או הזמן אינטגרציה סוהר—אנו מבטיחים יציבות ותמיכה לאחר המסירה.
דוגמאות ViewFactory ל-iOS
אתה יכול להתאים אישית לא רק את התמונה אלא גם צבעי הודעות, גופנים ופריסה. רשימה מלאה של שיטות class CustomViewFactory: DefaultViewFactory { func makeMessageAvatarView(for userInfo: UserAvatarData) -> some View { // Ваш кастомный аватар CustomAvatarView(imageUrl: userInfo.imageURL) } } Utils.shared.viewFactory = CustomViewFactory() מתוארת בתיעוד של Stream.







