Розробка мобільного додатку для новинного агрегатора

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Розробка мобільного додатку для новинного агрегатора
Середній
від 1 тижня до 3 місяців
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Розробка мобільного додатка для новостного агрегатора

Новостний агрегатор — це не просто лента з RSS. Це персоналізований потік з десятків джерел, з offline-читанням, миттєвим пошуком та push-сповіщеннями про breaking news. Головна технічна завдача — зробити ленту чутливою при сотнях джерел та тисячах матеріалів в кешу, не убивши при цьому батарею.

Архітектура: звідки беруться новини

Три підходи до агрегації контенту:

  1. Власний краулер на бекенді — парсить RSS/Atom фіди джерел за розкладом (cron), зберігає нормалізовані статті в БД. Мобільний клієнт працює тільки з вашим API. Плюс: контроль над форматом, кешуванням, дедупліцированням. Мінус: потрібен бекенд з інфраструктурою.

  2. NewsAPI / GNews / Currents API — готові агрегатори з REST API. Швидкий старт, але платні при комерційному використанні, обмежений набір джерел.

  3. Гібридний — власний краулер для пріоритетних джерел + сторонній API як резервний канал.

Для продакшн-додатка з реальними користувачами — перший або третій варіант.

Персоналізована лента: архітектура на клієнті

Лента будується на основі підписок користувача (джерела, теги, категорії) + алгоритму ранжування.

На клієнті — пагінований список з кешуванням через Room (Android) або Core Data (iOS). Стратегія: при відкритті додатка показуємо кешовані дані миттєво, паралельно запитуємо свіжі.

// Android — Repository з NetworkBoundResource паттерном
class NewsRepository(
    private val newsApi: NewsApi,
    private val newsDao: NewsDao
) {
    fun getFeed(userId: String): Flow<Resource<List<Article>>> = networkBoundResource(
        query = { newsDao.getArticles(userId) },
        fetch = { newsApi.getFeed(userId, page = 1) },
        saveFetchResult = { articles ->
            newsDao.deleteOldArticles(olderThan = System.currentTimeMillis() - 7.days)
            newsDao.insertArticles(articles)
        },
        shouldFetch = { cached -> cached.isEmpty() || cached.first().isStale() }
    )
}

Пагінація — Paging 3 на Android, кастомна cursor-based на iOS. Offset-based (page=2&per_page=20) ломиться при вставці нових статей в початок ленти — користувач видит дублі. Cursor-based (after_id=article_12345) цього позбавлена.

Offline-читання

Offline працює через два механізми:

  • Автоматичний кеш ленти в Room/Core Data (останні N статей).
  • Ручне збереження — користувач явно додає статю в «Читати пізніше».

Для повнофункціонального offline-читання потрібно зберігати не тільки метадані, але й HTML-контент статті. Це або зберігання в БД (blob), або файлова система. HTML парситься та відображається через WKWebView (iOS) або WebView з вимкненою мережею (Android).

// iOS — збереження контенту для offline
func saveForOffline(article: Article) async throws {
    let content = try await contentParser.fetchFullText(url: article.url)
    let sanitizedHTML = HTMLSanitizer.sanitize(content, baseURL: article.url)

    let offlineArticle = OfflineArticle(
        id: article.id,
        title: article.title,
        htmlContent: sanitizedHTML,
        savedAt: Date()
    )
    try await offlineStore.save(offlineArticle)
}

Push-сповіщення про breaking news

Breaking news — сповіщення повинно прийти протягом хвилин після публікації. Схема:

  1. Бекенд краулер виявляє статю з тегом breaking або високою engagement velocity.
  2. Визначає, яким користувачам релевантна (за підписками на джерело/тему).
  3. Відправляє push через FCM/APNs з priority: high.

На клієнті — deep link в push повинна відкривати конкретну статю:

// Android — обробка deep link з push
override fun onMessageReceived(message: RemoteMessage) {
    val articleId = message.data["article_id"] ?: return
    val intent = Intent(this, ArticleActivity::class.java).apply {
        putExtra("article_id", articleId)
        flags = Intent.FLAG_ACTIVITY_NEW_TASK
    }
    // Показуємо сповіщення з PendingIntent
}

Пошук

Миттєвий пошук по локальному кешу через Room FTS (Full Text Search):

@Fts4(contentEntity = ArticleEntity::class)
@Entity(tableName = "articles_fts")
data class ArticleFts(
    @PrimaryKey @ColumnInfo(name = "rowid") val rowid: Int = 0,
    val title: String,
    val description: String
)

@Query("SELECT * FROM articles INNER JOIN articles_fts ON articles.rowid = articles_fts.rowid WHERE articles_fts MATCH :query")
fun searchArticles(query: String): Flow<List<ArticleEntity>>

FTS4/FTS5 у SQLite — пошук по всьому тексту за мілісекунди навіть на 50 000 статях.

Типові проблеми при розробці

Дедупліцірування. Одна новина у 5 різних джерел — 5 різних URL, однаковий смисл. Рішення — MinHash або SimHash на бекенді для порівняння текстового сходства. Клієнт тільки відображає дедупліцірований результат.

Зображення в ленті. Lazy loading через Glide (Android) або Kingfisher (iOS). Але 50 картинок при швидкому скролі — це 50 паралельних запитів. Потрібен prefetch з пріоритизацією: RecyclerView.Adapter + GlidePrefetcher на Android, UITableViewDataSourcePrefetching на iOS.

Час читання. Показуємо «5 хвилин читання» — рахуємо на бекенді за кількістю слів, кешуємо в метаданих статті.

Стек та терміни

Компонент iOS Android
Список UICollectionView + DiffableDataSource RecyclerView + ListAdapter
БД Core Data або SQLite.swift Room + FTS5
Зображення Kingfisher Glide
Мережа URLSession + Combine Retrofit + Coroutines
Push APNs через OneSignal FCM через OneSignal

MVP новостного агрегатора (лента, категорії, offline, пошук, push про breaking news) — від 6 до 10 тижнів залежно від кількості платформ та складності бекенда.