Skip to content

Commit

Permalink
Track analytics for a few important events (quran#1472)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmedre authored Oct 29, 2020
1 parent b5c5e0c commit e307bea
Show file tree
Hide file tree
Showing 19 changed files with 273 additions and 16 deletions.
3 changes: 2 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ android {
targetSdkVersion deps.android.build.targetSdkVersion
versionCode 3010
versionName "3.0.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "com.quran.labs.androidquran.core.QuranTestRunner"
multiDexEnabled true
}

Expand Down Expand Up @@ -151,6 +151,7 @@ dependencies {

// dagger
kapt deps.dagger.apt
kaptAndroidTest deps.dagger.apt
implementation deps.dagger.runtime

// workmanager
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.quran.labs.androidquran
package com.quran.labs.androidquran.base

import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.quran.labs.androidquran.base

import com.quran.labs.androidquran.QuranApplication
import com.quran.labs.androidquran.di.DaggerTestApplicationComponent
import com.quran.labs.androidquran.di.component.application.ApplicationComponent
import com.quran.labs.androidquran.di.module.application.ApplicationModule

class TestApplication : QuranApplication() {

override fun initializeInjector(): ApplicationComponent {
return DaggerTestApplicationComponent.builder()
.applicationModule(ApplicationModule(this))
.build()
}

override fun setupTimber() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.quran.labs.androidquran.core

import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
import com.quran.labs.androidquran.base.TestApplication

class QuranTestRunner : AndroidJUnitRunner() {

override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(cl, TestApplication::class.qualifiedName, context)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.quran.labs.androidquran.di

import com.quran.analytics.provider.AnalyticsModule
import com.quran.common.networking.NetworkModule
import com.quran.data.page.provider.QuranPageModule
import com.quran.labs.androidquran.core.worker.di.WorkerModule
import com.quran.labs.androidquran.data.QuranDataModule
import com.quran.labs.androidquran.di.component.application.ApplicationComponent
import com.quran.labs.androidquran.di.module.application.ApplicationModule
import com.quran.labs.androidquran.di.module.application.DatabaseModule
import com.quran.labs.androidquran.di.module.widgets.BookmarksWidgetUpdaterModule
import com.quran.labs.androidquran.di.quran.TestQuranActivityComponent
import dagger.Component
import javax.inject.Singleton

@Singleton
@Component(
modules = [AnalyticsModule::class,
ApplicationModule::class,
DatabaseModule::class,
NetworkModule::class,
QuranDataModule::class,
QuranPageModule::class,
WorkerModule::class,
BookmarksWidgetUpdaterModule::class]
)
interface TestApplicationComponent : ApplicationComponent {
override fun quranActivityComponentBuilder(): TestQuranActivityComponent.Builder
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.quran.labs.androidquran.di.quran

import com.quran.labs.androidquran.di.ActivityScope
import com.quran.labs.androidquran.di.component.activity.QuranActivityComponent
import dagger.Subcomponent

@ActivityScope
@Subcomponent(modules = [TestQuranActivityModule::class])
interface TestQuranActivityComponent : QuranActivityComponent {

@Subcomponent.Builder
interface Builder : QuranActivityComponent.Builder {
override fun build(): TestQuranActivityComponent
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.quran.labs.androidquran.di.quran

import com.quran.labs.androidquran.presenter.data.QuranIndexEventLogger
import dagger.Module
import dagger.Provides

@Module
class TestQuranActivityModule {

@Provides
fun bindQuranIndexEventLogger(): QuranIndexEventLogger {
return QuranIndexEventLogger { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.matcher.IntentMatchers
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.quran.labs.androidquran.BaseActivityTest
import com.quran.labs.androidquran.ui.QuranActivity
import com.quran.labs.androidquran.base.BaseActivityTest
import org.hamcrest.Matchers
import org.junit.Rule
import org.junit.Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ open class QuranApplication : MultiDexApplication() {
Timber.plant(RecordingLogTree())
}

private fun initializeInjector(): ApplicationComponent {
open fun initializeInjector(): ApplicationComponent {
return DaggerApplicationComponent.builder()
.applicationModule(ApplicationModule(this))
.build()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.quran.labs.androidquran.di.component.activity;

import com.quran.labs.androidquran.di.ActivityScope;
import com.quran.labs.androidquran.di.module.activity.QuranActivityModule;
import com.quran.labs.androidquran.ui.QuranActivity;
import dagger.Subcomponent;

@ActivityScope
@Subcomponent(modules = QuranActivityModule.class)
public interface QuranActivityComponent {
void inject(QuranActivity quranActivity);

@Subcomponent.Builder
interface Builder {
QuranActivityComponent build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.quran.labs.androidquran.data.QuranDataModule;
import com.quran.labs.androidquran.data.QuranDataProvider;
import com.quran.labs.androidquran.di.component.activity.PagerActivityComponent;
import com.quran.labs.androidquran.di.component.activity.QuranActivityComponent;
import com.quran.labs.androidquran.di.module.application.ApplicationModule;
import com.quran.labs.androidquran.di.module.application.DatabaseModule;
import com.quran.labs.androidquran.di.module.widgets.BookmarksWidgetUpdaterModule;
Expand Down Expand Up @@ -53,6 +54,7 @@
public interface ApplicationComponent {
// subcomponents
PagerActivityComponent.Builder pagerActivityComponentBuilder();
QuranActivityComponent.Builder quranActivityComponentBuilder();

// application
void inject(QuranApplication quranApplication);
Expand All @@ -65,7 +67,6 @@ public interface ApplicationComponent {
void inject(QuranDownloadService quranDownloadService);

// activities
void inject(QuranActivity quranActivity);
void inject(QuranDataActivity quranDataActivity);
void inject(QuranImportActivity quranImportActivity);
void inject(AudioManagerActivity audioManagerActivity);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.quran.labs.androidquran.di.module.activity

import com.quran.labs.androidquran.presenter.data.QuranIndexEventLogger
import com.quran.labs.androidquran.presenter.data.QuranIndexEventLoggerImpl
import dagger.Binds
import dagger.Module

@Module
interface QuranActivityModule {
@Binds
fun bindQuranIndexEventLogger(impl: QuranIndexEventLoggerImpl): QuranIndexEventLogger
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.quran.labs.androidquran.presenter.data

import com.quran.analytics.AnalyticsProvider
import com.quran.labs.androidquran.common.audio.QariItem
import com.quran.labs.androidquran.presenter.data.QuranEventLogger.AudioPlaybackSource.PAGE
import com.quran.labs.androidquran.util.QuranSettings
import dagger.Reusable
import javax.inject.Inject

@Reusable
class QuranEventLogger @Inject constructor(
private val analyticsProvider: AnalyticsProvider,
private val quranSettings: QuranSettings
) {

fun logAnalytics(isDualPages: Boolean, showingTranslations: Boolean, isSplitScreen: Boolean) {
val isLockOrientation = quranSettings.isLockOrientation
val lockingOrientation = when {
isLockOrientation && quranSettings.isLandscapeOrientation -> "landscape"
isLockOrientation -> "portrait"
else -> "no"
}

val params : Map<String, Any> = mapOf(
"mode" to getScreenMode(isDualPages, showingTranslations, isSplitScreen),
"pageType" to quranSettings.pageType,
"isNightMode" to quranSettings.isNightMode,
"isArabic" to quranSettings.isArabicNames,
"background" to if (quranSettings.useNewBackground()) "default" else "legacy",
"isLockingOrientation" to lockingOrientation,
"overlayInfo" to quranSettings.shouldOverlayPageInfo(),
"markerPopups" to quranSettings.shouldDisplayMarkerPopup(),
"navigation" to if (quranSettings.navigateWithVolumeKeys()) "with_volume" else "default",
"shouldHighlightBookmarks" to quranSettings.shouldHighlightBookmarks()
)

analyticsProvider.logEvent("quran_view", params)
}

fun logAudioPlayback(
source: AudioPlaybackSource,
qari: QariItem,
isDualPages: Boolean,
showingTranslations: Boolean,
isSplitScreen: Boolean
) {
val params : Map<String, Any> = mapOf(
"id" to qari.id,
"path" to qari.path,
"isGapless" to qari.isGapless,
"source" to if (source == PAGE) { "page" } else { "ayah" },
"mode" to getScreenMode(isDualPages, showingTranslations, isSplitScreen)
)
analyticsProvider.logEvent("audio_playback", params)
}

fun switchToTranslationMode(translations: Int) {
val params: Map<String, Any> = mutableMapOf("translations" to translations)
analyticsProvider.logEvent("switch_to_translations", params)
}

private fun getScreenMode(
isDualPages: Boolean,
showingTranslations: Boolean,
isSplitScreen: Boolean
): String {
return when {
isDualPages && showingTranslations && isSplitScreen -> "split_quran_translation"
isDualPages && showingTranslations -> "dual_translations"
isDualPages -> "dual_quran"
showingTranslations -> "translation"
else -> "quran"
}
}

enum class AudioPlaybackSource { PAGE, AYAH }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.quran.labs.androidquran.presenter.data

fun interface QuranIndexEventLogger {
fun logAnalytics()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.quran.labs.androidquran.presenter.data

import com.quran.analytics.AnalyticsProvider
import com.quran.labs.androidquran.util.QuranSettings
import dagger.Reusable
import javax.inject.Inject

@Reusable
class QuranIndexEventLoggerImpl @Inject constructor(
private val analyticsProvider: AnalyticsProvider,
private val quranSettings: QuranSettings
): QuranIndexEventLogger {

override fun logAnalytics() {
val appLocation = quranSettings.appCustomLocation
val pathType = if ("com.quran" in appLocation) { "external" } else { "sdcard" }

val params: Map<String, Any> = mapOf(
"pathType" to pathType,
"sortOrder" to quranSettings.bookmarksSortOrder,
"groupByTags" to quranSettings.bookmarksGroupedByTags,
"showRecents" to quranSettings.showRecents,
"showDate" to quranSettings.showDate
)

analyticsProvider.logEvent("quran_index_view", params)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import android.widget.ArrayAdapter;
import android.widget.Toast;

import com.quran.analytics.AnalyticsProvider;
import com.quran.data.core.QuranInfo;
import com.quran.data.model.SuraAyah;
import com.quran.labs.androidquran.HelpActivity;
Expand All @@ -52,6 +51,7 @@
import com.quran.labs.androidquran.model.translation.ArabicDatabaseUtils;
import com.quran.labs.androidquran.presenter.audio.AudioPresenter;
import com.quran.labs.androidquran.presenter.bookmark.RecentPagePresenter;
import com.quran.labs.androidquran.presenter.data.QuranEventLogger;
import com.quran.labs.androidquran.service.AudioService;
import com.quran.labs.androidquran.service.QuranDownloadService;
import com.quran.labs.androidquran.service.util.DefaultDownloadReceiver;
Expand Down Expand Up @@ -220,7 +220,7 @@ public class PagerActivity extends QuranActionBarActivity implements
@Inject QuranInfo quranInfo;
@Inject QuranFileUtils quranFileUtils;
@Inject AudioPresenter audioPresenter;
@Inject AnalyticsProvider analyticsProvider;
@Inject QuranEventLogger quranEventLogger;

private CompositeDisposable compositeDisposable;
private final CompositeDisposable foregroundDisposable = new CompositeDisposable();
Expand Down Expand Up @@ -368,7 +368,7 @@ public void onPageScrollStateChanged(int state) {

@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
int positionOffsetPixels) {
if (ayahToolBar.isShowing() && ayahToolBarPos != null) {
final int startPage = quranInfo.getPageFromSuraAyah(start.sura, start.ayah);
int barPos = quranInfo.getPositionFromPage(startPage, isDualPageVisible());
Expand Down Expand Up @@ -493,6 +493,8 @@ public void onPageSelected(int position) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
defaultNavigationBarColor = getWindow().getNavigationBarColor();
}

quranEventLogger.logAnalytics(isDualPages, showingTranslation, isSplitScreen);
}

private boolean isDualPageVisible() {
Expand Down Expand Up @@ -658,8 +660,7 @@ private void animateToolBar(boolean visible) {
public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean navigate = audioStatusBar.getCurrentMode() !=
AudioStatusBar.PLAYING_MODE
&& PreferenceManager.getDefaultSharedPreferences(this).
getBoolean(Constants.PREF_USE_VOLUME_KEY_NAV, false);
&& quranSettings.navigateWithVolumeKeys();
if (navigate && keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
return true;
Expand Down Expand Up @@ -992,6 +993,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
return true;
} else if (itemId == R.id.goto_translation) {
if (translations != null) {
quranEventLogger.switchToTranslationMode(translations.size());
switchToTranslation();
}
return true;
Expand Down Expand Up @@ -1480,6 +1482,10 @@ public void onPlayPressed() {
page = ((numberOfPagesDual - position) * 2) - 1;
}

// log the event
quranEventLogger.logAudioPlayback(QuranEventLogger.AudioPlaybackSource.PAGE,
audioStatusBar.getAudioInfo(), isDualPages, showingTranslation, isSplitScreen);

int startSura = quranDisplayData.safelyGetSuraOnPage(page);
int startAyah = quranInfo.getFirstAyahOnPage(page);
List<Integer> startingSuraList = quranInfo.getListOfSurahWithStartingOnPage(page);
Expand Down Expand Up @@ -1939,6 +1945,8 @@ public boolean onMenuItemClick(MenuItem item) {
sliderPage = slidingPagerAdapter.getPagePosition(TRANSLATION_PAGE);
break;
case R.id.cab_play_from_here:
quranEventLogger.logAudioPlayback(QuranEventLogger.AudioPlaybackSource.AYAH,
audioStatusBar.getAudioInfo(), isDualPages, showingTranslation, isSplitScreen);
playFromAyah(getCurrentPage(), start.sura, start.ayah);
toggleActionBarVisibility(true);
sliderPage = -1;
Expand Down
Loading

0 comments on commit e307bea

Please sign in to comment.