This is a complete Android implementation of a journal app using Jetpack Compose and the Adapty SDK for subscription management. The app demonstrates how to implement premium feature gating with real subscription processing.
- Free journal entry creation - Users can write and save daily journal entries
- Premium features behind paywall - History viewing requires a premium subscription
- Real subscription processing - Powered by Adapty SDK with Google Play Billing
- Native Android design - Built with Jetpack Compose following Material Design 3
- Local data persistence - Journal entries stored using Room database
Before running this project, ensure you have:
- Android Studio (Arctic Fox or later)
- Android SDK (API level 26+)
- Kotlin (1.9.0+)
- Adapty account - Sign up here
- Google Play Console account - For subscription products
git clone https://github.com/ferrousguy/Focus-Journal-Android.git
cd FocusJournal- Go to your Adapty Dashboard
- Copy your API Key from General settings
- Open
app/src/main/java/io/adapty/focusjournal/utils/AppConstants.kt - Replace
"API key goes here"with your actual Adapty API key
object AppConstants {
object Adapty {
const val API_KEY = "your_adapty_api_key_here"
const val ACCESS_LEVEL_ID = "premium"
const val PLACEMENT_ID = "on_tap_history"
}
}Configure the following in your Adapty dashboard:
- Access Level: Create an access level with ID
"premium" - Placement: Create a placement with ID
"on_tap_history" - Products: Set up your subscription products in Google Play Console and link them in Adapty
- Paywall: Configure a paywall for the placement
Open the project in Android Studio and sync Gradle files. All dependencies will be automatically downloaded.
- Connect an Android device or start an emulator
- Click Run in Android Studio or use:
./gradlew installDebugapp/src/main/java/io/adapty/focusjournal/
├── FocusJournalApplication.kt # App initialization & Adapty setup
├── MainActivity.kt # Main activity
├── data/
│ ├── dao/
│ │ └── JournalEntryDao.kt # Room database access
│ ├── database/
│ │ ├── Converters.kt # Room type converters
│ │ └── FocusJournalDatabase.kt # Room database setup
│ ├── model/
│ │ └── JournalEntry.kt # Data model
│ └── repository/
│ └── JournalRepository.kt # Data repository
├── navigation/
│ └── FocusJournalNavigation.kt # Navigation setup
├── ui/
│ ├── screen/
│ │ ├── HistoryScreen.kt # Premium history view
│ │ ├── HomeScreen.kt # Main journal entry screen
│ │ └── PaywallScreen.kt # Subscription paywall
│ └── theme/
│ ├── Color.kt # App colors
│ ├── Theme.kt # Material theme
│ └── Type.kt # Typography
├── utils/
│ └── AppConstants.kt # Configuration constants
└── viewmodel/
└── ProfileManager.kt # Subscription & data management
The Adapty SDK is initialized in FocusJournalApplication.kt:
class FocusJournalApplication : Application() {
override fun onCreate() {
super.onCreate()
Adapty.activate(this, Builder(AppConstants.Adapty.API_KEY).build())
}
}Premium status is managed in ProfileManager.kt:
val isPremium: StateFlow<Boolean> = customerProfile.map { profile ->
profile?.accessLevels?.get(AppConstants.Adapty.ACCESS_LEVEL_ID)?.let { accessLevel ->
accessLevel.isActive || accessLevel.isInGracePeriod || accessLevel.isLifetime
} ?: false
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = false
)The paywall is triggered when non-premium users try to access history:
- Placement ID:
"on_tap_history" - Access Level:
"premium" - Purchase Flow: Handled through Adapty SDK with callbacks
-
Free User Flow:
- Launch the app
- Create journal entries freely
- Tap "View History" → Paywall appears
- Purchase subscription → History unlocks
-
Premium User Flow:
- Launch the app (with active subscription)
- Create journal entries
- Tap "View History" → History view opens directly
- Create and save journal entries
- Local storage of entries
- View complete history of all journal entries
- Chronological display with timestamps
- Adapty Documentation: https://adapty.io/docs