פיתוח ווידג'טים לאנדרואיד: RemoteViews, Glance ו-FCM

וידג'טים של Android מאבדים רלוונטיות אם הנתונים מתעדכנים לעתים רחוקות מדי — משתמשים רואים שערי מטבע או סטטוסי הזמנות מיושנים. אנחנו בונים וידג'טים עם עדכונים מהירים באמצעות RemoteViews, Glance ו-FCM, ומספקים פרויקטים סוהר מארכיטקטורה ועד פרסום. הצוות שלנו מבטיח ביצועים אמינים ותמיכה מתמשכת כך שווידג'טים תמיד מציגים מידע עדכני.

פיתוח ותמיכה בכל סוגי היישומים הניידים:

יישומים ניידים למידע ובידור
אפליקציות חדשות, משחקים, מדריכים, קטלוגים מקוונים, אפליקציות מזג אוויר, אפליקציות כושר ובריאות, אפליקציות נסיעות, אפליקציות חינוכיות, רשתות חברתיות ומסנג'רים, חידונים, בלוגים ופודקאסטים, פורומים, אגרגטורים
יישומים ניידים למסחר אלקטרוני
חנויות מקוונות, אפליקציות B2B, מרקטפלייסים, בורסות מקוונות, שירותי קאשבק, בורסות, פלטפורמות דרופשיפינג, תוכניות נאמנות, משלוחי מזון ומוצרים, מערכות תשלום.
יישומים ניידים לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, ניהול פרויקטים, כלים לצוותי מכירות, ניהול פיננסי, ניהול ייצור, ניהול לוגיסטיקה ומשלוחים, ניהול משאבי אנוש, מערכות ניטור נתונים
יישומים ניידים לשירותים אלקטרוניים
פלטפורמות מודעות מסווגות, בתי ספר מקוונים, בתי קולנוע מקוונים, פלטפורמות שירות אלקטרוניות, פלטפורמות קאשבק, אירוח וידאו, פורטלים נושאיים, פלטפורמות הזמנות ותזמון מקוונות, פלטפורמות מסחר מקוונות

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

השירותים שאנו מציעים
מציג 1 מתוך 1כל 1734 השירותים
פיתוח ווידג'טים לאנדרואיד: RemoteViews, Glance ו-FCM
בינוני
~3-5 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית מובייל עבור FEEDME
    פיתוח אפליקציית מובייל עבור FEEDME
    971
  • פיתוח אפליקציית מובייל עבור XOOMER
    פיתוח אפליקציית מובייל עבור XOOMER
    869
  • פיתוח אפליקציית מובייל עבור RHL
    פיתוח אפליקציית מובייל עבור RHL
    1289
  • פיתוח אפליקציית מובייל עבור ZIPPY
    פיתוח אפליקציית מובייל עבור ZIPPY
    1143
  • פיתוח אפליקציית מובייל עבור Affhome
    פיתוח אפליקציית מובייל עבור Affhome
    1076
  • פיתוח אפליקציית מובייל עבור חברת FLAVORS
    פיתוח אפליקציית מובייל עבור חברת FLAVORS
    677

בניתם וידג'ט שמתעדכן כל 30 דקות, אבל משתמשים מתלוננים על נתונים מיושנים. שערי מטבע משתנים כל דקה, סטטוס הזמנה צריך עדכונים בזמן אמת. המינימום הסטנדרטי של updatePeriodMillis של 30 דקות לא יספיק. הפתרון הוא להשתמש ב-WorkManager למשימות תקופתיות או בהודעות push מהשרת. יש לנו ניסיון רב בפיתוח וידג'טים לאנדרואיד, עם למעלה מ-50 פרויקטים ב-Google Play. לדוגמה, בפרויקט פלטפורמת מסחר, החלפנו עדכונים מבוססי משיכה בעדכוני push דרך FCM, והפחתנו את זמן ההשהיה מ-30 דקות ל-2 שניות. המשתמשים הבחינו בהבדל מיד. המומחיות שלנו בפיתוח וידג'טים לאנדרואיד כוללת RemoteViews, AppWidgetProvider ו-Glance ליצירת וידג'טים מלוטשים. אנחנו בונים וידג'טים בכל רמת מורכבות: מלוחות מידע ועד אוספים אינטראקטיביים עם עדכונים מיידיים. אנחנו מבטיחים יציבות ועמידה בהנחיות. קבלו ייעוץ למשימה שלכם.

איך לעדכן וידג'טים מהר יותר מ-30 דקות?

המערכת מאפשרת android:updatePeriodMillis של לא פחות מ-1800000 אלפיות שנייה. לעדכונים תכופים יותר, השתמשו ב-WorkManager עם PeriodicWorkRequest (מינימום 15 דקות, מוגדר ב-API) או ב-AlarmManager. בתוך WorkManager, קראו ל-AppWidgetManager.updateAppWidget(). לעדכוני push — FirebaseMessagingService.onMessageReceived עם קריאה ישירה ל-updateAppWidget. WorkManager מכבד אוטומטית את Doze Mode ו-Standby Buckets כדי לחסוך בסוללה. הנה השוואה בין הגישות:

שיטה מרווח מינימלי המלצה
updatePeriodMillis 30 דקות רק לנתונים בתדירות נמוכה
WorkManager 15 דקות לנתונים קבועים (מזג אוויר, שערים)
Push (FCM) מיידי לעדכונים מונעי אירועים (סטטוס הזמנה, הודעות)

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

דוגמה למימוש עדכון וידג'ט עם WorkManager
class WidgetUpdateWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {
        val widgetManager = AppWidgetManager.getInstance(applicationContext)
        val widgetIds = widgetManager.getAppWidgetIds(ComponentName(applicationContext, MyWidget::class.java))
        val views = buildRemoteViews(applicationContext)
        widgetManager.updateAppWidget(widgetIds, views)
        return Result.success()
    }
}

למה RemoteViews מגביל אינטראקטיביות?

וידג'טים של אנדרואיד רצים בתהליך של המשגר, ולכן רק RemoteViews זמינים. RemoteViews מוגבל ל-Views בסיסיים: TextView, ImageView, Button, LinearLayout, RelativeLayout, FrameLayout, GridLayout, ListView, GridView, StackView. RecyclerView, ConstraintLayout (לפני API 31), Views מותאמים אישית ו-WebView אסורים. להצגת רשימות, השתמשו ב-ListView או GridView עם RemoteViewsFactory. החל מאנדרואיד 12 (API 31), נוספו CheckBox, RadioButton ו-Switch. חשוב לציין, כל האלמנטים משתמשים ב-PendingIntent לטיפול בקליקים — assignOnClick לא עובד כי אין גישה ישירה ל-View. טעות נפוצה היא לנסות להגדיר onClickListener ישירות; זה בלתי אפשרי. השתמשו ב-class WidgetUpdateWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { val widgetManager = AppWidgetManager.getInstance(applicationContext) val widgetIds = widgetManager.getAppWidgetIds(ComponentName(applicationContext, MyWidget::class.java)) val views = buildRemoteViews(applicationContext) widgetManager.updateAppWidget(widgetIds, views) return Result.success() } } או ב-class MyGlanceWidget : GlanceAppWidget() { @Composable override fun Content() { val data = currentState<MyWidgetData>() Column(modifier = GlanceModifier.fillMaxSize().background(Color.White)) { Text(text = data.title, style = TextStyle(fontSize = 16.sp)) Button(text = "Обновить", onClick = actionRunCallback<RefreshAction>()) } } } לאוספים.

Glance: גישה דקלרטיבית

ספריית Glance מציעה תחביר דמוי Compose, שמסתיר יצירה ידנית של RemoteViews. כותבים דקלרטיבית: Column, Text, Button. Glance יוצר אוטומטית RemoteViews. זה מפחית את הסיכוי לשגיאות ומאיץ את הפיתוח. עם זאת, Glance עדיין לא תומך בכל הרכיבים: לדוגמה, LazyColumn לא זמין; השתמשו ב-Column עם מספר קבוע של שורות. ניהול מצב נעשה דרך GlanceStateDefinition ו-updateAppWidgetState. לפרויקט חדש עם minSdkVersion 23+, זו הבחירה הטובה ביותר. הנה דוגמה מינימלית:

class MyGlanceWidget : GlanceAppWidget() {
    @Composable
    override fun Content() {
        val data = currentState<MyWidgetData>()
        Column(modifier = GlanceModifier.fillMaxSize().background(Color.White)) {
            Text(text = data.title, style = TextStyle(fontSize = 16.sp))
            Button(text = "Обновить", onClick = actionRunCallback<RefreshAction>())
        }
    }
}

ספריית Glance - מאגר GitHub הרשמי

תכונה RemoteViews Glance
תחביר אימפרטיבי (XML + Java/Kotlin) דקלרטיבי (דמוי Compose)
סבירות לשגיאות גבוהה יותר נמוכה יותר
תמיכה באוספים ListView/GridView Column (מספר קבוע של שורות)
API מינימלי 17 (עם הגבלות) 23

AppWidgetProvider וטיפול בעדכונים

class MyWidget : AppWidgetProvider() { override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { appWidgetIds.forEach { widgetId -> val views = buildRemoteViews(context) appWidgetManager.updateAppWidget(widgetId, views) } } } הוא class WidgetListFactory(private val context: Context) : RemoteViewsService.RemoteViewsFactory { private var items: List<WidgetItem> = emptyList() override fun onDataSetChanged() { items = loadDataFromSharedPrefs(context) } override fun getViewAt(position: Int): RemoteViews { val item = items[position] return RemoteViews(context.packageName, R.layout.widget_list_item).apply { setTextViewText(R.id.item_title, item.title) val fillIntent = Intent().putExtra("item_id", item.id) setOnClickFillInIntent(R.id.item_container, fillIntent) } } } שמקבל עדכונים. ב-setResult(Activity.RESULT_OK, intent.putExtra(EXTRA_APPWIDGET_ID, widgetId)) , צרו RemoteViews וקראו ל-updateAppWidget(). מימוש טיפוסי:

class MyWidget : AppWidgetProvider() {
    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray
    ) {
        appWidgetIds.forEach { widgetId ->
            val views = buildRemoteViews(context)
            appWidgetManager.updateAppWidget(widgetId, views)
        }
    }
}

לווידג'טים עם נתונים מהאינטרנט, השתמשו בטוען רקע ב-onReceive או דרך WorkManager. לעולם אל תחסמו את onUpdate — זהו thread של ממשק המשתמש. טפלו בשגיאות טעינה: הציגו placeholder (לדוגמה, TextView עם "שגיאה בטעינה") ותזמנו ניסיון חוזר דרך WorkManager.

עבודה עם אוספים דרך RemoteViewsFactory

ListView או GridView בוידג'ט דורשים RemoteViewsFactory. ה-factory יוצר RemoteViews לכל פריט. קליקים על פריטים מיושמים באמצעות setOnClickFillInIntent ו-setPendingIntentTemplate. התבנית היא PendingIntent שתופעל עם נתוני מילוי. דוגמה:

class WidgetListFactory(private val context: Context) : RemoteViewsService.RemoteViewsFactory {
    private var items: List<WidgetItem> = emptyList()

    override fun onDataSetChanged() {
        items = loadDataFromSharedPrefs(context)
    }

    override fun getViewAt(position: Int): RemoteViews {
        val item = items[position]
        return RemoteViews(context.packageName, R.layout.widget_list_item).apply {
            setTextViewText(R.id.item_title, item.title)
            val fillIntent = Intent().putExtra("item_id", item.id)
            setOnClickFillInIntent(R.id.item_container, fillIntent)
        }
    }
}

חשוב: onDataSetChanged() נקרא ב-thread רקע, אבל ה-factory עצמו עשוי להיות במטמון. נקו את המטמון כשצריך.

הגדרת וידג'ט על ידי המשתמש

AppWidgetConfigure Activity נפתח כשמוסיפים את הווידג'ט. המשתמש בוחר פרמטרים (עיר, ערכת נושא, תדירות עדכון). לאחר הבחירה, חשוב לקרוא ל:

setResult(Activity.RESULT_OK, intent.putExtra(EXTRA_APPWIDGET_ID, widgetId)) 

בלי זה, הווידג'ט לא יתווסף. ב-Glance, הפעילו הגדרה דרך GlanceAppWidgetManager().startConfigureActivityIntent.

תהליך הפיתוח

  1. ניתוח דרישות: הגדרת פונקציונליות, תדירות עדכון, גדלים יעד (2x2, 4x2, 4x4).
  2. עיצוב פריסה: בחירה בין RemoteViews ל-Glance, יצירת פריסת XML או ממשק Compose.
  3. מימוש: כתיבת לוגיקת AppWidgetProvider עם WorkManager או FCM.
  4. אינטגרציית נתונים: חיבור ל-API, מסד נתונים (Room) או SharedPreferences.
  5. בדיקות: על אמולטורים ומכשירים אמיתיים, כולל Doze Mode.
  6. פרסום: הכנת מטא-דאטה, חתימת קוד, הגשה ל-Google Play.

מה כלול

  • פריסת RemoteViews מותאמת לגדלים (2x2, 4x2, 4x4).
  • AppWidgetProvider עם תמיכה בעדכונים (WorkManager, FCM).
  • מסך הגדרה אם נדרש.
  • אינטגרציה עם מסד נתונים (Room) או API רשת.
  • פרסום ב-Google Play עם מטא-דאטה, חתימת קוד והגדרת provisioning profile.
  • תיעוד וקוד מקור.

לוחות זמנים ומחירים

פיתוח וידג'ט בודד עם הגדרה ועדכונים קבועים אורך 3 עד 5 ימים. אם נדרש אוסף עם עדכוני push, עד שבוע. עלות טיפוסית: וידג'ט פשוט $800–$1500, וידג'ט מורכב עם push $2000–$4000. לקוחות חוסכים 20% מזמן הפיתוח באמצעות הגישה האופטימלית שלנו. התמחור מחושב באופן אישי: שלחו מפרט טכני להצעת מחיר. קבלו ייעוץ על ארכיטקטורה — נעזור לכם לבחור את הערימה (RemoteViews או Glance) ולהימנע מבעיות ביצועים טיפוסיות. הזמינו פיתוח וידג'ט היום — צרו קשר כדי להתחיל. בצעו אופטימיזציה לתקציב שלכם — אנו מציעים תנאים גמישים.

טעויות נפוצות בפיתוח וידג'טים

  • שימוש ב-updatePeriodMillis לנתונים שדורשים עדכונים תכופים. עברו ל-WorkManager או FCM.
  • חסימת onUpdate() עם פעולות ארוכות. העבירו את כל משימות הרקע ל-WorkManager.
  • התעלמות מ-Doze Mode: השתמשו ב-WorkManager תוך כיבוד Standby Buckets.
  • טיפול שגוי בהגדרה: אל תשכחו לקרוא ל-setResult.
  • חוסר ב-placeholders לשגיאות טעינת נתונים.

אנחנו מיישמים וידג'טים ב-Java או Kotlin, כולל פתרונות היברידיים. למעלה מ-50 פרויקטים מוצלחים מאשרים את המומחיות שלנו — עם דירוג ממוצע של 4.8 כוכבים ולמעלה מ-100,000 התקנות פעילות. צרו קשר להערכת פרויקט.