Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modularise core module #1133

Merged
merged 1 commit into from
Jul 23, 2024
Merged
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
1 change: 1 addition & 0 deletions embrace-android-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ dependencies {
compileOnly(libs.opentelemetry.api)
compileOnly(libs.opentelemetry.semconv)
compileOnly(libs.opentelemetry.semconv.incubating)
compileOnly(libs.lifecycle.common.java8)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import android.content.res.Resources
* Interface for retrieving identifiers and strings from the app's [android.content.res.Resources] object. This can be used
* instead of directly accessing resources through the [Context] so we can more easily fake things during tests.
*/
internal interface AndroidResourcesService {
fun getIdentifier(name: String?, defType: String?, defPackage: String?): Int
public interface AndroidResourcesService {
public fun getIdentifier(name: String?, defType: String?, defPackage: String?): Int

@Throws(Resources.NotFoundException::class)
fun getString(id: Int): String
public fun getString(id: Int): String
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@ import android.content.res.Resources
/**
* Specifies the application ID and build ID.
*/
internal class BuildInfo internal constructor(
public class BuildInfo(
/**
* The ID of the particular build, generated at compile-time.
*/
val buildId: String?,
public val buildId: String?,

/**
* The BuildType name of the particular build, extracted at compile-time.
*/
val buildType: String?,
public val buildType: String?,

/**
* The Flavor name of the particular build, extracted at compile-time.
*/
val buildFlavor: String?
public val buildFlavor: String?
) {

internal companion object {
const val BUILD_INFO_BUILD_ID: String = "emb_build_id"
const val BUILD_INFO_BUILD_TYPE: String = "emb_build_type"
const val BUILD_INFO_BUILD_FLAVOR: String = "emb_build_flavor"
public companion object {
public const val BUILD_INFO_BUILD_ID: String = "emb_build_id"
public const val BUILD_INFO_BUILD_TYPE: String = "emb_build_type"
public const val BUILD_INFO_BUILD_FLAVOR: String = "emb_build_flavor"
private const val RES_TYPE_STRING = "string"

/**
Expand All @@ -35,7 +35,7 @@ internal class BuildInfo internal constructor(
* @return the build information
*/
@JvmStatic
fun fromResources(resources: AndroidResourcesService, packageName: String): BuildInfo {
public fun fromResources(resources: AndroidResourcesService, packageName: String): BuildInfo {
return BuildInfo(
getBuildResource(resources, packageName, BUILD_INFO_BUILD_ID),
getBuildResource(resources, packageName, BUILD_INFO_BUILD_TYPE),
Expand All @@ -46,7 +46,7 @@ internal class BuildInfo internal constructor(
/**
* Given a build property name and a build property type, retrieves the embrace build resource value.
*/
fun getBuildResource(
public fun getBuildResource(
resources: AndroidResourcesService,
packageName: String,
buildProperty: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import android.content.Context
/**
* Implementation used in production that just defers to the given [Context]
*/
internal class EmbraceAndroidResourcesService(private val context: Context) : AndroidResourcesService {
public class EmbraceAndroidResourcesService(private val context: Context) :
AndroidResourcesService {
@SuppressLint("DiscouragedApi")
override fun getIdentifier(name: String?, defType: String?, defPackage: String?): Int =
context.resources.getIdentifier(name, defType, defPackage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,34 @@ import io.embrace.android.embracesdk.internal.registry.ServiceRegistry
* Contains a core set of dependencies that are required by most services/classes in the SDK.
* This includes a reference to the application context, a clock, logger, etc...
*/
internal interface CoreModule {
public interface CoreModule {

/**
* Reference to the context. This will always return the application context so won't leak.
*/
val context: Context
public val context: Context

val packageInfo: PackageInfo
public val packageInfo: PackageInfo

/**
* Reference to the current application.
*/
val application: Application
public val application: Application

/**
* Returns the service registry. This is used to register services that need to be closed
*/
val serviceRegistry: ServiceRegistry
public val serviceRegistry: ServiceRegistry

/**
* Returns an service to retrieve Android resources
*/
val resources: AndroidResourcesService
public val resources: AndroidResourcesService

/**
* Whether the application is a debug build
*/
val isDebug: Boolean
public val isDebug: Boolean

val buildInfo: BuildInfo
public val buildInfo: BuildInfo
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import io.embrace.android.embracesdk.internal.capture.metadata.AppEnvironment
import io.embrace.android.embracesdk.internal.logging.EmbLogger
import io.embrace.android.embracesdk.internal.registry.ServiceRegistry

internal class CoreModuleImpl(
public class CoreModuleImpl(
ctx: Context,
logger: EmbLogger
) : CoreModule {
Expand All @@ -26,7 +26,7 @@ internal class CoreModuleImpl(
override val packageInfo: PackageInfo
get() = context.packageManager.getPackageInfo(context.packageName, 0)

override val application by singleton { context as Application }
override val application: Application by singleton { context as Application }

override val serviceRegistry: ServiceRegistry by singleton {
ServiceRegistry(logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import kotlin.reflect.KProperty
/**
* How the dependency should be loaded.
*/
internal enum class LoadType {
public enum class LoadType {

/**
* The dependency should be instantiated as soon as the module is created.
Expand All @@ -27,7 +27,7 @@ internal enum class LoadType {
* Lazy dependencies are NOT thread safe. It is assumed that dependencies will always be
* initialized on the same thread.
*/
internal inline fun <reified T> singleton(
public inline fun <reified T> singleton(
loadType: LoadType = LoadType.LAZY,
noinline provider: Provider<T>
): ReadOnlyProperty<Any?, T> = SingletonDelegate(loadType, provider)
Expand All @@ -36,16 +36,16 @@ internal inline fun <reified T> singleton(
* Creates a new dependency from a factory, meaning every time this property is called a
* new object will be created.
*/
internal inline fun <reified T> factory(
public inline fun <reified T> factory(
noinline provider: Provider<T>
): ReadOnlyProperty<Any?, T> = FactoryDelegate(provider)

internal class FactoryDelegate<T>(private inline val provider: Provider<T>) : ReadOnlyProperty<Any?, T> {
public class FactoryDelegate<T>(private inline val provider: Provider<T>) : ReadOnlyProperty<Any?, T> {

override fun getValue(thisRef: Any?, property: KProperty<*>): T = provider()
}

internal class SingletonDelegate<T>(
public class SingletonDelegate<T>(
loadType: LoadType,
provider: Provider<T>
) : ReadOnlyProperty<Any?, T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import java.util.concurrent.atomic.AtomicBoolean
* An object that holds all of the services that are registered with the SDK. This makes it simpler
* to remember to set callbacks & close resources when creating a new service.
*/
internal class ServiceRegistry(
public class ServiceRegistry(
private val logger: EmbLogger
) : Closeable {

Expand All @@ -24,17 +24,23 @@ internal class ServiceRegistry(

// lazy init avoids type checks at startup until absolutely necessary.
// once these variables are initialized, no further services should be registered.
val closeables by lazy { registry.filterIsInstance<Closeable>() }
val memoryCleanerListeners by lazy { registry.filterIsInstance<MemoryCleanerListener>() }
val processStateListeners by lazy { registry.filterIsInstance<ProcessStateListener>() }
val activityLifecycleListeners by lazy { registry.filterIsInstance<ActivityLifecycleListener>() }
val startupListener by lazy { registry.filterIsInstance<StartupListener>() }
public val closeables: List<Closeable> by lazy { registry.filterIsInstance<Closeable>() }
public val memoryCleanerListeners: List<MemoryCleanerListener> by lazy {
registry.filterIsInstance<MemoryCleanerListener>()
}
public val processStateListeners: List<ProcessStateListener> by lazy {
registry.filterIsInstance<ProcessStateListener>()
}
public val activityLifecycleListeners: List<ActivityLifecycleListener> by lazy {
registry.filterIsInstance<ActivityLifecycleListener>()
}
public val startupListener: List<StartupListener> by lazy { registry.filterIsInstance<StartupListener>() }

fun registerServices(vararg services: Any?) {
public fun registerServices(vararg services: Any?) {
services.forEach(::registerService)
}

fun registerService(service: Any?) {
public fun registerService(service: Any?) {
if (initialized.get()) {
error("Cannot register a service - already initialized.")
}
Expand All @@ -44,35 +50,35 @@ internal class ServiceRegistry(
registry.add(service)
}

fun closeRegistration() {
public fun closeRegistration() {
initialized.set(true)
}

fun registerActivityListeners(processStateService: ProcessStateService) = processStateListeners.forEachSafe(
public fun registerActivityListeners(processStateService: ProcessStateService): Unit = processStateListeners.forEachSafe(
"Failed to register activity listener",
processStateService::addListener
)

fun registerActivityLifecycleListeners(activityLifecycleTracker: ActivityTracker) = activityLifecycleListeners.forEachSafe(
public fun registerActivityLifecycleListeners(activityLifecycleTracker: ActivityTracker): Unit = activityLifecycleListeners.forEachSafe(
"Failed to register activity lifecycle listener",
activityLifecycleTracker::addListener
)

fun registerMemoryCleanerListeners(memoryCleanerService: MemoryCleanerService) =
public fun registerMemoryCleanerListeners(memoryCleanerService: MemoryCleanerService): Unit =
memoryCleanerListeners.forEachSafe(
"Failed to register memory cleaner listener",
memoryCleanerService::addListener
)

fun registerStartupListener(activityLifecycleTracker: ActivityTracker) =
public fun registerStartupListener(activityLifecycleTracker: ActivityTracker): Unit =
startupListener.forEachSafe(
"Failed to register application lifecycle listener",
activityLifecycleTracker::addStartupListener
)

// close all of the services in one go. this prevents someone creating a Closeable service
// but forgetting to close it.
override fun close() = closeables.forEachSafe("Failed to close service", Closeable::close)
override fun close(): Unit = closeables.forEachSafe("Failed to close service", Closeable::close)

private fun <T> List<T>.forEachSafe(msg: String, action: (t: T) -> Unit) {
this.forEach {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.embrace.android.embracesdk.internal.session

internal interface MemoryCleanerListener {
public interface MemoryCleanerListener {

/**
* Clean collections in memory when a session ends occurs.
*/
fun cleanCollections()
public fun cleanCollections()
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package io.embrace.android.embracesdk.internal.session

internal interface MemoryCleanerService {
public interface MemoryCleanerService {

/**
* Adds an observer of the end session event.
*
* @param listener the observer to register
*/
fun addListener(listener: MemoryCleanerListener)
public fun addListener(listener: MemoryCleanerListener)

/**
* Flush collections from each service which has collections in memory.
*/
fun cleanServicesCollections()
public fun cleanServicesCollections()
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,27 @@ import android.os.Bundle
/**
* Listener implemented by observers of the [ActivityLifecycleTracker].
*/
internal interface ActivityLifecycleListener {
public interface ActivityLifecycleListener {

/**
* Triggered when an activity is opened.
*
* @param activity details of the activity
*/
fun onView(activity: Activity) {}
public fun onView(activity: Activity) {}

/**
* Triggered when an activity is closed.
*
* @param activity details of the activity
*/
fun onViewClose(activity: Activity) {}
public fun onViewClose(activity: Activity) {}

/**
* Triggered when an activity is created.
*
* @param activity the activity
* @param bundle the bundle
*/
fun onActivityCreated(activity: Activity, bundle: Bundle?) {}
public fun onActivityCreated(activity: Activity, bundle: Bundle?) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import java.io.Closeable
/**
* Tracks activity lifecycle events.
*/
internal interface ActivityTracker : Application.ActivityLifecycleCallbacks, Closeable {
public interface ActivityTracker : Application.ActivityLifecycleCallbacks, Closeable {

/**
* Gets the activity which is currently in the foreground.
*
* @return an optional of the activity currently in the foreground
*/
val foregroundActivity: Activity?
public val foregroundActivity: Activity?

fun addListener(listener: ActivityLifecycleListener)
public fun addListener(listener: ActivityLifecycleListener)

fun addStartupListener(listener: StartupListener)
public fun addStartupListener(listener: StartupListener)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package io.embrace.android.embracesdk.internal.session.lifecycle
/**
* Listener implemented by observers of the [ProcessStateService].
*/
internal interface ProcessStateListener {
public interface ProcessStateListener {

/**
* Triggered when the app enters the background.
*/
fun onBackground(timestamp: Long) {}
public fun onBackground(timestamp: Long) {}

/**
* Triggered when the application is resumed.
*
* @param coldStart whether this is a cold start
* @param timestamp the timestamp at which the application entered the foreground
*/
fun onForeground(coldStart: Boolean, timestamp: Long) {}
public fun onForeground(coldStart: Boolean, timestamp: Long) {}
}
Loading
Loading