Greetings Everyone. I'm new to Android development...
# multiplatform
a
Greetings Everyone. I'm new to Android development, and this is my first time working on a Koltin multiplatform project. My project structure is given below-
Copy code
project-root
├── android
│   ├── src
│   │   └── main
│   │       ├── java
│   │       │   └── org.example.application
│   │       │       └── MainActivity.kt (only being used to set app name and icon, invoking Application.kt inside setContent)
│   │       ├── res
│   │       │   ├── drawable
│   │       │   │   └── icon.png
│   │       │   ├── values
│   │       │   └── strings.xml (contains app name)
│   │       └── AndroidManifest.xml
│   └── build.gradle.kts
├── common
│   ├── src
│   │   ├── androidMain
│   │   │   ├── kotlin
│   │   │   │   └── org.example.application
│   │   │   │       └── common
│   │   │   │           └── Platform.kt (for actual functions)
│   │   │   └── AndroidManifest.xml
│   │   ├── commonMain
│   │   │   ├── kotlin
│   │   │   │   └── org.example.application
│   │   │   │       └── common
│   │   │   │           └── Platform.kt (for expect functions)
│   │   │   └── resources (marked as resources root)
│   │   │       └── drawable (contains images to be displayed in app)
│   │   │           ├── a.png
│   │   │           ├── b.png
│   │   │           └── c.png
│   │   ├── desktopMain
│   │   │   └── kotlin
│   │   │       └── org.example.application
│   │   │           └── common
│   │   │               └── Platform.kt (for actual functions)
│   │   └── jvmAndAndroidMain
│   │       └── kotlin
│   │           └── org.example.application
│   │               └── view
│   │                   └── Application.kt (contains composable functions to be displayed in app)
│   └── build.gradle.kts
├── desktop
│   ├── src
│   │   └── jvmMain
│   │       ├── kotlin
│   │       │   └── org.example.application
│   │       │       └── Main.kt (only being used to set app name and icon, invoking Application.kt inside Window)
│   │       └── resources
│   │           └── icon.png
│   └── build.gradle.kts
└── build.gradle.kts
Now I'm facing the following problems- 1. First and foremost, I'm not sure if my project structure is correct. I've referred to an example project by JetBrains as there were no tutorials available. So, can someone please tell me if I need to restructure it. 2. I'm using compose UI toolkit for developing frontend for android as well as desktop. Now, I want to display some images in the app which are located inside common/src/commonMain/resources/drawable. When I use
Image(painter = painterResource("drawable/${imgName}.png"))
where,
imgName
is a variable containing the image name (a/b/c) inside common/src/jvmAndAndroidMain/kotlin/org.example.application/view/Application.kt, It works fine when I run the desktop application but on android it gives an error insisting me to use resource id instead of resource path. 3. I need to use app data so while writing platform specific code for Android inside common/src/androidMain/kotlin/org.example.application/Platform.kt when I try to implement SharedPreferences using this-
val sharedPreferences = context.getSharedPreferences("app_data", Context.MODE_PRIVATE)
, it is asking for a context. What I've tried till now- For Problem #2 Even when I try to use
Image(painter = painterResource(R.drawable.imgName)
it is unable to locate the images. For Problem #3 I tried to declare a companion object inside MainActivity class located at android/src/main/java/org.example.application/MainActivity.kt like this-
Copy code
init {
        instance = this
    }

companion object {
    private var instance: MainActivity? = null

    fun applicationContext() : Context {
        return instance!!.applicationContext
    }
}
But when I try to import MainActivity in common/src/androidMain/kotlin/org.example.application/common/Platform.kt, it gives a circular import error. Thank you for your time. Any help would be appreciated :)
j
1. The project structure looks mostly correct. I'm assuming strings.xml is actually under android/src/main/res/values and that's just a typo where you have it up a level. 2. Make sure you're using the
painterResource()
function from the
org.jetbrains.compose.resources
package, which takes a string parameter. You'll need
implementation(compose.components.resources)
as a dependency in your Android app module, or expose it from your shared module as
api(compose.components.resources)
. You also need to
@OptIn(ExperimentalResourceApi::class)
to use it. 3. Definitely don't retain a reference to a
Context
like this. This will leak memory! The shared module should not depend on your app modules. Instead, use a dependency injection pattern to pass the
Context
reference into the class or function that requires it. If this is a view model, use the `AndroidViewModel` class. You might look at using Koin for dependency injection.
#3 managing references to application contexts is one of the more challenging aspects of Android development, so it's good to learn how to do this properly early on.
a
@Jeff Lockhart Thank you for your help 🙇 #1 Yes, the strings.xml file is located inside the android/src/main/res/values directory, I made a typo here. #2 I tried adding the
compose.components.resources
dependency in my gradle file first for android app module and then the shared module but it gives unresolved reference error for
components
in both the cases. #3 Thanks for providing the resources for me to study from. I'll surely go through them.
j
Are you applying the compose plugin?
Copy code
plugins {
    ...
    id("org.jetbrains.compose")
}
You also need to opt in to use the dependency. See example here.
a
Yes, I had already applied the plugin id("org.jetbrains.compose") but even then, when I add this-
Copy code
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
implementation(compose.components.resources)
to my gradle file under common module I get this error- "Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public val TaskContainer.components: TaskProvider<ComponentReport> defined in org.gradle.kotlin.dsl"
j
What version of compose are you using?
a
@Jeff Lockhart I'm currently using Compose v1.1.0
j
Note the example I linked is using the latest version 1.4.0.