diff --git a/CHANGELOG.md b/CHANGELOG.md index 98ccca4..fca50ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log - +- 5.7.0 + - Update Gradle to latest version to fix Proguard issues + - Location 1.0.0 + - Location tracking based on defined geofence + - New Event Attributes: + - `geofence_name` + - `geofence_transition_type` + - `location_accuracy` + - `device_last_latitude` + - `device_last_longitude` - 5.6.2 - Embed proguard-rules - All Modules - proguard-rules are now embedded in each module @@ -20,7 +29,7 @@ - 5.5.5 - Webview bug fix: disable Hardware Acceleration for Tealium webview - Install Referrer 1.1.2 - - Placement of endconnection() to more appropriate location + - Bug fix: resolve referrerClient NPE by adding `endConnection()` after establishing connection - 5.5.4 - Fixed VisitorProfile URL to default to profile provided in Tealium.Config - 5.5.3 diff --git a/Modules/Location/.gitignore b/Modules/Location/.gitignore new file mode 100644 index 0000000..1bcf832 --- /dev/null +++ b/Modules/Location/.gitignore @@ -0,0 +1,5 @@ +.idea +.gradle +*.iml +build +local.properties \ No newline at end of file diff --git a/Modules/Location/LocationSample/.gitignore b/Modules/Location/LocationSample/.gitignore new file mode 100644 index 0000000..2b75303 --- /dev/null +++ b/Modules/Location/LocationSample/.gitignore @@ -0,0 +1,13 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/Modules/Location/LocationSample/app/.gitignore b/Modules/Location/LocationSample/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/Modules/Location/LocationSample/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/Modules/Location/LocationSample/app/build.gradle b/Modules/Location/LocationSample/app/build.gradle new file mode 100644 index 0000000..d549014 --- /dev/null +++ b/Modules/Location/LocationSample/app/build.gradle @@ -0,0 +1,40 @@ +apply plugin: 'com.android.application' +apply plugin: 'com.google.gms.google-services' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.1" + defaultConfig { + applicationId "com.example.tealiumlocationdemoapp" + minSdkVersion 19 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + + // Tealium dependencies + implementation 'com.tealium:library:5.7.0' + implementation 'com.tealium:location:1.0.0' + + // Other required dependencies + runtimeOnly 'com.google.android.gms:play-services-location:17.0.0' + implementation 'com.google.firebase:firebase-messaging:20.0.0' + implementation 'com.optimizely.ab:android-sdk:2.1.0' + + // Testing dependencies + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' +} diff --git a/Modules/Location/LocationSample/app/google-services.json b/Modules/Location/LocationSample/app/google-services.json new file mode 100644 index 0000000..fb49f8d --- /dev/null +++ b/Modules/Location/LocationSample/app/google-services.json @@ -0,0 +1,3 @@ +{ + "_comment": "INSERT YOUR GOOGLE-SERVICES.JSON CONFIGURATION HERE" +} \ No newline at end of file diff --git a/Modules/Location/LocationSample/app/proguard-rules.pro b/Modules/Location/LocationSample/app/proguard-rules.pro new file mode 100644 index 0000000..6299c0b --- /dev/null +++ b/Modules/Location/LocationSample/app/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +-keep com.tealium.internal.** { + *; +} \ No newline at end of file diff --git a/Modules/Location/LocationSample/app/src/main/AndroidManifest.xml b/Modules/Location/LocationSample/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..71393a7 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Modules/Location/LocationSample/app/src/main/Assets/geofences.json b/Modules/Location/LocationSample/app/src/main/Assets/geofences.json new file mode 100644 index 0000000..98c9519 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/Assets/geofences.json @@ -0,0 +1,22 @@ +[ + { + "name": "Tealium_asset1", + "latitude": 59.4610304, + "longitude": -9.9707625, + "radius": 100, + "expire_after": -1, + "trigger_on_enter": true, + "trigger_on_exit": true, + "minimum_dwell_time": 0 + }, + { + "name": "Tealium_asset2", + "latitude": 39.9061189, + "longitude": -142.2379163, + "radius": 100, + "expire_after": -1, + "trigger_on_enter": true, + "trigger_on_exit": true, + "minimum_dwell_time": 0 + } +] \ No newline at end of file diff --git a/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/App.java b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/App.java new file mode 100644 index 0000000..1a4c568 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/App.java @@ -0,0 +1,11 @@ +package com.example.tealiumlocationdemoapp; + +import android.app.Application; + +public class App extends Application { + @Override + public void onCreate() { + super.onCreate(); + TealiumHelper.initialize(this); + } +} diff --git a/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationAssets.java b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationAssets.java new file mode 100644 index 0000000..0f592ba --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationAssets.java @@ -0,0 +1,102 @@ +package com.example.tealiumlocationdemoapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.tealium.location.TealiumLocation; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class LocationAssets extends Activity { + + private boolean mLocationShowcaseStarted = false; + private TealiumLocation mInstance; + private final String mGeofenceJsonFile = "geofences.json"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_assets); + + findViewById(R.id.location_assets_button_update) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mLocationShowcaseStarted) { + drawActiveGeofences(); + drawUsedAssets(); + } else { + showToast("Please press Start first!"); + } + } + }); + + findViewById(R.id.location_assets_button_start) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mLocationShowcaseStarted) { + startLocationShowcase(); + } else { + showToast("Showcase Already Started!"); + } + } + }); + + findViewById(R.id.location_assets_button_stop).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mLocationShowcaseStarted) { + showToast("Please press Start first!"); + } + } + }); + } + + private void startLocationShowcase() { + mLocationShowcaseStarted = true; + + Set tealiumInstances = new HashSet<>(); + tealiumInstances.add(TealiumHelper.TEALIUM_MAIN); + + mInstance = TealiumLocation.setupInstanceWithFile(this, tealiumInstances, mGeofenceJsonFile); + mInstance.startLocationUpdates(true, 5000); + drawUsedAssets(); + drawActiveGeofences(); + } + + private void drawActiveGeofences() { + List activeGeofences = mInstance.getAllGeofenceNames(); + String geofenceNames = ""; + + for (String name : activeGeofences) { + geofenceNames = geofenceNames + name + "\n"; + } + + TextView geofenceNameData = findViewById(R.id.location_assets_geofencesdata); + geofenceNameData.setText(geofenceNames); + } + + private void drawUsedAssets() { + TextView urlData = findViewById(R.id.location_assets_assetsdata); + urlData.setText(mGeofenceJsonFile); + } + + private void showToast(String message) { + Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mLocationShowcaseStarted) { + TealiumLocation.destroyInstance(); + } + } +} diff --git a/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationConfig.java b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationConfig.java new file mode 100644 index 0000000..22ad52d --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationConfig.java @@ -0,0 +1,110 @@ +package com.example.tealiumlocationdemoapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.tealium.library.Tealium; +import com.tealium.location.TealiumLocation; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class LocationConfig extends Activity { + + private Tealium.Config mTealiumConfig; + private boolean mLocationShowcaseStarted = false; + private TealiumLocation mInstance; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_config); + + findViewById(R.id.location_config_button_update) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mLocationShowcaseStarted) { + drawActiveGeofences(); + drawUsedConfig(); + } else { + showToast("Please press Start first!"); + } + } + }); + + findViewById(R.id.location_config_button_start) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mLocationShowcaseStarted) { + startLocationShowcase(); + } else { + showToast("Showcase Already Started!"); + } + } + }); + + findViewById(R.id.location_config_button_stop) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mLocationShowcaseStarted) { + showToast("Please press Start first!"); + } + } + }); + } + + private void startLocationShowcase() { + mLocationShowcaseStarted = true; + + mTealiumConfig = TealiumHelper.getConfig(); + + Set tealiumInstances = new HashSet<>(); + tealiumInstances.add(TealiumHelper.TEALIUM_MAIN); + + if (mTealiumConfig != null) { + mInstance = TealiumLocation.setupInstanceWithConfig(this, tealiumInstances, mTealiumConfig); + mInstance.startLocationUpdates(true, 5000); + drawActiveGeofences(); + drawUsedConfig(); + } else { + showToast("Error with config"); + } + } + + private void drawActiveGeofences() { + List activeGeofences = mInstance.getAllGeofenceNames(); + String geofenceNames = ""; + + for (String name : activeGeofences) { + geofenceNames = geofenceNames + name + "\n"; + } + + TextView geofenceNameData = findViewById(R.id.location_config_geofencesdata); + geofenceNameData.setText(geofenceNames); + } + + private void drawUsedConfig() { + TextView urlData = findViewById(R.id.location_config_configdata); + urlData.setText(mTealiumConfig.getAccountName()); + } + + private void showToast(String message) { + Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mLocationShowcaseStarted) { + TealiumLocation.destroyInstance(); + } + } +} diff --git a/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationGeofencing.java b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationGeofencing.java new file mode 100644 index 0000000..2ec8c9d --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationGeofencing.java @@ -0,0 +1,115 @@ +package com.example.tealiumlocationdemoapp; + +import android.app.Activity; +import android.location.Location; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.tealium.location.TealiumLocation; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class LocationGeofencing extends Activity { + + private boolean mLocationShowcaseStarted = false; + private Location mLastLocation; + private TealiumLocation mInstance; + private static final String GEOFENCES_URL = "https://tags.tiqcdn.com/dle/tealiummobile/location/geofences.json"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_geofencing); + + findViewById(R.id.location_geofencing_button_update) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mLocationShowcaseStarted) { + mLastLocation = mInstance.getLastLocation(); + drawLastLocation(); + drawActiveGeofences(); + } else { + showToast("Please press Start first!"); + } + } + }); + + findViewById(R.id.location_geofencing_button_start) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mLocationShowcaseStarted) { + startLocationShowcase(); + } else { + showToast("Showcase Already Started!"); + } + } + }); + + findViewById(R.id.location_geofencing_button_stop) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mLocationShowcaseStarted) { + mInstance.stopLocationUpdates(); + showToast("Showcase Stopped."); + } else { + showToast("Please press Start first!"); + } + } + }); + } + + private void startLocationShowcase() { + mLocationShowcaseStarted = true; + + Set tealiumInstances = new HashSet<>(); + tealiumInstances.add(TealiumHelper.TEALIUM_MAIN); + + mInstance = TealiumLocation.setupInstanceWithUrl(this, tealiumInstances, GEOFENCES_URL); + mInstance.startLocationUpdates(true, 5000); + drawLastLocation(); + drawActiveGeofences(); + } + + private void drawLastLocation() { + TextView locationData = findViewById(R.id.location_geofencing_locationdata); + + if (mLastLocation != null) { + locationData.setText("Latitude: " + mLastLocation.getLatitude() + "\nLongitude: " + mLastLocation.getLongitude()); + } else { + locationData.setText("Please Update UI"); + Toast.makeText(getApplicationContext(), "Location Updates Every 5 Seconds, Please wait a bit!", Toast.LENGTH_SHORT).show(); + } + } + + private void drawActiveGeofences() { + List activeGeofences = mInstance.getActiveGeofenceNames(); + String geofenceNames = ""; + + for (String geofence : activeGeofences) { + geofenceNames = geofenceNames + geofence + "\n"; + } + + TextView geofenceNameData = findViewById(R.id.location_geofencing_geofencesdata); + geofenceNameData.setText(geofenceNames); + } + + private void showToast(String message) { + Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mLocationShowcaseStarted) { + TealiumLocation.destroyInstance(); + } + } +} diff --git a/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationTracking.java b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationTracking.java new file mode 100644 index 0000000..daf296b --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationTracking.java @@ -0,0 +1,90 @@ +package com.example.tealiumlocationdemoapp; + +import android.app.Activity; +import android.location.Location; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.tealium.location.TealiumLocation; + +import java.util.HashSet; +import java.util.Set; + +public class LocationTracking extends Activity { + + private boolean mLocationShowcaseStarted = false; + private Location mLastLocation; + private TealiumLocation mInstance; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_location); + + findViewById(R.id.location_tracking_button_update) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mLocationShowcaseStarted) { + mLastLocation = mInstance.getLastLocation(); + drawLastLocation(); + } else { + showToast("Please press Start first!"); + } + } + }); + + findViewById(R.id.location_tracking_button_start) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mLocationShowcaseStarted) { + startLocationShowcase(); + } else { + showToast("Showcase Already Started!"); + } + } + }); + + findViewById(R.id.location_tracking_button_stop) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mLocationShowcaseStarted) { + mInstance.stopLocationUpdates(); + showToast("Showcase Stopped."); + } else { + showToast("Please press Start first!"); + } + } + }); + } + + private void startLocationShowcase() { + mLocationShowcaseStarted = true; + + Set tealiumInstances = new HashSet<>(); + tealiumInstances.add(TealiumHelper.TEALIUM_MAIN); + + mInstance = TealiumLocation.setupInstance(this, tealiumInstances); + mInstance.startLocationUpdates(true, 5000); + drawLastLocation(); + } + + private void drawLastLocation() { + TextView locationData = findViewById(R.id.location_tracking_locationdata); + + if (mLastLocation != null) { + locationData.setText("Latitude: " + mLastLocation.getLatitude() + "\nLongitude: " + mLastLocation.getLongitude()); + } else { + locationData.setText("Please Update UI"); + showToast("Location Updates Every 5 Seconds, Please wait a bit!"); + } + } + + private void showToast(String message) { + Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); + } +} diff --git a/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationUrl.java b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationUrl.java new file mode 100644 index 0000000..3f93579 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/LocationUrl.java @@ -0,0 +1,105 @@ +package com.example.tealiumlocationdemoapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.tealium.location.TealiumLocation; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class LocationUrl extends Activity { + + private boolean mLocationShowcaseStarted = false; + private TealiumLocation mInstance; + private final String mGeofenceJsonUrl = "https://tags.tiqcdn.com/dle/tealiummobile/location/geofences.json"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_url); + + findViewById(R.id.location_url_button_update) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mLocationShowcaseStarted) { + drawActiveGeofences(); + drawUsedUrl(); + } else { + showToast("Please press Start first!"); + } + } + }); + + findViewById(R.id.location_url_button_start) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mLocationShowcaseStarted) { + startLocationShowcase(); + } else { + showToast("Showcase Already Started!"); + } + } + }); + + findViewById(R.id.location_url_button_stop) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mLocationShowcaseStarted) { + showToast("Please press Start first!"); + } + } + }); + } + + private void startLocationShowcase() { + mLocationShowcaseStarted = true; + + Set tealiumInstances = new HashSet<>(); + tealiumInstances.add(TealiumHelper.TEALIUM_MAIN); + + mInstance = TealiumLocation.setupInstanceWithUrl(this, tealiumInstances, mGeofenceJsonUrl); + mInstance.startLocationUpdates(true, 5000); + drawActiveGeofences(); + drawUsedUrl(); + } + + private void drawActiveGeofences() { + List activeGeofences = mInstance.getAllGeofenceNames(); + String geofenceNames = ""; + + for (String name : activeGeofences) { + geofenceNames = geofenceNames + name + "\n"; + } + + TextView geofenceNameData = findViewById(R.id.location_url_geofencesdata); + geofenceNameData.setText(geofenceNames); + } + + private void drawUsedUrl() { + TextView urlData = findViewById(R.id.location_url_urldata); + urlData.setText(mGeofenceJsonUrl); + } + + private void showToast(String message) { + Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mLocationShowcaseStarted) { + TealiumLocation.destroyInstance(); + } + } +} + + diff --git a/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/MainActivity.java b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/MainActivity.java new file mode 100644 index 0000000..87db7b6 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/MainActivity.java @@ -0,0 +1,97 @@ +package com.example.tealiumlocationdemoapp; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.view.View; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +public class MainActivity extends AppCompatActivity { + + public static final int LOCATION_REQUEST_CODE = 101; + private static final String TAG = "MainActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + if ((ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) + != PackageManager.PERMISSION_GRANTED) && ContextCompat.checkSelfPermission(getApplicationContext(), + Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + requestLocationPermission(); + } + + findViewById(R.id.main_button_url_demo) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(v.getContext(), LocationUrl.class)); + } + }); + + findViewById(R.id.main_button_assets_demo) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(v.getContext(), LocationAssets.class)); + } + }); + + findViewById(R.id.main_button_config_demo) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(v.getContext(), LocationConfig.class)); + } + }); + + findViewById(R.id.main_button_location_demo) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(v.getContext(), LocationTracking.class)); + } + }); + + findViewById(R.id.main_button_geofencing_demo) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(v.getContext(), LocationGeofencing.class)); + } + }); + } + + public void requestLocationPermission() { + if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_REQUEST_CODE); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + String message; + if (requestCode == LOCATION_REQUEST_CODE) { + // If request is cancelled, the result arrays are empty. + if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) { + message = "Location Permission Granted"; + } else { + message = "Location Permission Not Granted"; + } + } else { + message = "Location Permission Not Granted"; + } + showToast(message); + } + + private void showToast(String message) { + Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); + } + +} diff --git a/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/TealiumFirebaseMessagingService.java b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/TealiumFirebaseMessagingService.java new file mode 100644 index 0000000..1a4d9d6 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/TealiumFirebaseMessagingService.java @@ -0,0 +1,36 @@ +package com.example.tealiumlocationdemoapp; + +import android.util.Log; + +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; + +public class TealiumFirebaseMessagingService extends FirebaseMessagingService { + + public static final String TAG = "TealiumFirebaseMsgSvc"; + + public TealiumFirebaseMessagingService() { + } + + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + Log.d(TAG, "From: " + remoteMessage.getFrom()); + + if (remoteMessage.getNotification() != null) { + Log.d(TAG, "Message Notification Title: " + remoteMessage.getNotification().getTitle()); + Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); + } + } + + /** + * Called if InstanceID token is updated. This may occur if the security of + * the previous token had been compromised. Note that this is called when the InstanceID token + * is initially generated so this is where you would retrieve the token. + */ + @Override + public void onNewToken(String token) { + Log.d(TAG, "Refreshed token: " + token); + + TealiumHelper.updatePushToken(token); + } +} diff --git a/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/TealiumHelper.java b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/TealiumHelper.java new file mode 100644 index 0000000..d957699 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/java/com/example/tealiumlocationdemoapp/TealiumHelper.java @@ -0,0 +1,168 @@ +package com.example.tealiumlocationdemoapp; + +import android.app.Application; +import android.content.SharedPreferences; +import android.util.Log; +import android.webkit.WebView; + +import com.tealium.internal.data.Dispatch; +import com.tealium.internal.listeners.WebViewLoadedListener; +import com.tealium.internal.tagbridge.RemoteCommand; +import com.tealium.library.DispatchValidator; +import com.tealium.library.Tealium; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * This class abstracts interaction with the Tealium library and simplifies comprehension + */ +public final class TealiumHelper { + + static { + Log.i("TagBridge", " --- START --- "); + } + + private final static String KEY_TEALIUM_INIT_COUNT = "tealium_init_count"; + private final static String KEY_TEALIUM_INITIALIZED = "tealium_initialized"; + private final static String TAG = "TealiumHelper"; + private static Tealium.Config sConfig; + + // Identifier for the main Tealium instance + public static final String TEALIUM_MAIN = "main"; + + // Not instantiatable. + private TealiumHelper() { + } + + public static void initialize(Application application) { + + Log.i(TAG, "initialize(" + application.getClass().getSimpleName() + ")"); + + WebView.setWebContentsDebuggingEnabled(true); + + final Tealium.Config config = Tealium.Config.create(application, "tealiummobile", "location", "dev"); + + // (OPTIONAL) Update console logs verbosity + config.setForceOverrideLogLevel("dev"); + + // (OPTIONAL) Get the WebView with UTag loaded + config.getEventListeners().add(createWebViewLoadedListener()); + + // (OPTIONAL) Control how the library treats views/links + config.getDispatchValidators().add(createDispatchValidator()); + + sConfig = config; + + final Tealium instance = Tealium.createInstance(TEALIUM_MAIN, sConfig); + + // (OPTIONAL) Enhanced integrations + instance.addRemoteCommand(createLoggerRemoteCommand()); + + // (OPTIONAL) Use tealium.getDataSources().getPersistentDataSources() to set/modify lifetime values + SharedPreferences sp = instance.getDataSources().getPersistentDataSources(); + sp.edit().putInt(KEY_TEALIUM_INIT_COUNT, sp.getInt(KEY_TEALIUM_INIT_COUNT, 0) + 1).commit(); + + // (OPTIONAL) Use tealium.getDataSources().getVolatileDataSources() to set/modify runtime only values + instance.getDataSources().getVolatileDataSources() + .put(KEY_TEALIUM_INITIALIZED, System.currentTimeMillis()); + + // (OPTIONAL) tracking initialization + final Map data = new HashMap<>(2); + data.put("logged_in", false); + data.put("visitor_status", new String[]{"new_user", "unregistered"}); + TealiumHelper.trackEvent("initialization", data); + } + + public static void trackView(String viewName, Map data) { + final Tealium instance = Tealium.getInstance(TEALIUM_MAIN); + + // Instance can be remotely destroyed through publish settings + if (instance != null) { + instance.trackView(viewName, data); + } + } + + public static void trackEvent(String eventName, Map data) { + final Tealium instance = Tealium.getInstance(TEALIUM_MAIN); + + // Instance can be remotely destroyed through publish settings + if (instance != null) { + instance.trackEvent(eventName, data); + } + } + + private static WebViewLoadedListener createWebViewLoadedListener() { + return new WebViewLoadedListener() { + @Override + public void onWebViewLoad(WebView webView, boolean success) { + Log.d(TAG, "WebView " + webView + + (success ? " loaded successfully" : "failed to load")); + } + + @Override + public String toString() { + return "LoggingWebViewLoadListener"; + } + }; + } + + private static DispatchValidator createDispatchValidator() { + return new DispatchValidator() { + @Override + protected boolean shouldDrop(Dispatch dispatch) { + + // Drop any desired dispatches here by returning true. (Never queued nor sent) + return super.shouldDrop(dispatch); + } + + @Override + protected boolean shouldQueue(Dispatch dispatch, boolean shouldQueue) { + + Log.d(TAG, String.format( + Locale.ROOT, + "%s dispatch: %s", + (shouldQueue ? "Queueing" : "Sending"), + dispatch)); + + return super.shouldQueue(dispatch, shouldQueue); + } + + @Override + public String toString() { + return "CustomDispatchValidator"; + } + }; + } + + private static RemoteCommand createLoggerRemoteCommand() { + return new RemoteCommand("logger", "Logs dispatches") { + @Override + protected void onInvoke(Response response) throws Exception { + final String message = response.getRequestPayload() + .optString("message", "no_message"); + Log.i(TAG, "RemoteCommand Message: " + message); + } + + @Override + public String toString() { + return "LoggerRemoteCommand"; + } + }; + } + + public static Tealium.Config getConfig() { + return sConfig; + } + + public static void updatePushToken(String token) { + + if (Tealium.getInstance(TealiumHelper.TEALIUM_MAIN) == null || token == null) { + return; + } + + Tealium.getInstance(TealiumHelper.TEALIUM_MAIN).getDataSources().getPersistentDataSources().edit().putString("push_token", token).apply(); + } + +} \ No newline at end of file diff --git a/Modules/Location/LocationSample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/Modules/Location/LocationSample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/Modules/Location/LocationSample/app/src/main/res/drawable/ic_launcher_background.xml b/Modules/Location/LocationSample/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Modules/Location/LocationSample/app/src/main/res/drawable/tealium_logo_rgb_600x278px.png b/Modules/Location/LocationSample/app/src/main/res/drawable/tealium_logo_rgb_600x278px.png new file mode 100644 index 0000000..b26670d Binary files /dev/null and b/Modules/Location/LocationSample/app/src/main/res/drawable/tealium_logo_rgb_600x278px.png differ diff --git a/Modules/Location/LocationSample/app/src/main/res/drawable/tealium_logo_white_rgb_600x278px.png b/Modules/Location/LocationSample/app/src/main/res/drawable/tealium_logo_white_rgb_600x278px.png new file mode 100644 index 0000000..2346da5 Binary files /dev/null and b/Modules/Location/LocationSample/app/src/main/res/drawable/tealium_logo_white_rgb_600x278px.png differ diff --git a/Modules/Location/LocationSample/app/src/main/res/layout/activity_assets.xml b/Modules/Location/LocationSample/app/src/main/res/layout/activity_assets.xml new file mode 100644 index 0000000..87eb026 --- /dev/null +++ b/Modules/Location/LocationSample/app/src/main/res/layout/activity_assets.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + +