Skip to content

Commit

Permalink
chore: java sample fixes and improvements (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrehan27 authored Jul 4, 2023
1 parent 9ae6f4c commit 85022d1
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
Expand All @@ -13,6 +14,8 @@
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;

import com.google.android.material.dialog.MaterialAlertDialogBuilder;
Expand All @@ -37,7 +40,6 @@ public class DashboardActivity extends BaseActivity<ActivityDashboardBinding> {
private AuthViewModel authViewModel;
private CustomerIORepository customerIORepository;

@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
private final ActivityResultLauncher<Intent> notificationSettingsRequestLauncher =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (isNotificationPermissionGranted()) {
Expand All @@ -50,10 +52,7 @@ public class DashboardActivity extends BaseActivity<ActivityDashboardBinding> {
if (isGranted) {
showPushPermissionGranted();
} else {
MaterialAlertDialogBuilder builder = ViewUtils.createAlertDialog(this);
builder.setMessage(R.string.notification_permission_denied);
builder.setNeutralButton(R.string.open_settings, (dialogInterface, i) -> openNotificationPermissionSettings());
builder.show();
showPushPermissionDeniedAlert(R.string.notification_permission_denied);
}
});

Expand Down Expand Up @@ -174,35 +173,39 @@ private void startSimpleFragmentActivity(String fragmentName) {
}

private void requestNotificationPermission() {
// Push notification permission is only required by API Level 33 (Android 13) and above
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
showPushPermissionGrantedAlert();
return;
}

// Ask for notification permission if not granted
if (isNotificationPermissionGranted()) {
// Ask for notification permission if not granted
showPushPermissionGrantedAlert();
} else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
MaterialAlertDialogBuilder builder = ViewUtils.createAlertDialog(this);
builder.setMessage(R.string.notification_permission_failure);
builder.setNeutralButton(R.string.open_settings, (dialogInterface, i) -> openNotificationPermissionSettings());
builder.show();
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
// If notification permission is not available or denied permanently, show prompt to open settings
showPushPermissionDeniedAlert(R.string.notification_permission_failure);
} else {
// Else, request notification permission
notificationPermissionRequestLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
}
}

@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
private boolean isNotificationPermissionGranted() {
return ContextCompat.checkSelfPermission(DashboardActivity.this,
Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED;
// Push notification permission is only required by API Level 33 (Android 13) and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
return ContextCompat.checkSelfPermission(DashboardActivity.this,
Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED;
}

// For Android OS 12 and below, notification enabled status can be checked using NotificationManagerCompat
return NotificationManagerCompat.from(this).areNotificationsEnabled();
}

@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
private void openNotificationPermissionSettings() {
Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
final Intent intent;
final String packageName = getPackageName();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
} else {
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + packageName));
}
notificationSettingsRequestLauncher.launch(intent);
}

Expand All @@ -218,4 +221,11 @@ private void showPushPermissionGrantedAlert() {
builder.setMessage(R.string.notification_permission_success);
builder.show();
}

private void showPushPermissionDeniedAlert(@StringRes int messageResId) {
MaterialAlertDialogBuilder builder = ViewUtils.createAlertDialog(this);
builder.setMessage(messageResId);
builder.setNeutralButton(R.string.open_settings, (dialogInterface, i) -> openNotificationPermissionSettings());
builder.show();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ private void setupViews() {
clipboard.setPrimaryClip(clip);
});
binding.saveButton.setOnClickListener(view -> saveSettings());
binding.restoreDefaultsButton.setOnClickListener(view -> updateIOWithConfig(CustomerIOSDKConfig.getDefaultConfigurations()));
binding.restoreDefaultsButton.setOnClickListener(view -> {
updateIOWithConfig(CustomerIOSDKConfig.getDefaultConfigurations());
saveSettings();
});
}

private void setupObservers() {
Expand All @@ -147,7 +150,14 @@ private boolean isTrackingURLValid(String url) {
Uri uri = Uri.parse(url);
String scheme = uri.getScheme();
// Since SDK does not allow tracking URL with empty host or incorrect schemes
return !TextUtils.isEmpty(uri.getAuthority()) && ("http".equals(scheme) || "https".equals(scheme));
return !TextUtils.isEmpty(uri.getAuthority()) && ("http".equals(scheme) || "https".equals(scheme)) && uri.getPath().endsWith("/");
}

@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private <T extends Number & Comparable<T>> boolean isNumberValid(T number, T min) {
// Compares if the value is not null and greater than or equal to min
// i.e. evaluates number >= min
return number != null && number.compareTo(min) >= 0;
}

private void updateIOWithConfig(@NonNull CustomerIOSDKConfig config) {
Expand All @@ -174,12 +184,28 @@ private void saveSettings() {
isFormValid = updateErrorState(binding.apiKeyInputLayout, TextUtils.isEmpty(apiKey), R.string.error_text_input_field_blank) && isFormValid;

String bqSecondsDelayText = ViewUtils.getTextTrimmed(binding.bqDelayTextInput);
isFormValid = updateErrorState(binding.bqDelayInputLayout, TextUtils.isEmpty(bqSecondsDelayText), R.string.error_text_input_field_blank) && isFormValid;
Double bqSecondsDelay = StringUtils.parseDouble(bqSecondsDelayText, null);
boolean isBQSecondsDelayTextEmpty = TextUtils.isEmpty(bqSecondsDelayText);
if (isBQSecondsDelayTextEmpty) {
isFormValid = updateErrorState(binding.bqDelayInputLayout, true, R.string.error_text_input_field_blank) && isFormValid;
} else {
double minDelay = 1.0;
isFormValid = updateErrorState(binding.bqDelayInputLayout,
!isNumberValid(bqSecondsDelay, minDelay),
getString(R.string.error_number_input_field_small, String.valueOf(minDelay))) && isFormValid;
}

String bqMinTasksText = ViewUtils.getTextTrimmed(binding.bqTasksTextInput);
isFormValid = updateErrorState(binding.bqTasksInputLayout, TextUtils.isEmpty(bqMinTasksText), R.string.error_text_input_field_blank) && isFormValid;
Integer bqMinTasks = StringUtils.parseInteger(bqMinTasksText, null);
boolean isBQMinTasksTextEmpty = TextUtils.isEmpty(bqMinTasksText);
if (isBQMinTasksTextEmpty) {
isFormValid = updateErrorState(binding.bqTasksInputLayout, true, R.string.error_text_input_field_blank) && isFormValid;
} else {
int minTasks = 1;
isFormValid = updateErrorState(binding.bqTasksInputLayout,
!isNumberValid(bqMinTasks, minTasks),
getString(R.string.error_number_input_field_small, String.valueOf(minTasks))) && isFormValid;
}

if (isFormValid) {
binding.progressIndicator.show();
Expand Down Expand Up @@ -214,4 +240,12 @@ private boolean updateErrorState(TextInputLayout textInputLayout,
ViewUtils.setError(textInputLayout, error);
return !isErrorEnabled;
}

private boolean updateErrorState(TextInputLayout textInputLayout,
boolean isErrorEnabled,
String errorMessage) {
String error = isErrorEnabled ? errorMessage : null;
ViewUtils.setError(textInputLayout, error);
return !isErrorEnabled;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.customer.android.sample.java_layout.ui.tracking;

import android.os.Bundle;
import android.text.TextUtils;

import androidx.fragment.app.FragmentActivity;

Expand Down Expand Up @@ -90,48 +89,31 @@ private void setupViews() {
}

binding.sendEventButton.setOnClickListener(view -> {
boolean isFormValid = true;
String attributeName = ViewUtils.getText(binding.attributeNameTextInput);
String attributeValue = ViewUtils.getText(binding.attributeValueTextInput);

if (TextUtils.isEmpty(attributeName)) {
ViewUtils.setError(binding.attributeNameInputLayout, getString(R.string.error_text_input_field_empty));
isFormValid = false;
} else {
ViewUtils.setError(binding.attributeNameInputLayout, null);
Map<String, String> attributes = new HashMap<>();
attributes.put(attributeName, attributeValue);

final String attributeType;
switch (mAttributeType) {
case ATTRIBUTE_TYPE_DEVICE:
attributeType = getString(R.string.device);
customerIORepository.setDeviceAttributes(attributes);
break;
case ATTRIBUTE_TYPE_PROFILE:
attributeType = getString(R.string.profile);
customerIORepository.setProfileAttributes(attributes);
break;
default:
return;
}

if (TextUtils.isEmpty(attributeValue)) {
ViewUtils.setError(binding.attributeValueInputLayout, getString(R.string.error_text_input_field_empty));
isFormValid = false;
} else {
ViewUtils.setError(binding.attributeValueInputLayout, null);
}

if (isFormValid) {
Map<String, String> attributes = new HashMap<>();
attributes.put(attributeName, attributeValue);

final String attributeType;
switch (mAttributeType) {
case ATTRIBUTE_TYPE_DEVICE:
attributeType = getString(R.string.device);
customerIORepository.setDeviceAttributes(attributes);
break;
case ATTRIBUTE_TYPE_PROFILE:
attributeType = getString(R.string.profile);
customerIORepository.setProfileAttributes(attributes);
break;
default:
return;
}

FragmentActivity activity = getActivity();
if (activity != null) {
Snackbar.make(binding.sendEventButton,
getString(R.string.attributes_tracked_msg_format, attributeType),
Snackbar.LENGTH_SHORT).show();
}
FragmentActivity activity = getActivity();
if (activity != null) {
Snackbar.make(binding.sendEventButton,
getString(R.string.attributes_tracked_msg_format, attributeType),
Snackbar.LENGTH_SHORT).show();
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,29 +52,21 @@ private void prepareViewsForAutomatedTests() {

private void setupViews() {
binding.sendEventButton.setOnClickListener(view -> {
boolean isFormValid = true;
String eventName = ViewUtils.getText(binding.eventNameTextInput);
String propertyName = ViewUtils.getText(binding.propertyNameTextInput);
String propertyValue = ViewUtils.getText(binding.propertyValueTextInput);

if (TextUtils.isEmpty(eventName)) {
ViewUtils.setError(binding.eventNameInputLayout, getString(R.string.error_text_input_field_empty));
isFormValid = false;
} else {
ViewUtils.setError(binding.eventNameInputLayout, null);
Map<String, String> extras = new HashMap<>();
if (!TextUtils.isEmpty(propertyName)) {
extras.put(propertyName, propertyValue);
}
customerIORepository.trackEvent(eventName, extras);

if (isFormValid) {
Map<String, String> extras = new HashMap<>();
extras.put(propertyName, propertyValue);
customerIORepository.trackEvent(eventName, extras);

FragmentActivity activity = getActivity();
if (activity != null) {
Snackbar.make(binding.sendEventButton,
R.string.event_tracked_msg,
Snackbar.LENGTH_SHORT).show();
}
FragmentActivity activity = getActivity();
if (activity != null) {
Snackbar.make(binding.sendEventButton,
R.string.event_tracked_msg,
Snackbar.LENGTH_SHORT).show();
}
});
}
Expand Down
1 change: 1 addition & 0 deletions samples/java_layout/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@
<string name="filter_view_universal_link">Java Sample Universal Scheme Links</string>
<string name="error_text_input_field_blank">This field cannot be blank</string>
<string name="error_text_input_field_empty">This field cannot be empty</string>
<string name="error_number_input_field_small">The value must be greater than or equal to %1$s</string>
</resources>

0 comments on commit 85022d1

Please sign in to comment.