Repository: matomo-org/matomo-sdk-android Branch: master Commit: b11fe80f16e9 Files: 105 Total size: 369.1 KB Directory structure: gitextract_u8aen19b/ ├── .github/ │ ├── dependabot.yml │ ├── pull_request_template.md │ ├── release.yml │ └── workflows/ │ ├── pull-request-ci.yml │ ├── release.yml │ └── update-gradle-wrapper.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── exampleapp/ │ ├── README.md │ ├── build.gradle │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── org/ │ │ └── matomo/ │ │ └── demo/ │ │ └── SmokeTest.kt │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── org/ │ │ └── matomo/ │ │ └── demo/ │ │ ├── DemoActivity.kt │ │ ├── DemoApp.kt │ │ └── SettingsActivity.java │ └── res/ │ ├── layout/ │ │ ├── activity_demo.xml │ │ └── activity_settings.xml │ ├── menu/ │ │ └── demo.xml │ ├── values/ │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── values-w820dp/ │ └── dimens.xml ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── settings.gradle └── tracker/ ├── build.gradle ├── lint.xml └── src/ ├── main/ │ ├── AndroidManifest.xml │ └── java/ │ └── org/ │ └── matomo/ │ └── sdk/ │ ├── LegacySettingsPorter.kt │ ├── Matomo.kt │ ├── QueryParams.java │ ├── TrackMe.java │ ├── Tracker.java │ ├── TrackerBuilder.java │ ├── dispatcher/ │ │ ├── DefaultDispatcher.kt │ │ ├── DefaultDispatcherFactory.kt │ │ ├── DefaultPacketSender.kt │ │ ├── DispatchMode.java │ │ ├── Dispatcher.java │ │ ├── DispatcherFactory.kt │ │ ├── Event.java │ │ ├── EventCache.java │ │ ├── EventDiskCache.java │ │ ├── Packet.java │ │ ├── PacketFactory.java │ │ └── PacketSender.kt │ ├── extra/ │ │ ├── CustomDimension.java │ │ ├── CustomVariables.java │ │ ├── DimensionQueue.java │ │ ├── DownloadTracker.java │ │ ├── EcommerceItems.java │ │ ├── InstallReferrerReceiver.java │ │ ├── MatomoApplication.java │ │ ├── MatomoExceptionHandler.java │ │ └── TrackHelper.java │ └── tools/ │ ├── ActivityHelper.java │ ├── BuildInfo.java │ ├── Checksum.java │ ├── Connectivity.java │ ├── CurrencyFormatter.java │ ├── DeviceHelper.java │ ├── PropertySource.java │ └── UrlHelper.java └── test/ └── java/ ├── org/ │ └── matomo/ │ └── sdk/ │ ├── LegacySettingsPorterTest.java │ ├── MatomoTest.java │ ├── TrackMeTest.java │ ├── TrackerBuilderTest.java │ ├── TrackerTest.java │ ├── dispatcher/ │ │ ├── DefaultDispatcherTest.java │ │ ├── DefaultPacketSenderTest.java │ │ ├── EventCacheTest.java │ │ ├── EventDiskCacheTest.java │ │ ├── EventTest.java │ │ ├── PacketFactoryTest.java │ │ └── PacketTest.java │ ├── extra/ │ │ ├── CustomDimensionTest.java │ │ ├── CustomVariablesTest.java │ │ ├── DimensionQueueTest.java │ │ ├── DownloadTrackerTest.java │ │ ├── EcommerceItemsTest.java │ │ ├── InstallReferrerReceiverTest.java │ │ ├── MatomoApplicationTest.java │ │ └── TrackHelperTest.java │ └── tools/ │ ├── BuildInfoTest.kt │ ├── ChecksumTest.kt │ ├── ConnectivityTest.kt │ ├── CurrencyFormatterTest.kt │ ├── DeviceHelperTest.kt │ └── PropertySourceTest.kt └── testhelpers/ ├── BaseTest.kt ├── DefaultTestCase.kt ├── FullEnvTestLifeCycle.kt ├── FullEnvTestRunner.kt ├── JUnitTree.kt ├── MatomoTestApplication.kt ├── QueryHashMap.kt ├── TestActivity.kt ├── TestHelper.kt └── TestPreferences.kt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/dependabot.yml ================================================ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "gradle" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "daily" - package-ecosystem: "github-actions" directory: "/" # Location of package manifests schedule: interval: "weekly" ================================================ FILE: .github/pull_request_template.md ================================================ ================================================ FILE: .github/release.yml ================================================ changelog: exclude: labels: - ignore-for-release authors: - someuser categories: - title: Breaking Changes 🛠 labels: - breaking-change - title: Exciting New Features 🎉 labels: - enhancement - title: Dependencies labels: - dependencies - title: Espresso test labels: - Espresso - title: Pipeline labels: - pipeline - title: Other Changes labels: - "*" ================================================ FILE: .github/workflows/pull-request-ci.yml ================================================ name: PullRequest on: push: branches: - master pull_request: env: BRANCH_NAME: ${{ github.head_ref || github.ref_name }} jobs: env-job: runs-on: ubuntu-latest outputs: modified-branch-name: ${{ steps.env.outputs.MODIFIED_BRANCH_NAME }} name: Modify branch name steps: - name: Sets MODIFIED_BRANCH_NAME id: env env: name: "${{env.BRANCH_NAME}}" run: | echo "MODIFIED_BRANCH_NAME=${name//\//-}" >> ${GITHUB_OUTPUT} cat ${GITHUB_OUTPUT} buildTest: name: Build & Unit-Tests runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ ubuntu-latest ] steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 - name: Set up JDK uses: actions/setup-java@v5 with: distribution: 'adopt' java-version: 17 - uses: gradle/actions/wrapper-validation@v6 - name: Build project run: ./gradlew assembleDebug - name: Run tests run: ./gradlew test - name: Jacoco run: ./gradlew :tracker:jacocoTestReport --no-daemon - name: Codecov run: bash <(curl -s https://codecov.io/bash) Check: name: Check runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ ubuntu-latest ] needs: - env-job steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 - name: Install JDK uses: actions/setup-java@v5 with: distribution: 'adopt' java-version: 17 - name: Code checks run: ./gradlew check - name: Archive Lint report uses: actions/upload-artifact@v7 if: ${{ always() }} with: name: Matomo-Lint-${{ needs.env-job.outputs.modified-branch-name }} path: tracker/build/reports/lint-results.html Espresso: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ ubuntu-latest ] api: [ 30 ] abi: [ x86_64 ] tag: [ default ] needs: - env-job steps: - name: kvm support run: | egrep -c '(vmx|svm)' /proc/cpuinfo id sudo adduser $USER kvm sudo chown -R $USER /dev/kvm id - uses: actions/checkout@v6 with: fetch-depth: 0 submodules: true - name: show envs run: | echo ${{ needs.env-job.outputs.modified-branch-name }} - name: set up JDK 17 uses: actions/setup-java@v5 with: distribution: 'adopt' java-version: 17 - name: Install Android SDK uses: hannesa2/action-android/install-sdk@0.1.16.7 - name: Run instrumentation tests uses: hannesa2/action-android/emulator-run-cmd@0.1.16.7 with: cmd: ./gradlew cAT --continue api: ${{ matrix.api }} tag: ${{ matrix.tag }} abi: ${{ matrix.abi }} cmdOptions: -noaudio -no-boot-anim -no-window -metrics-collection - name: Archive Espresso results uses: actions/upload-artifact@v7 if: ${{ always() }} with: name: matomo-Espresso-${{ needs.env-job.outputs.modified-branch-name }} path: | ./**/build/reports/androidTests/connected ./**/build/outputs !./**/build/outputs/apk ================================================ FILE: .github/workflows/release.yml ================================================ name: Release with changelog on: push: tags: - '*' jobs: release: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ ubuntu-latest ] steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 - name: Install JDK ${{ matrix.java_version }} uses: actions/setup-java@v5 with: distribution: 'adopt' java-version: 17 - name: Build project run: ./gradlew assembleRelease env: VERSION: ${{ github.ref }} - name: Get the version id: tagger uses: jimschubert/query-tag-action@v2 with: skip-unshallow: 'true' abbrev: false commit-ish: HEAD - name: Check pre-release run: | echo "tag=${{steps.tagger.outputs.tag}}" if [[ ${{ steps.tagger.outputs.tag }} == *alpha* || ${{ steps.tagger.outputs.tag }} == *beta* ]] then prerelease=true else prerelease=false fi echo "PRE_RELEASE=$prerelease" >> $GITHUB_ENV echo "prerelease=$prerelease" - name: Create Release uses: softprops/action-gh-release@v3.0.0 with: tag_name: ${{steps.tagger.outputs.tag}} name: ${{steps.tagger.outputs.tag}} prerelease: ${{ env.PRE_RELEASE }} generate_release_notes: true files: ./tracker/build/outputs/aar/tracker-release.aar env: GITHUB_TOKEN: ${{ secrets.FINE_GRAINED_PATN }} ================================================ FILE: .github/workflows/update-gradle-wrapper.yml ================================================ name: Update Gradle Wrapper on: schedule: - cron: "0 6 * * MON" jobs: update-gradle-wrapper: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Install JDK uses: actions/setup-java@v5 with: distribution: 'adopt' java-version: 17 - name: Update Gradle Wrapper uses: gradle-update/update-gradle-wrapper-action@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} set-distribution-checksum: false ================================================ FILE: .gitignore ================================================ # Gradle files .gradle/ build/ # Local configuration file (sdk path, etc) local.properties # Android Studio generated folders .navigation/ captures/ .externalNativeBuild # IntelliJ project files *.iml .idea/ # Misc .DS_Store Thumbs.db # Keystore files *.jks ================================================ FILE: LICENSE ================================================ Copyright 2018 Matomo team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Matomo team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================ Matomo SDK for Android ======================== [![](https://jitpack.io/v/matomo-org/matomo-sdk-android.svg)](https://jitpack.io/#matomo-org/matomo-sdk-android) ![Build](https://github.com/matomo-org/matomo-sdk-android/actions/workflows/pull-request-ci.yml/badge.svg) [![Codecov](https://codecov.io/gh/matomo-org/matomo-sdk-android/branch/master/graph/badge.svg)](https://codecov.io/gh/matomo-org/matomo-sdk-android?branch=master) Welcome to the [Matomo](http://matomo.org) Tracking SDK for Android. This library helps you send analytics data from Android apps to Matomo instances. Until v4 this library was known as **Piwik** Tracking SDK for Android. __Features__: * Caching and offline support * Graceful reconnection handling * WIFI-only mode * Thread-safe support for multiple trackers * Support for custom connection implementations * Complete [Matomo HTTP API](https://developer.matomo.org/api-reference/tracking-api) support * [Custom dimensions](https://matomo.org/docs/custom-dimensions/) * [Event Tracking](https://matomo.org/docs/event-tracking/) * [Content Tracking](https://matomo.org/docs/content-tracking/) * [Ecommerce](https://matomo.org/docs/ecommerce-analytics/) * Checksum based app install/upgrade tracking ## Quickstart For the not so quick start, [see here](https://github.com/matomo-org/matomo-sdk-android/wiki/Getting-started) or look at our [demo app](https://github.com/matomo-org/matomo-sdk-android/tree/master/exampleapp) * [Setup Matomo](https://matomo.org/docs/installation/) on your server. * Include the library in your app modules `build.gradle` file via [JitPack](https://jitpack.io/#matomo-org/matomo-sdk-android) ```groovy repositories { maven { url 'https://jitpack.io' } } dependencies { implementation 'com.github.matomo-org:matomo-sdk-android:' } ``` * Now you need to initialize your `Tracker`. It's recommended to store it as singleton. You can extend `MatomoApplication` or create and store a `Tracker` instance yourself: ```java import org.matomo.sdk.TrackerBuilder; public class YourApplication extends Application { private Tracker tracker; public synchronized Tracker getTracker() { if (tracker == null){ tracker = TrackerBuilder.createDefault("http://domain.tld/matomo.php", 1).build(Matomo.getInstance(this)); } return tracker; } } ``` * The `TrackHelper` class is the easiest way to submit events to your tracker: ```java // The `Tracker` instance from the previous step Tracker tracker = ((MatomoApplication) getApplication()).getTracker(); // Track a screen view TrackHelper.track().screen("/activity_main/activity_settings").title("Settings").with(tracker); // Monitor your app installs TrackHelper.track().download().with(tracker); ``` * Something not working? Check [here](https://github.com/matomo-org/matomo-sdk-android/wiki/Troubleshooting). ## License Android SDK for Matomo is released under the BSD-3 Clause license, see [LICENSE](https://github.com/matomo-org/matomo-sdk-android/blob/master/LICENSE). ================================================ FILE: build.gradle ================================================ buildscript { ext.kotlin_version = "2.2.20" repositories { google() maven { url "https://plugins.gradle.org/m2/" } maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots" } } dependencies { classpath "com.android.tools.build:gradle:8.13.0" classpath "com.mxalbert.gradle:jacoco-android:0.2.1" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() maven { url "https://plugins.gradle.org/m2/" } maven { url "https://jitpack.io" } } ext { globalMinSdkVersion = 21 globalTargetSdkVersion = 35 globalCompileSdkVersion = 35 } } ================================================ FILE: exampleapp/README.md ================================================ # Demo Application Matomo Android SDK ## Description Example of using the Matomo Tracking SDK for Android ``` ./gradlew :example:clean :example:installDebug ``` ================================================ FILE: exampleapp/build.gradle ================================================ plugins { id "com.android.application" id "kotlin-android" } android { namespace "org.matomo.demo" defaultConfig { applicationId "org.matomo.demo" minSdkVersion project.ext.globalMinSdkVersion compileSdk project.ext.globalCompileSdkVersion targetSdkVersion project.ext.globalTargetSdkVersion versionCode 2 versionName "2.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunnerArguments useTestStorageService: "true" } buildTypes { release { } } compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = "17" } } dependencies { implementation project(":tracker") implementation "androidx.appcompat:appcompat:1.7.1" implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "com.github.AppDevNext.Logcat:LogcatCoreLib:3.4" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" androidTestImplementation "androidx.test.ext:junit-ktx:1.3.0" androidTestUtil "androidx.test.services:test-services:1.6.0" androidTestImplementation "androidx.test.espresso:espresso-core:3.7.0" } ================================================ FILE: exampleapp/src/androidTest/java/org/matomo/demo/SmokeTest.kt ================================================ package org.matomo.demo import android.graphics.Bitmap import androidx.test.core.graphics.writeToTestStorage import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.captureToBitmap import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.ext.junit.rules.activityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Rule import org.junit.Test import org.junit.rules.TestName import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class SmokeTest { @get:Rule val activityScenarioRule = activityScenarioRule() @get:Rule var nameRule = TestName() @Test fun testExpand() { onView(withId(R.id.trackMainScreenViewButton)).perform(click()) onView(isRoot()) .perform(captureToBitmap { bitmap: Bitmap -> bitmap.writeToTestStorage("${javaClass.simpleName}_${nameRule.methodName}-trackMainScreenViewButton") }) onView(withId(R.id.trackDispatchNow)).perform(click()) onView(isRoot()) .perform(captureToBitmap { bitmap: Bitmap -> bitmap.writeToTestStorage("${javaClass.simpleName}_${nameRule.methodName}-trackDispatchNow") }) onView(withId(R.id.trackCustomVarsButton)).perform(click()) onView(isRoot()) .perform(captureToBitmap { bitmap: Bitmap -> bitmap.writeToTestStorage("${javaClass.simpleName}_${nameRule.methodName}-trackCustomVarsButton") }) onView(withId(R.id.raiseExceptionButton)).perform(click()) onView(isRoot()) .perform(captureToBitmap { bitmap: Bitmap -> bitmap.writeToTestStorage("${javaClass.simpleName}_${nameRule.methodName}-raiseExceptionButton") }) onView(withId(R.id.addEcommerceItemButton)).perform(click()) onView(isRoot()) .perform(captureToBitmap { bitmap: Bitmap -> bitmap.writeToTestStorage("${javaClass.simpleName}_${nameRule.methodName}-addEcommerceItemButton") }) onView(withId(R.id.trackEcommerceCartUpdateButton)).perform(click()) onView(isRoot()) .perform(captureToBitmap { bitmap: Bitmap -> bitmap.writeToTestStorage("${javaClass.simpleName}_${nameRule.methodName}-trackEcommerceCartUpdateButton") }) onView(withId(R.id.completeEcommerceOrderButton)).perform(click()) onView(isRoot()) .perform(captureToBitmap { bitmap: Bitmap -> bitmap.writeToTestStorage("${javaClass.simpleName}_${nameRule.methodName}-completeEcommerceOrderButton") }) onView(withId(R.id.trackGoalButton)).perform(click()) onView(isRoot()) .perform(captureToBitmap { bitmap: Bitmap -> bitmap.writeToTestStorage("${javaClass.simpleName}_${nameRule.methodName}-trackGoalButton") }) onView(withId(R.id.goalTextEditView)).perform(click()) onView(isRoot()) .perform(captureToBitmap { bitmap: Bitmap -> bitmap.writeToTestStorage("${javaClass.simpleName}_${nameRule.methodName}-goalTextEditView") }) } } ================================================ FILE: exampleapp/src/main/AndroidManifest.xml ================================================ ================================================ FILE: exampleapp/src/main/java/org/matomo/demo/DemoActivity.kt ================================================ /* * Android SDK for Matomo * * @link https://github.com/matomo-org/matomo-android-sdk * @license https://github.com/matomo-org/matomo-sdk-android/blob/master/LICENSE BSD-3 Clause */ package org.matomo.demo import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.View import android.widget.EditText import androidx.appcompat.app.AppCompatActivity import org.matomo.sdk.QueryParams import org.matomo.sdk.TrackMe import org.matomo.sdk.Tracker import org.matomo.sdk.extra.EcommerceItems import org.matomo.sdk.extra.MatomoApplication import org.matomo.sdk.extra.TrackHelper class DemoActivity : AppCompatActivity() { private var cartItems: Int = 0 private var items: EcommerceItems? = null private val tracker: Tracker get() = (application as MatomoApplication).tracker override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_demo) items = EcommerceItems() findViewById(R.id.trackMainScreenViewButton).setOnClickListener { v: View? -> TrackHelper.track(TrackMe().set(QueryParams.SESSION_START, 1)) .screen("/") .title("Main screen") .with(tracker) } findViewById(R.id.trackDispatchNow).setOnClickListener { v: View? -> tracker.dispatch() } findViewById(R.id.trackCustomVarsButton).setOnClickListener { v: View? -> TrackHelper.track() .screen("/custom_vars") .title("Custom Vars") .variable(1, "first", "var") .variable(2, "second", "long value") .with(tracker) } findViewById(R.id.raiseExceptionButton).setOnClickListener { v: View? -> TrackHelper.track() .exception(Exception("OnPurposeException")) .description("Crash button") .fatal(false) .with(tracker) } findViewById(R.id.trackGoalButton).setOnClickListener { v: View? -> var revenue: Float try { revenue = (findViewById(R.id.goalTextEditView) as EditText).text.toString().toInt().toFloat() } catch (e: Exception) { TrackHelper.track().exception(e).description("wrong revenue").with(tracker) revenue = 0f } TrackHelper.track().goal(1).revenue(revenue).with(tracker) } findViewById(R.id.addEcommerceItemButton).setOnClickListener { v: View? -> val skus: List = mutableListOf("00001", "00002", "00003", "00004") val names: List = mutableListOf("Silly Putty", "Fishing Rod", "Rubber Boots", "Cool Ranch Doritos") val categories: List = mutableListOf("Toys & Games", "Hunting & Fishing", "Footwear", "Grocery") val prices: List = mutableListOf(449, 3495, 2450, 250) val index = cartItems % 4 val quantity = (cartItems / 4) + 1 items!!.addItem( EcommerceItems.Item(skus[index]) .name(names[index]) .category(categories[index]) .price(prices[index]) .quantity(quantity) ) cartItems++ } findViewById(R.id.trackEcommerceCartUpdateButton).setOnClickListener { v: View? -> TrackHelper.track() .cartUpdate(8600) .items(items) .with(tracker) } findViewById(R.id.completeEcommerceOrderButton).setOnClickListener { v: View? -> TrackHelper.track() .order((10000 * Math.random()).toString(), 10000) .subTotal(1000) .tax(2000) .shipping(3000) .discount(500) .items(items) .with(tracker) } } override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.demo, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { val id = item.itemId if (id == R.id.action_settings) { val intent = Intent(this, SettingsActivity::class.java) intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) startActivity(intent) return true } return super.onOptionsItemSelected(item) } } ================================================ FILE: exampleapp/src/main/java/org/matomo/demo/DemoApp.kt ================================================ /* * Android SDK for Matomo * * @link https://github.com/matomo-org/matomo-android-sdk * @license https://github.com/matomo-org/matomo-sdk-android/blob/master/LICENSE BSD-3 Clause */ package org.matomo.demo import info.hannes.timber.DebugFormatTree import org.matomo.sdk.TrackMe import org.matomo.sdk.TrackerBuilder import org.matomo.sdk.extra.DimensionQueue import org.matomo.sdk.extra.DownloadTracker.Extra import org.matomo.sdk.extra.MatomoApplication import org.matomo.sdk.extra.TrackHelper import timber.log.Timber import timber.log.Timber.Forest.plant class DemoApp : MatomoApplication() { override fun onCreateTrackerConfig(): TrackerBuilder { return TrackerBuilder.createDefault("https://demo2.matomo.org/matomo.php", 81) } override fun onCreate() { super.onCreate() onInitTracker() } private fun onInitTracker() { // Print debug output when working on an app. plant(DebugFormatTree()) // When working on an app we don't want to skew tracking results. // getMatomo().setDryRun(BuildConfig.DEBUG); // If you want to set a specific userID other than the random UUID token, do it NOW to ensure all future actions use that token. // Changing it later will track new events as belonging to a different user. // String userEmail = ....preferences....getString // getTracker().setUserId(userEmail); // Track this app install, this will only trigger once per app version. // i.e. "http://org.matomo.demo:1/185DECB5CFE28FDB2F45887022D668B4" TrackHelper.track().download().identifier(Extra.ApkChecksum(this)).with(tracker) // Alternative: // i.e. "http://org.matomo.demo:1/com.android.vending" // getTracker().download(); val dimensionQueue = DimensionQueue(tracker) // This will be send the next time something is tracked. dimensionQueue.add(0, "test") tracker.addTrackingCallback { trackMe: TrackMe? -> Timber.i("Tracker.Callback.onTrack(%s)", trackMe) trackMe } } } ================================================ FILE: exampleapp/src/main/java/org/matomo/demo/SettingsActivity.java ================================================ /* * Android SDK for Matomo * * @link https://github.com/matomo-org/matomo-android-sdk * @license https://github.com/matomo-org/matomo-sdk-android/blob/master/LICENSE BSD-3 Clause */ package org.matomo.demo; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import org.matomo.sdk.extra.MatomoApplication; import org.matomo.sdk.extra.TrackHelper; import java.util.ArrayList; import java.util.Collections; import timber.log.Timber; public class SettingsActivity extends Activity { private void refreshUI(final Activity settingsActivity) { // auto track button Button button = findViewById(R.id.bindtoapp); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { TrackHelper.track().screens(getApplication()).with(((MatomoApplication) getApplication()).getTracker()); } }); // Dry run CheckBox dryRun = findViewById(R.id.dryRunCheckbox); dryRun.setChecked(((MatomoApplication) getApplication()).getTracker().getDryRunTarget() != null); dryRun.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ((MatomoApplication) getApplication()).getTracker().setDryRunTarget(((CheckBox) v).isChecked() ? Collections.synchronizedList(new ArrayList<>()) : null); } }); // out out CheckBox optOut = findViewById(R.id.optOutCheckbox); optOut.setChecked(((MatomoApplication) getApplication()).getTracker().isOptOut()); optOut.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ((MatomoApplication) getApplication()).getTracker().setOptOut(((CheckBox) v).isChecked()); } }); // dispatch interval EditText input = findViewById(R.id.dispatchIntervallInput); input.setText(Long.toString( ((MatomoApplication) getApplication()).getTracker().getDispatchInterval() )); input.addTextChangedListener( new TextWatcher() { @Override public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { try { int interval = Integer.parseInt(charSequence.toString().trim()); ((MatomoApplication) getApplication()).getTracker() .setDispatchInterval(interval); } catch (NumberFormatException e) { Timber.d("not a number: %s", charSequence.toString()); } } @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } @Override public void afterTextChanged(Editable editable) { } } ); //session Timeout Input input = findViewById(R.id.sessionTimeoutInput); input.setText(Long.toString( (((MatomoApplication) getApplication()).getTracker().getSessionTimeout() / 60000) )); input.addTextChangedListener( new TextWatcher() { @SuppressLint("SetTextI18n") @Override public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { try { int timeoutMin = Integer.parseInt(charSequence.toString().trim()); timeoutMin = Math.abs(timeoutMin); ((MatomoApplication) getApplication()).getTracker() .setSessionTimeout(timeoutMin * 60); } catch (NumberFormatException e) { ((EditText) settingsActivity.findViewById(R.id.sessionTimeoutInput)).setText("30"); Timber.d("not a number: %s", charSequence.toString()); } } @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { } @Override public void afterTextChanged(Editable editable) { } } ); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); refreshUI(this); } } ================================================ FILE: exampleapp/src/main/res/layout/activity_demo.xml ================================================