Skip to content

Commit 84551e2

Browse files
committed
feat: update errorHandler to support the same classes as in Swift.
1 parent d37d2d3 commit 84551e2

File tree

47 files changed

+992
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+992
-1
lines changed

changes-for-exceptions-2.diff

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
diff --git a/core/src/main/java/com/segment/analytics/kotlin/core/Analytics.kt b/core/src/main/java/com/segment/analytics/kotlin/core/Analytics.kt
2+
index 3c6ddbc..cf70141 100644
3+
--- a/core/src/main/java/com/segment/analytics/kotlin/core/Analytics.kt
4+
+++ b/core/src/main/java/com/segment/analytics/kotlin/core/Analytics.kt
5+
@@ -8,6 +8,7 @@ import com.segment.analytics.kotlin.core.platform.plugins.ContextPlugin
6+
import com.segment.analytics.kotlin.core.platform.plugins.SegmentDestination
7+
import com.segment.analytics.kotlin.core.platform.plugins.StartupQueue
8+
import com.segment.analytics.kotlin.core.platform.plugins.UserInfoPlugin
9+
+import com.segment.analytics.kotlin.core.platform.plugins.logger.LogFilterKind
10+
import com.segment.analytics.kotlin.core.platform.plugins.logger.SegmentLog
11+
import com.segment.analytics.kotlin.core.platform.plugins.logger.log
12+
import kotlinx.coroutines.*
13+
@@ -83,7 +84,10 @@ open class Analytics protected constructor(
14+
constructor(configuration: Configuration) : this(configuration,
15+
object : CoroutineConfiguration {
16+
override val store = Store()
17+
- override val analyticsScope = CoroutineScope(SupervisorJob())
18+
+ val exceptionHandler =
19+
+ CoroutineExceptionHandler { coroutineContext, throwable ->
20+
+ println("From: $coroutineContext caught: $throwable") }
21+
+ override val analyticsScope = CoroutineScope(SupervisorJob()+exceptionHandler)
22+
override val analyticsDispatcher : CloseableCoroutineDispatcher =
23+
Executors.newCachedThreadPool().asCoroutineDispatcher()
24+
override val networkIODispatcher : CloseableCoroutineDispatcher =
25+
@@ -95,28 +99,32 @@ open class Analytics protected constructor(
26+
// This function provides a default state to the store & attaches the storage and store instances
27+
// Initiates the initial call to settings and adds default system plugins
28+
internal fun build() {
29+
- // because startup queue doesn't depend on a state, we can add it first
30+
- add(SegmentLog())
31+
- add(StartupQueue())
32+
- add(ContextPlugin())
33+
- add(UserInfoPlugin())
34+
-
35+
- // Setup store
36+
- analyticsScope.launch(analyticsDispatcher) {
37+
- store.also {
38+
- // load memory with initial value
39+
- it.provide(userInfo)
40+
- it.provide(System.defaultState(configuration, storage))
41+
+ try {
42+
+ // because startup queue doesn't depend on a state, we can add it first
43+
+ add(SegmentLog())
44+
+ add(StartupQueue())
45+
+ add(ContextPlugin())
46+
+ add(UserInfoPlugin())
47+
+
48+
+ // Setup store
49+
+ analyticsScope.launch(analyticsDispatcher) {
50+
+ store.also {
51+
+ // load memory with initial value
52+
+ it.provide(userInfo)
53+
+ it.provide(System.defaultState(configuration, storage))
54+
+
55+
+ // subscribe to store after state is provided
56+
+ storage.subscribeToStore()
57+
+ }
58+
59+
- // subscribe to store after state is provided
60+
- storage.subscribeToStore()
61+
- }
62+
+ if (configuration.autoAddSegmentDestination) {
63+
+ add(SegmentDestination())
64+
+ }
65+
66+
- if (configuration.autoAddSegmentDestination) {
67+
- add(SegmentDestination())
68+
+ checkSettings()
69+
}
70+
-
71+
- checkSettings()
72+
+ } catch (t: Throwable) {
73+
+ log("Error calling build(): $t")
74+
}
75+
}
76+
77+
diff --git a/core/src/main/java/com/segment/analytics/kotlin/core/platform/Mediator.kt b/core/src/main/java/com/segment/analytics/kotlin/core/platform/Mediator.kt
78+
index c3a599c..55bfecf 100644
79+
--- a/core/src/main/java/com/segment/analytics/kotlin/core/platform/Mediator.kt
80+
+++ b/core/src/main/java/com/segment/analytics/kotlin/core/platform/Mediator.kt
81+
@@ -51,7 +51,11 @@ internal class Mediator(internal var plugins: CopyOnWriteArrayList<Plugin> = Cop
82+
83+
fun applyClosure(closure: (Plugin) -> Unit) {
84+
plugins.forEach {
85+
- closure(it)
86+
+ try {
87+
+ closure(it)
88+
+ } catch (t : Throwable) {
89+
+ Analytics.segmentLog("Caught Exception while applying closure to plugin: $it: $t")
90+
+ }
91+
}
92+
}
93+

copy-aar-to-migration-sample.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#! /bin/sh
2+
3+
cp android/build/outputs/aar/android-debug.aar ../sample-java-to-kotlin-migration/app/libs/analytics-kotlin.aar && echo "Copy successful!"

core/src/main/java/com/segment/analytics/kotlin/core/Errors.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
package com.segment.analytics.kotlin.core
22

33
import com.segment.analytics.kotlin.core.platform.plugins.logger.segmentLog
4+
sealed class AnalyticsError(): Throwable() {
5+
data class StorageUnableToCreate(override val message: String?): AnalyticsError()
6+
data class StorageUnableToWrite(override val message: String?): AnalyticsError()
7+
data class StorageUnableToRename(override val message: String?): AnalyticsError()
8+
data class StorageUnableToOpen(override val message: String?): AnalyticsError()
9+
data class StorageUnableToClose(override val message: String?): AnalyticsError()
10+
data class StorageInvalid(override val message: String?): AnalyticsError()
11+
data class StorageUnknown(override val message: String?, override val cause: Throwable?): AnalyticsError()
12+
data class NetworkUnexpectedHTTPCode(override val message: String?): AnalyticsError()
13+
data class NetworkServerLimited(override val message: String?): AnalyticsError()
14+
data class NetworkServerRejected(override val message: String?): AnalyticsError()
15+
data class NetworkUnknown(override val message: String?, override val cause: Throwable?): AnalyticsError()
16+
data class NetworkInvalidData(override val message: String?): AnalyticsError()
17+
data class JsonUnableToSerialize(override val message: String?, override val cause: Throwable?): AnalyticsError()
18+
data class JsonUnableToDeserialize(override val message: String?, override val cause: Throwable?): AnalyticsError()
19+
data class JsonUnknown(override val message: String?, override val cause: Throwable?): AnalyticsError()
20+
data class PluginError(override val message: String?, override val cause: Throwable?): AnalyticsError()
21+
data class EnrichmentError(override val message: String?): AnalyticsError()
22+
data class SettingsFetchError(override val message: String?, override val cause: Throwable?): AnalyticsError()
23+
}
424

525
/**
626
* Reports an internal error to the user-defined error handler.

core/src/main/java/com/segment/analytics/kotlin/core/Settings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ internal fun Analytics.fetchSettings(
115115
log("Fetched Settings: $settingsString")
116116
LenientJson.decodeFromString(settingsString)
117117
} catch (ex: Exception) {
118-
reportErrorWithMetrics(this, ex, "Failed to fetch settings",
118+
reportErrorWithMetrics(this, AnalyticsError.SettingsFetchError(ex.message, ex), "Failed to fetch settings",
119119
Telemetry.INVOKE_ERROR_METRIC, ex.stackTraceToString()) {
120120
it["error"] = ex.toString()
121121
it["writekey"] = writeKey
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
plugins {
2+
id 'com.android.application'
3+
id 'org.jetbrains.kotlin.android'
4+
id 'org.jetbrains.kotlin.plugin.serialization'
5+
}
6+
7+
android {
8+
namespace 'com.segment.analytics.next.kotlin_android_api21_app'
9+
compileSdk 33
10+
11+
defaultConfig {
12+
applicationId "com.segment.analytics.next.kotlin_android_api21_app"
13+
minSdk 21
14+
//noinspection ExpiredTargetSdkVersion
15+
targetSdk 33
16+
versionCode 1
17+
versionName "1.0"
18+
19+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
20+
}
21+
22+
buildTypes {
23+
release {
24+
minifyEnabled false
25+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
26+
}
27+
}
28+
compileOptions {
29+
sourceCompatibility JavaVersion.VERSION_1_8
30+
targetCompatibility JavaVersion.VERSION_1_8
31+
}
32+
kotlinOptions {
33+
jvmTarget = '1.8'
34+
}
35+
buildFeatures {
36+
viewBinding true
37+
}
38+
}
39+
40+
dependencies {
41+
42+
implementation project(':android')
43+
implementation 'androidx.core:core-ktx:1.7.0'
44+
implementation 'androidx.appcompat:appcompat:1.6.1'
45+
implementation 'com.google.android.material:material:1.6.1'
46+
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
47+
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
48+
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
49+
testImplementation 'junit:junit:4.13.2'
50+
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
51+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
52+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.segment.analytics.next.kotlin_android_api21_app
2+
3+
import androidx.test.platform.app.InstrumentationRegistry
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
5+
6+
import org.junit.Test
7+
import org.junit.runner.RunWith
8+
9+
import org.junit.Assert.*
10+
11+
/**
12+
* Instrumented test, which will execute on an Android device.
13+
*
14+
* See [testing documentation](http://d.android.com/tools/testing).
15+
*/
16+
@RunWith(AndroidJUnit4::class)
17+
class ExampleInstrumentedTest {
18+
@Test
19+
fun useAppContext() {
20+
// Context of the app under test.
21+
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22+
assertEquals("com.segment.analytics.next.kotlin_android_api21_app", appContext.packageName)
23+
}
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<uses-permission android:name="android.permission.INTERNET" />
5+
<application
6+
android:name=".SampleApplication"
7+
android:allowBackup="true"
8+
android:icon="@mipmap/ic_launcher"
9+
android:label="@string/app_name"
10+
android:supportsRtl="true"
11+
android:theme="@style/Theme.AnalyticsAndroidNext">
12+
<activity
13+
android:name=".MainActivity"
14+
android:exported="true"
15+
android:label="@string/app_name"
16+
android:theme="@style/Theme.AnalyticsAndroidNext.NoActionBar">
17+
<intent-filter>
18+
<action android:name="android.intent.action.MAIN" />
19+
20+
<category android:name="android.intent.category.LAUNCHER" />
21+
</intent-filter>
22+
</activity>
23+
</application>
24+
25+
</manifest>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.segment.analytics.next.kotlin_android_api21_app
2+
3+
import android.os.Bundle
4+
import android.util.Log
5+
import androidx.fragment.app.Fragment
6+
import android.view.LayoutInflater
7+
import android.view.View
8+
import android.view.ViewGroup
9+
import androidx.navigation.fragment.findNavController
10+
import com.segment.analytics.next.kotlin_android_api21_app.databinding.FragmentFirstBinding
11+
12+
/**
13+
* A simple [Fragment] subclass as the default destination in the navigation.
14+
*/
15+
class FirstFragment : Fragment() {
16+
17+
private val TAG = SampleApplication.TAG + "/FirstFragment"
18+
private var _binding: FragmentFirstBinding? = null
19+
20+
// This property is only valid between onCreateView and
21+
// onDestroyView.
22+
private val binding get() = _binding!!
23+
24+
override fun onCreateView(
25+
inflater: LayoutInflater, container: ViewGroup?,
26+
savedInstanceState: Bundle?
27+
): View? {
28+
29+
_binding = FragmentFirstBinding.inflate(inflater, container, false)
30+
return binding.root
31+
32+
}
33+
34+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
35+
super.onViewCreated(view, savedInstanceState)
36+
37+
binding.buttonFirst.setOnClickListener {
38+
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
39+
}
40+
41+
binding.buttonTrack.setOnClickListener {
42+
Log.d(TAG, "onViewCreated: trying to track")
43+
SampleApplication.analytics.track("test-track")
44+
}
45+
}
46+
47+
override fun onDestroyView() {
48+
super.onDestroyView()
49+
_binding = null
50+
}
51+
}

0 commit comments

Comments
 (0)