RssNews is an Android application that allows users to read, favorite, and manage news articles fetched from RSS feeds. The project supports user authentication through email/password and Google Sign-In, with articles stored in Firebase Realtime Database. The application was created as part of the PRM (Mobile Programming) course at PJATK.
- User authentication via email/password and Google Sign-In
- Fetch news articles from RSS feeds
- Mark articles as read/unread
- Favorite/unfavorite articles
- Persist data using Firebase Realtime Database
- Support for local storage using SharedPreferences
- Push notifications for new articles
- Swipe to refresh for fetching new articles
- TopAppBar for category selection and account management
-
Clone the repository:
git clone https://github.com/szwedzik/rssnews.git
-
Open the project in Android Studio.
-
Build the project to install all dependencies.
-
Run the project on an Android emulator or a physical device.
- Android Studio Arctic Fox or later
- Android SDK 30 or later
- Firebase project with Realtime Database and Authentication enabled
- Google services JSON file (
google-services.json
)
- Firebase for authentication and database
- Kotlin Coroutines for asynchronous programming
- Coil for image loading
- Accompanist for swipe to refresh
-
Create a new project in the Firebase Console.
-
Enable Authentication (Email/Password and Google Sign-In).
-
Enable Realtime Database.
-
Download the
google-services.json
file and place it in theapp
directory of your project. -
Replace the placeholder in
strings.xml
with your Firebase key:<resources> <string name="app_name">RssNews</string> <string name="default_web_client_id">REPLACE_THIS_WITH_YOUR_FIREBASE_KEY</string> </resources>
We use Firebase Authentication for user login and registration.
class FirebaseAuthManager(activity: Activity) {
private val auth: FirebaseAuth = FirebaseAuth.getInstance()
private val googleSignInClient: GoogleSignInClient
init {
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(activity.getString(R.string.default_web_client_id))
.requestEmail()
.build()
googleSignInClient = GoogleSignIn.getClient(activity, gso)
}
// Other authentication methods...
}
We use RssParser to fetch and parse articles from RSS feeds.
class RssViewModel : ViewModel() {
private val rssParser: RssParser = RssParser()
fun fetchArticles(url: String) {
viewModelScope.launch {
_isRefreshing.value = true
try {
val channel = rssParser.getRssChannel(url)
val articles = channel.items.map { article ->
Article(
title = article.title ?: "",
link = article.link ?: "",
description = cleanDescription(article.description ?: ""),
imageUrl = article.image ?: null,
categories = article.categories,
pubDate = article.pubDate ?: "",
creator = article.author ?: "",
isRead = sharedPreferencesManager.isArticleRead(article.link ?: ""),
isFavorite = sharedPreferencesManager.isArticleFavorite(article.link ?: "")
)
}
_articles.value = articles
} catch (e: Exception) {
e.printStackTrace()
} finally {
_isRefreshing.value = false
}
}
}
}
Favorites are stored in Firebase Realtime Database.
class FirebaseDatabaseManager {
private val database: DatabaseReference = FirebaseDatabase.getInstance().reference
fun saveFavoriteArticle(article: Article) {
val articleId = article.link.hashCode().toString()
database.child("favorite_articles").child(articleId).setValue(article)
}
fun getFavoriteArticles(): List<Article> {
val snapshot = database.child("favorite_articles").get().await()
val articles = snapshot.children.mapNotNull { it.getValue(Article::class.java) }
return articles
}
}
Push notifications are handled using WorkManager.
class ArticleCheckWorker(appContext: Context, workerParams: WorkerParameters) : CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
// Check for new articles and send notifications
return Result.success()
}
}
The application requires the following permissions:
- INTERNET
- ACCESS_NETWORK_STATE
Permissions are requested at runtime for devices running Android M (API 23) or later.
private fun checkPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.INTERNET), REQUEST_CODE)
}
}
- Fork the repository
- Create your feature branch (git checkout -b feature/my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin feature/my-new-feature)
- Create a new Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.