Skip to content

Commit 7a89db6

Browse files
authored
Merge pull request #66 from AppDevNext/Countly
Countly
2 parents 9b3c708 + a62a85e commit 7a89db6

8 files changed

Lines changed: 221 additions & 0 deletions

File tree

LogcatCountlyLib/build.gradle

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
apply plugin: 'com.android.library'
2+
apply plugin: 'kotlin-android'
3+
apply plugin: 'kotlin-android-extensions'
4+
5+
android {
6+
compileSdkVersion propCompileSdkVersion
7+
8+
defaultConfig {
9+
versionName getTag()
10+
versionCode getGitCommitCount()
11+
12+
minSdkVersion 16
13+
project.archivesBaseName = "LogcatCountly"
14+
}
15+
16+
compileOptions {
17+
sourceCompatibility JavaVersion.VERSION_1_8
18+
targetCompatibility JavaVersion.VERSION_1_8
19+
}
20+
}
21+
22+
dependencies {
23+
api project(':LogcatCoreLib')
24+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
25+
26+
api "ly.count.android:sdk:20.04.4"
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="info.hannes.logcat.countly">
3+
4+
<application>
5+
6+
</application>
7+
8+
</manifest>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package info.hannes.countly
2+
3+
import android.annotation.SuppressLint
4+
import android.app.Activity
5+
import android.content.Context
6+
import android.content.pm.PackageManager
7+
import android.provider.Settings
8+
import info.hannes.logcat.BuildConfig
9+
import ly.count.android.sdk.Countly
10+
import ly.count.android.sdk.CountlyConfig
11+
import ly.count.android.sdk.DeviceId
12+
13+
14+
@Suppress("PrivatePropertyName")
15+
class Analytics : IAnalytics {
16+
17+
var countlyInstance: Countly = Countly.sharedInstance()
18+
private set
19+
20+
override fun isInitialized(): Boolean {
21+
return countlyInstance.isInitialized
22+
}
23+
24+
override fun recordEvent(event: String) {
25+
if (isInitialized()) {
26+
countlyInstance.events().recordEvent(event, segmentation, 1)
27+
}
28+
}
29+
30+
override fun recordError(message: String) {
31+
if (isInitialized()) {
32+
countlyInstance.crashes().recordHandledException(RuntimeException(message))
33+
}
34+
}
35+
36+
override fun recordError(throwable: Throwable) {
37+
if (isInitialized()) {
38+
countlyInstance.crashes().recordHandledException(throwable)
39+
}
40+
}
41+
42+
override fun recordWarning(message: String) {
43+
if (isInitialized()) {
44+
countlyInstance.crashes().recordHandledException(RuntimeException(message))
45+
}
46+
}
47+
48+
override fun onStart(activity: Activity?) {
49+
if (isInitialized()) {
50+
countlyInstance.onStart(activity)
51+
}
52+
}
53+
54+
override fun onStop() {
55+
if (isInitialized()) {
56+
countlyInstance.onStop()
57+
}
58+
}
59+
60+
companion object {
61+
val segmentation = mutableMapOf<String, Any>()
62+
63+
@SuppressLint("HardwareIds")
64+
fun initAnalytics(context: Context, loggingEnabled: Boolean = false, countlyKey: String, countlyHost: String) {
65+
var version = ""
66+
try {
67+
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
68+
version = pInfo.versionName
69+
} catch (ignore: PackageManager.NameNotFoundException) {
70+
}
71+
segmentation["app_version"] = version
72+
segmentation["logging_version"] = BuildConfig.VERSION_NAME
73+
74+
val config = CountlyConfig()
75+
.setAppKey(countlyKey)
76+
.setContext(context)
77+
.setDeviceId(Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID))
78+
.setIdMode(DeviceId.Type.DEVELOPER_SUPPLIED)
79+
.setServerURL(countlyHost)
80+
.setLoggingEnabled(loggingEnabled)
81+
.setViewTracking(true)
82+
.setHttpPostForced(true)
83+
.enableCrashReporting()
84+
Countly.sharedInstance().init(config)
85+
}
86+
}
87+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package info.hannes.countly
2+
3+
import android.util.Log
4+
import info.hannes.timber.DebugTree
5+
6+
class CountlyTree(private val analytics: Analytics, private val serverIgnoreToken: String? = null) : DebugTree() {
7+
8+
// some regex explanation :
9+
// $t sign to search
10+
// . any char
11+
// + minimum once
12+
// ? null or once
13+
// | or
14+
// # beginning with #
15+
// [^#] any char except #
16+
// *$ till end of line
17+
18+
// short variable to avoid lint warning "Duplicate char n inside Character class" in following line
19+
private val t = serverIgnoreToken
20+
private val regex: Regex = "$t.+?$t|$t[^$t]*$".toRegex()
21+
22+
override fun log(priority: Int, tag: String?, message: String, throwable: Throwable?) {
23+
// we ignore INFO, DEBUG and VERBOSE
24+
if (priority <= Log.INFO) {
25+
return
26+
}
27+
var localMessage = message
28+
serverIgnoreToken?.let {
29+
localMessage = regex.replace(message, "")
30+
}
31+
32+
when {
33+
throwable != null -> analytics.recordError(throwable)
34+
priority == Log.WARN -> analytics.recordEvent(localMessage)
35+
else -> analytics.recordError(localMessage)
36+
}
37+
}
38+
39+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package info.hannes.countly
2+
3+
import android.app.Activity
4+
5+
interface IAnalytics {
6+
7+
fun isInitialized(): Boolean
8+
9+
fun recordEvent(event: String)
10+
11+
fun recordWarning(message: String)
12+
13+
fun recordError(message: String)
14+
15+
fun recordError(throwable: Throwable)
16+
17+
fun onStart(activity: Activity?)
18+
19+
fun onStop()
20+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package info.hannes.logging
2+
3+
import android.app.Application
4+
import info.hannes.countly.Analytics
5+
import info.hannes.countly.CountlyTree
6+
import info.hannes.timber.DebugTree
7+
import timber.log.Timber
8+
9+
abstract class LoggingApplication(
10+
private val countlyHost: String,
11+
private val countlyKey: String,
12+
private val debugBuildType: Boolean,
13+
private val serverIgnoreToken: String? = null
14+
) : Application() {
15+
16+
override fun onCreate() {
17+
super.onCreate()
18+
val oldHandler = Thread.getDefaultUncaughtExceptionHandler()
19+
20+
Thread.setDefaultUncaughtExceptionHandler { t, e ->
21+
@Suppress("ControlFlowWithEmptyBody")
22+
Timber.e(e.cause?.also { } ?: run { e })
23+
oldHandler?.uncaughtException(t, e)
24+
}
25+
26+
setupLogging(!debugBuildType)
27+
}
28+
29+
@Suppress("MemberVisibilityCanBePrivate")
30+
protected fun setupLogging(countlyLogging: Boolean) {
31+
Timber.plant(DebugTree())
32+
if (countlyLogging) {
33+
Analytics.initAnalytics(this, countlyLogging, countlyKey, countlyHost)
34+
Timber.plant(CountlyTree(Analytics(), serverIgnoreToken))
35+
}
36+
}
37+
38+
}

sample/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ android {
3939
dependencies {
4040
implementation project(':LogcatCoreLib')
4141
implementation project(':LogcatCrashlyticLib')
42+
implementation project(':LogcatCountlyLib')
4243
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
4344
implementation "androidx.appcompat:appcompat:1.1.0"
4445
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
include ':LogcatCoreLib'
22
include ':LogcatCrashlyticLib'
3+
include ':LogcatCountlyLib'
34
include ':sample'

0 commit comments

Comments
 (0)