Skip to content
Open
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: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
57d81702cb268580c8fbbb23084aa8a069982a0e
df6ccaa5ff68ede57ae658e8b2a3af4aedeec1a8
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package app.rive.runtime.kotlin
import android.content.Context
import androidx.startup.Initializer
import app.rive.runtime.kotlin.core.Rive
import app.rive.runtime.kotlin.core.RiveInitialized

/**
* Initializes Rive; needs to be done at startup.
Expand Down Expand Up @@ -37,9 +38,9 @@ import app.rive.runtime.kotlin.core.Rive
* In fact, if you want to provide a custom renderer type you'll need to init Rive manually.
*/

class RiveInitializer : Initializer<Unit> {
override fun create(context: Context) {
return Rive.init(context)
class RiveInitializer : Initializer<RiveInitialized> {
override fun create(context: Context): RiveInitialized {
return RiveInitialized(Rive.init(context))
}

override fun dependencies(): List<Class<out Initializer<*>>> {
Expand Down
62 changes: 62 additions & 0 deletions kotlin/src/main/java/app/rive/runtime/kotlin/core/NativeLoader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package app.rive.runtime.kotlin.core

import android.content.Context
import android.os.Build
import com.getkeepsafe.relinker.ReLinker

internal object NativeLoader {

/**
* Loads specified library by name and covers edge cases.
* ReLinker is only needed for API Level < 23.
*
* @param context required for ReLinker
* @param name the name of the library to load
* @return `true` if successfully loaded
*/
fun loadLibrary(context: Context, name: String): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return loadLibrary(name)
}

val relinkerLoaded = runCatching {
ReLinker.loadLibrary(context, name)
}.isSuccess

// Ignore ReLinker result first, since it catches some exception and may not be loaded
// resulting in false-positives
// Loading twice won't work anyway so there is no problem
return loadLibrary(name) || relinkerLoaded
}

/**
* Loads specified library by name and covers edge cases.
* May fail on some API Level < 23 devices.
*
* @param name the name of the library to load
* @return `true` if successfully loaded
*/
private fun loadLibrary(name: String): Boolean {
var loaded = true

// normally it's just the name but some manufacturers mess with this
systemLoadLibrary(name) {
systemLoadLibrary("$name.so") {
systemLoadLibrary("lib$name") {
systemLoadLibrary("lib$name.so") {
loaded = false
}
}
}
}
return loaded
}

private fun systemLoadLibrary(name: String, onError: () -> Unit = { }) {
if (runCatching {
System.loadLibrary(name)
}.isFailure) {
onError()
}
}
}
11 changes: 6 additions & 5 deletions kotlin/src/main/java/app/rive/runtime/kotlin/core/Rive.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ object Rive {
* [app.rive.runtime.kotlin.RiveAnimationView][RiveAnimationView]. Defaults to
* [RendererType.Rive].
*/
fun init(context: Context, defaultRenderer: RendererType = RendererType.Rive) {
// NOTE: loadLibrary also allows us to specify a version, something we might want to take
// advantage of
ReLinker.loadLibrary(context, RIVE_ANDROID)
fun init(context: Context, defaultRenderer: RendererType = RendererType.Rive): Boolean {
val loaded = NativeLoader.loadLibrary(context, RIVE_ANDROID)
defaultRendererType = defaultRenderer
initializeCppEnvironment()
if (loaded) {
initializeCppEnvironment()
}
return loaded
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package app.rive.runtime.kotlin.core

import app.rive.runtime.kotlin.RiveInitializer

/**
* Represents the result of the [Rive] initialization.
* Only used for [RiveInitializer] to be compatible with other initializers.
*
* @property success Indicates whether the initialization was successful.
*/
data class RiveInitialized(
val success: Boolean
)