Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ compile:
./gradlew build
sudo xcode-select --switch /Applications/Xcode.app && /usr/bin/xcodebuild -version
cd ./sentry-samples/kmp-app/iosApp; pod install
cd ./sentry-samples/kmp-app-mvvm-di/iosApp; pod install
xcodebuild -workspace ./sentry-samples/kmp-app/iosApp/iosApp.xcworkspace -scheme iosApp -configuration Debug -sdk iphonesimulator -arch arm64
xcodebuild -workspace ./sentry-samples/kmp-app-mvvm-di/iosApp/iosApp.xcworkspace -scheme iosApp -configuration Debug -sdk iphonesimulator -arch arm64

# We stop gradle at the end to make sure the cache folders
# don't contain any lock files and are free to be cached.
Expand Down
57 changes: 57 additions & 0 deletions sentry-samples/kmp-app-mvvm-di/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Sentry KMP Demo App

This is a demo app for the Sentry Kotlin Multiplatform SDK that includes a native iOS app and a native Android app with shared code.

## Shared Features
- Dependency Injection with Koin
- ViewModels
- Sentry Setup

## Getting Started

### IDE

Install the [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) for Android Studio.

You can use Android Studio to run both the Android and iOS sample apps.

The android target is available as `sentry-samples.kmp-app-mvvm-di.androidApp` automatically.
The iOS target needs to be configured: add a new run configuration and select an iOS application as a new target.
You can then select the `iosApp.xcworkspace` file for the required `Xcode project file`.

### Android
- Export your `ANDROID_HOME` environment variable if you haven't done already.
- You can run `./gradlew :sentry-samples:kmp-app:androidApp:assembleDebug` to compile the Android app.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- You can run `./gradlew :sentry-samples:kmp-app:androidApp:assembleDebug` to compile the Android app.
- You can run `./gradlew :sentry-samples:kmp-app:androidApp:assembleDebug` to compile the Android app.
- You can run `xcodebuild -workspace ./sentry-samples/kmp-app-mvvm-di/iosApp/iosApp.xcworkspace -scheme iosApp -configuration Debug -sdk iphonesimulator -arch arm64` to compile the iOS app.


### iOS

#### Cocoapods
You need Cocoapods installed on your machine.

Run `export LANG=en_US.UTF-8` to avoid encoding issues.

`pod install` will automatically run through gradle if you run the iOS app through Android Studio.
However, you can still run `pod install` on the iOS folder manually if you want to make sure the pods are up to date.

#### DSYMS
First you need to have `sentry-cli` installed.

Then add the following script to your `Build Phases` in Xcode and change the `org`, `project`, `auth_token` slug placeholders accordingly:
Make sure to change the placeholders correctly, otherwise the iOS app will not run.

```shell
if which sentry-cli >/dev/null; then
export SENTRY_ORG=<org_slug>
export SENTRY_PROJECT=<project_slug>
export SENTRY_AUTH_TOKEN=<auth_token>
ERROR=$(sentry-cli upload-dif "$DWARF_DSYM_FOLDER_PATH" 2>&1 >/dev/null)
if [ ! $? -eq 0 ]; then
echo "warning: sentry-cli - $ERROR"
fi
else
echo "warning: sentry-cli not installed, download from https://github.com/getsentry/sentry-cli/releases"
fi
```

### Sentry Setup
If you need to change the `DSN` or any options you can do so in the `SentrySetup.kt` file in the `shared` module.
55 changes: 55 additions & 0 deletions sentry-samples/kmp-app-mvvm-di/androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
plugins {
id("com.android.application")
kotlin("android")
}

android {
namespace = "sentry.kmp.demo.android"
compileSdk = 33
defaultConfig {
applicationId = "sentry.kmp.demo"
minSdk = 21
targetSdk = 33
versionCode = 1
versionName = "1.0"
}
buildFeatures {
compose = true
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.0-dev-k1.8.0-33c0ad36f83"
}
}

dependencies {
implementation(rootProject.project(":sentry-samples:kmp-app-mvvm-di:shared"))
implementation("androidx.core:core-ktx:1.10.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.8.0")
implementation("androidx.activity:activity-compose:1.7.0")
implementation("androidx.lifecycle:lifecycle-runtime:2.6.1")
implementation("androidx.lifecycle:lifecycle-viewmodel:2.6.1")
implementation("androidx.navigation:navigation-compose:2.5.3")
implementation("androidx.navigation:navigation-runtime:2.5.3")
implementation("io.insert-koin:koin-android:3.2.0")
implementation("io.insert-koin:koin-core:3.2.0")
implementation("androidx.compose.compiler:compiler:1.4.0-dev-k1.8.0-33c0ad36f83")
implementation("androidx.compose.ui:ui:1.5.0-alpha02")
implementation("androidx.compose.ui:ui-tooling:1.5.0-alpha02")
implementation("androidx.compose.foundation:foundation:1.5.0-alpha02")
implementation("androidx.compose.material:material:1.5.0-alpha02")
}
21 changes: 21 additions & 0 deletions sentry-samples/kmp-app-mvvm-di/androidApp/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:name="sentry.kmp.demo.android.MainApp"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="DataExtractionRules">
<meta-data android:name="io.sentry.auto-init" android:value="false" />
<activity
android:name="sentry.kmp.demo.android.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package sentry.kmp.demo.android

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.component.KoinComponent
import sentry.kmp.demo.android.theme.Theme
import sentry.kmp.demo.android.ui.MyApp
import sentry.kmp.demo.models.AuthenticationViewModel
import sentry.kmp.demo.models.HomeViewModel

class MainActivity : ComponentActivity(), KoinComponent {

private val authenticationViewModel: AuthenticationViewModel by viewModel()
private val homeViewModel: HomeViewModel by viewModel()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Theme {
MyApp(authenticationViewModel, homeViewModel)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package sentry.kmp.demo.android

import android.app.Application
import android.content.Context
import android.util.Log
import org.koin.dsl.module
import sentry.kmp.demo.initKoin
import sentry.kmp.demo.sentry.initSentry

class MainApp : Application() {

override fun onCreate() {
super.onCreate()

initSentry(this)

initKoin(
module {
single<Context> { this@MainApp }
single {
{ Log.i("Startup", "Hello from Android/Kotlin!") }
}
}
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package sentry.kmp.demo.android.theme

import androidx.compose.ui.graphics.Color

val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package sentry.kmp.demo.android.theme

import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Shapes
import androidx.compose.ui.unit.dp

val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(4.dp),
large = RoundedCornerShape(0.dp)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package sentry.kmp.demo.android.theme

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.MaterialTheme
import androidx.compose.material.darkColors
import androidx.compose.material.lightColors
import androidx.compose.runtime.Composable

private val DarkColorPalette = darkColors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200
)

private val LightColorPalette = lightColors(
primary = Purple500,
primaryVariant = Purple700,
secondary = Teal200
)

@Composable
fun Theme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}

MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package sentry.kmp.demo.android.theme

import androidx.compose.material.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp

val Typography = Typography(
body1 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package sentry.kmp.demo.android.ui

import androidx.compose.runtime.Composable
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import sentry.kmp.demo.models.AuthenticationViewModel
import sentry.kmp.demo.models.HomeViewModel

@Composable
fun MyApp(authenticationViewModel: AuthenticationViewModel, homeViewModel: HomeViewModel) {
val navController = rememberNavController()

NavHost(
navController = navController,
startDestination = "login"
) {
composable("login") {
LoginScreen(navController, authenticationViewModel)
}
composable("home") {
HomeScreen(navController, homeViewModel)
}
}
}
Loading