Skip to content

Commit 25d3082

Browse files
Shahroz16claude
andcommitted
feat: integrate location module into sample apps
Wire location module into both sample apps for internal testing: Kotlin Compose sample: - Register ModuleLocation in MainApplication - Add location permission request launcher (fine + coarse) - Add dashboard buttons: Request Location Permission, Set Manual Location (sends hardcoded SF coords), Request Location Once - Pass permission and location callbacks through navigation graph - Add location-related string resources Java Layout sample: - Register ModuleLocation in CustomerIORepository Both samples: - Add location module dependency in sample-app.gradle Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2a698db commit 25d3082

File tree

8 files changed

+110
-10
lines changed

8 files changed

+110
-10
lines changed

samples/java_layout/src/main/java/io/customer/android/sample/java_layout/sdk/CustomerIORepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io.customer.android.sample.java_layout.support.Optional;
1414
import io.customer.messaginginapp.MessagingInAppModuleConfig;
1515
import io.customer.messaginginapp.ModuleMessagingInApp;
16+
import io.customer.location.ModuleLocation;
1617
import io.customer.messagingpush.ModuleMessagingPushFCM;
1718
import io.customer.sdk.CustomerIO;
1819
import io.customer.sdk.CustomerIOConfig;
@@ -38,6 +39,9 @@ public void initializeSdk(SampleApplication application) {
3839
// Enables push notification
3940
builder.addCustomerIOModule(new ModuleMessagingPushFCM());
4041

42+
// Enables location tracking
43+
builder.addCustomerIOModule(new ModuleLocation());
44+
4145
// Enables in-app messages
4246
if (sdkConfig.isInAppMessagingEnabled()) {
4347
builder.addCustomerIOModule(new ModuleMessagingInApp(

samples/kotlin_compose/src/main/java/io/customer/android/sample/kotlin_compose/MainActivity.kt

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class MainActivity : ComponentActivity() {
3939
}
4040
private val deepLinkIntentState: MutableStateFlow<Intent?> = MutableStateFlow(null)
4141
lateinit var notificationPermissionRequestLauncher: ActivityResultLauncher<String>
42+
lateinit var locationPermissionRequestLauncher: ActivityResultLauncher<Array<String>>
4243

4344
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
4445
private val notificationSettingsRequestLauncher = registerForActivityResult(
@@ -80,6 +81,18 @@ class MainActivity : ComponentActivity() {
8081
}
8182
}
8283

84+
locationPermissionRequestLauncher = this.registerForActivityResult(
85+
ActivityResultContracts.RequestMultiplePermissions()
86+
) { permissions ->
87+
val fineGranted = permissions[Manifest.permission.ACCESS_FINE_LOCATION] == true
88+
val coarseGranted = permissions[Manifest.permission.ACCESS_COARSE_LOCATION] == true
89+
if (fineGranted || coarseGranted) {
90+
showMessage(getString(R.string.location_permission_success))
91+
} else {
92+
showMessage(getString(R.string.location_permission_failure))
93+
}
94+
}
95+
8396
setContent {
8497
CustomerIoSDKTheme {
8598
val navController = rememberNavController()
@@ -93,7 +106,8 @@ class MainActivity : ComponentActivity() {
93106
startDestination = currentRoute,
94107
deepLinkState = deepLinkIntentState.asStateFlow(),
95108
modifier = Modifier.systemBarsPadding(),
96-
onCheckPermission = ::launchNotificationPermissionRequest
109+
onCheckPermission = ::launchNotificationPermissionRequest,
110+
onCheckLocationPermission = ::launchLocationPermissionRequest
97111
)
98112
}
99113
}
@@ -118,6 +132,28 @@ class MainActivity : ComponentActivity() {
118132
}
119133
}
120134

135+
private fun launchLocationPermissionRequest() {
136+
val hasFine = ContextCompat.checkSelfPermission(
137+
this,
138+
Manifest.permission.ACCESS_FINE_LOCATION
139+
) == PackageManager.PERMISSION_GRANTED
140+
val hasCoarse = ContextCompat.checkSelfPermission(
141+
this,
142+
Manifest.permission.ACCESS_COARSE_LOCATION
143+
) == PackageManager.PERMISSION_GRANTED
144+
145+
if (hasFine || hasCoarse) {
146+
showMessage(getString(R.string.location_permission_already_granted))
147+
} else {
148+
locationPermissionRequestLauncher.launch(
149+
arrayOf(
150+
Manifest.permission.ACCESS_FINE_LOCATION,
151+
Manifest.permission.ACCESS_COARSE_LOCATION
152+
)
153+
)
154+
}
155+
}
156+
121157
private fun showMessage(string: String) {
122158
Snackbar.make(this.findViewById(android.R.id.content), string, Snackbar.LENGTH_SHORT).show()
123159
}

samples/kotlin_compose/src/main/java/io/customer/android/sample/kotlin_compose/MainApplication.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.app.Application
44
import io.customer.android.sample.kotlin_compose.data.models.setValuesFromBuilder
55
import io.customer.android.sample.kotlin_compose.data.sdk.InAppMessageEventListener
66
import io.customer.android.sample.kotlin_compose.di.ServiceLocator
7+
import io.customer.location.ModuleLocation
78
import io.customer.messaginginapp.MessagingInAppModuleConfig
89
import io.customer.messaginginapp.ModuleMessagingInApp
910
import io.customer.messagingpush.ModuleMessagingPushFCM
@@ -37,6 +38,7 @@ class MainApplication : Application() {
3738
)
3839
)
3940
.addCustomerIOModule(ModuleMessagingPushFCM())
41+
.addCustomerIOModule(ModuleLocation())
4042
configuration.setValuesFromBuilder(builder)
4143

4244
CustomerIO.initialize(builder.build())

samples/kotlin_compose/src/main/java/io/customer/android/sample/kotlin_compose/navigation/AppNavigation.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ fun AppNavGraph(
4242
modifier: Modifier = Modifier,
4343
deepLinkState: StateFlow<Intent?>,
4444
startDestination: String = Screen.Login.route,
45-
onCheckPermission: () -> Unit
45+
onCheckPermission: () -> Unit,
46+
onCheckLocationPermission: () -> Unit
4647
) {
4748
val navController = rememberNavController()
4849

@@ -57,7 +58,7 @@ fun AppNavGraph(
5758
) {
5859
addLoginRoute(navController)
5960
addSettingsRoute(navController)
60-
addDashboardRoute(navController, onCheckPermission)
61+
addDashboardRoute(navController, onCheckPermission, onCheckLocationPermission)
6162
addCustomEventRoute(navController)
6263
addCustomAttributeRoute(navController)
6364
}
@@ -146,7 +147,8 @@ internal fun NavGraphBuilder.addCustomEventRoute(
146147

147148
internal fun NavGraphBuilder.addDashboardRoute(
148149
navController: NavHostController,
149-
onCheckPermission: () -> Unit
150+
onCheckPermission: () -> Unit,
151+
onCheckLocationPermission: () -> Unit
150152
) {
151153
composable(route = Screen.Dashboard.route, deepLinks = getDeepLink("dashboard")) {
152154
DashboardRoute(
@@ -164,7 +166,8 @@ internal fun NavGraphBuilder.addDashboardRoute(
164166
popUpTo(Screen.Dashboard.route) { inclusive = true }
165167
}
166168
},
167-
onCheckPermission = onCheckPermission
169+
onCheckPermission = onCheckPermission,
170+
onCheckLocationPermission = onCheckLocationPermission
168171
)
169172
}
170173
}

samples/kotlin_compose/src/main/java/io/customer/android/sample/kotlin_compose/ui/dashboard/Dashboard.kt

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ fun DashboardRoute(
4343
onTrackCustomAttribute: (type: String) -> Unit,
4444
onLogout: () -> Unit,
4545
onSettingsClick: () -> Unit,
46-
onCheckPermission: () -> Unit
46+
onCheckPermission: () -> Unit,
47+
onCheckLocationPermission: () -> Unit
4748
) {
4849
val userState = viewModel.uiState.collectAsState()
4950

@@ -62,7 +63,14 @@ fun DashboardRoute(
6263
viewModel.sendRandomEvent()
6364
},
6465
onSettingsClick = onSettingsClick,
65-
onCheckPermission = onCheckPermission
66+
onCheckPermission = onCheckPermission,
67+
onCheckLocationPermission = onCheckLocationPermission,
68+
onSetManualLocation = {
69+
viewModel.setManualLocation()
70+
},
71+
onRequestLocationOnce = {
72+
viewModel.requestLocationOnce()
73+
}
6674
)
6775
}
6876

@@ -74,7 +82,10 @@ fun DashboardScreen(
7482
onRandomEvent: () -> Unit,
7583
onLogout: () -> Unit,
7684
onSettingsClick: () -> Unit,
77-
onCheckPermission: () -> Unit
85+
onCheckPermission: () -> Unit,
86+
onCheckLocationPermission: () -> Unit,
87+
onSetManualLocation: () -> Unit,
88+
onRequestLocationOnce: () -> Unit
7889
) {
7990
val snackbarHostState = remember { SnackbarHostState() }
8091
val scope = rememberCoroutineScope()
@@ -98,7 +109,10 @@ fun DashboardScreen(
98109
}
99110
},
100111
onLogout = onLogout,
101-
onCheckPermission = onCheckPermission
112+
onCheckPermission = onCheckPermission,
113+
onCheckLocationPermission = onCheckLocationPermission,
114+
onSetManualLocation = onSetManualLocation,
115+
onRequestLocationOnce = onRequestLocationOnce
102116
)
103117
}
104118
VersionText()
@@ -116,7 +130,10 @@ fun SendEventsView(
116130
onRandomEvent: () -> Unit,
117131
showMessage: (String) -> Unit,
118132
onLogout: () -> Unit,
119-
onCheckPermission: () -> Unit
133+
onCheckPermission: () -> Unit,
134+
onCheckLocationPermission: () -> Unit,
135+
onSetManualLocation: () -> Unit,
136+
onRequestLocationOnce: () -> Unit
120137
) {
121138
val context = LocalContext.current
122139

@@ -156,6 +173,24 @@ fun SendEventsView(
156173
modifier = Modifier.testTag(stringResource(id = R.string.acd_push_prompt_button)),
157174
onClick = onCheckPermission
158175
)
176+
ActionButton(
177+
text = stringResource(R.string.request_location_permission),
178+
onClick = onCheckLocationPermission
179+
)
180+
ActionButton(
181+
text = stringResource(R.string.set_manual_location),
182+
onClick = {
183+
onSetManualLocation.invoke()
184+
showMessage(context.getString(R.string.location_sent_successfully))
185+
}
186+
)
187+
ActionButton(
188+
text = stringResource(R.string.request_location_once),
189+
onClick = {
190+
onRequestLocationOnce.invoke()
191+
showMessage(context.getString(R.string.location_request_sent))
192+
}
193+
)
159194
ActionButton(
160195
text = "Inline Examples (Navigation)",
161196
onClick = {

samples/kotlin_compose/src/main/java/io/customer/android/sample/kotlin_compose/ui/dashboard/DashboardViewModel.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope
55
import io.customer.android.sample.kotlin_compose.data.models.User
66
import io.customer.android.sample.kotlin_compose.data.repositories.UserRepository
77
import io.customer.android.sample.kotlin_compose.di.ServiceLocator
8+
import io.customer.location.ModuleLocation
89
import io.customer.sdk.CustomerIO
910
import java.util.Calendar
1011
import java.util.Random
@@ -60,4 +61,13 @@ class DashboardViewModel(
6061
}
6162
}
6263
}
64+
65+
fun setManualLocation() {
66+
// Send a sample location (San Francisco) for testing
67+
ModuleLocation.instance().locationServices.setLastKnownLocation(37.7749, -122.4194)
68+
}
69+
70+
fun requestLocationOnce() {
71+
ModuleLocation.instance().locationServices.requestLocationUpdateOnce()
72+
}
6373
}

samples/kotlin_compose/src/main/res/values/strings.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,12 @@
5151
<string name="title_inline_multiple">Multiple</string>
5252
<string name="title_inline_compose">Compose</string>
5353
<string name="title_inline_recycler">RecyclerView</string>
54+
<string name="request_location_permission">Request Location Permission</string>
55+
<string name="set_manual_location">Set Manual Location</string>
56+
<string name="request_location_once">Request Location Once</string>
57+
<string name="location_permission_success">Location permission granted</string>
58+
<string name="location_permission_failure">Location permission denied</string>
59+
<string name="location_permission_already_granted">Location permission already granted</string>
60+
<string name="location_sent_successfully">Manual location sent successfully</string>
61+
<string name="location_request_sent">Location request sent</string>
5462
</resources>

samples/sample-app.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,15 @@ dependencies {
128128
implementation(project(":messaginginapp"))
129129
// messaginginapp-compose adds messaginginapp transitively
130130
implementation(project(":messaginginapp-compose"))
131+
implementation(project(":location"))
131132
} else {
132133
// Stable releases dependency, use published versions directly
133134
implementation "io.customer.android:datapipelines:$cioSDKVersion"
134135
implementation "io.customer.android:messaging-push-fcm:$cioSDKVersion"
135136
implementation "io.customer.android:messaging-in-app:$cioSDKVersion"
136137
// messaginginapp-compose adds messaginginapp transitively
137138
implementation "io.customer.android:messaging-in-app-compose:$cioSDKVersion"
139+
implementation "io.customer.android:location:$cioSDKVersion"
138140
}
139141

140142
// Add Compose dependencies for all sample projects

0 commit comments

Comments
 (0)