Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/reusable_build_sample_apps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ jobs:
- "kotlin_compose"
include: # Add additional variables to each sample app build: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude
- sample-app: "java_layout"
cio-workspace-name: "Mobile: Native iOS & Android"
cio-cdpapikey-secret-key: "CUSTOMERIO_JAVA_WORKSPACE_CDP_API_KEY"
cio-siteid-secret-key: "CUSTOMERIO_JAVA_WORKSPACE_SITE_ID"
- sample-app: "kotlin_compose"
cio-workspace-name: "Mobile: xiOS CocoaPods FCM + Kotlin Android"
cio-cdpapikey-secret-key: "CUSTOMERIO_KOTLIN_WORKSPACE_CDP_API_KEY"
cio-siteid-secret-key: "CUSTOMERIO_KOTLIN_WORKSPACE_SITE_ID"

Expand Down Expand Up @@ -91,8 +93,10 @@ jobs:
touch "samples/local.properties"
echo "cdpApiKey=${{ secrets[matrix.cio-cdpapikey-secret-key] }}" >> "samples/local.properties"
echo "siteId=${{ secrets[matrix.cio-siteid-secret-key] }}" >> "samples/local.properties"
echo "branch=$BRANCH_NAME" >> "samples/local.properties"
echo "commit=${COMMIT_HASH:0:7}" >> "samples/local.properties"
echo "workspace=${{ matrix.cio-workspace-name }}" >> "samples/local.properties"
echo "branchName=$BRANCH_NAME" >> "samples/local.properties"
echo "commitHash=${COMMIT_HASH:0:7}" >> "samples/local.properties"
echo "commitsAheadCount=$(git rev-list $(git describe --tags --abbrev=0)..HEAD --count)" >> samples/local.properties
if [ "${{ inputs.use_latest_sdk_version == true }}" ]; then
echo "sdkVersion=${{ steps.latest-sdk-version-step.outputs.LATEST_TAG }}" >> "samples/local.properties"
fi
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package io.customer.android.sample.java_layout.buildinfo;

import android.graphics.Typeface;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.StyleSpan;

import androidx.annotation.NonNull;

import java.util.Locale;

import io.customer.android.sample.java_layout.BuildConfig;
import io.customer.sdk.Version;

/**
* Contains metadata about the build environment.
*/
public class BuildInfoMetadata {
private final String sdkVersion;
private final String appVersion;
private final String buildDate;
private final String gitMetadata;
private final String defaultWorkspace;
private final String language;
private final String uiFramework;
private final String sdkIntegration;

public BuildInfoMetadata() {
this.sdkVersion = BuildInfoMetadataUtils.resolveValidOrElse(BuildConfig.SDK_VERSION, () -> String.format(
Locale.ENGLISH, "%s-%s",
Version.version,
BuildInfoMetadataUtils.resolveValidOrElse(BuildConfig.COMMITS_AHEAD_COUNT, () -> "as-source")));
this.appVersion = String.valueOf(BuildConfig.VERSION_CODE);
this.buildDate = BuildInfoMetadataUtils.formatBuildDateWithRelativeTime(BuildConfig.BUILD_TIMESTAMP);
this.gitMetadata = String.format(Locale.ENGLISH, "%s-%s",
BuildInfoMetadataUtils.resolveValidOrElse(BuildConfig.BRANCH_NAME, () -> "working branch"),
BuildInfoMetadataUtils.resolveValidOrElse(BuildConfig.COMMIT_HASH, () -> "untracked"));
this.defaultWorkspace = BuildInfoMetadataUtils.resolveValidOrElse(BuildConfig.DEFAULT_WORKSPACE);
this.language = BuildInfoMetadataUtils.resolveValidOrElse(BuildConfig.LANGUAGE);
this.uiFramework = BuildInfoMetadataUtils.resolveValidOrElse(BuildConfig.UI_FRAMEWORK);
this.sdkIntegration = BuildInfoMetadataUtils.resolveValidOrElse(BuildConfig.SDK_INTEGRATION);
}

@NonNull
@Override
public String toString() {
return toFormattedString().toString();
}

@NonNull
public CharSequence toFormattedString() {
SpannableStringBuilder builder = new SpannableStringBuilder();

appendBold(builder, "SDK Version: ");
builder.append(sdkVersion).append(" \t");
appendBold(builder, "App version: ");
builder.append(appVersion).append("\n");
appendBold(builder, "Build Date: ");
builder.append(buildDate).append("\n");
appendBold(builder, "Branch: ");
builder.append(gitMetadata).append("\n");
appendBold(builder, "Default Workspace: ");
builder.append(defaultWorkspace).append("\n");
appendBold(builder, "Language: ");
builder.append(language).append(" \t");
appendBold(builder, "UI Framework: ");
builder.append(uiFramework).append("\n");
appendBold(builder, "SDK Integration: ");
builder.append(sdkIntegration);

return builder;
}

private void appendBold(@NonNull SpannableStringBuilder builder, @NonNull String text) {
SpannableString spannable = new SpannableString(text);
spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.append(spannable);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.customer.android.sample.java_layout.buildinfo;

import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

public class BuildInfoMetadataUtils {
public static String resolveValidOrElse(@Nullable String text) {
return resolveValidOrElse(text, () -> "unknown");
}

public static String resolveValidOrElse(@Nullable String text, @NonNull ValueProvider<String> fallbackProvider) {
// When local properties are not set, they have a string value of "null"
if (!TextUtils.isEmpty(text) && !"null".equalsIgnoreCase(text)) {
return text;
}

return fallbackProvider.get();
}

public static String formatBuildDateWithRelativeTime(long buildTimestamp) {
Date buildDate = new Date(buildTimestamp);
String formattedDate = DateFormat.getDateTimeInstance().format(buildDate);

long diffInMillis = System.currentTimeMillis() - buildTimestamp;
long daysAgo = TimeUnit.MILLISECONDS.toDays(diffInMillis);
String relativeTime = daysAgo == 0 ? "(Today)" : String.format(Locale.ENGLISH, "(%d days ago)", daysAgo);

return String.format(Locale.ENGLISH, "%s %s", formattedDate, relativeTime);
}

/**
* Provides a value when the original value is not valid using lambda expressions.
* This can be simplified with Java 8+ or Kotlin later if needed.
*/
public interface ValueProvider<T> {
@NonNull
T get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import io.customer.android.sample.java_layout.BuildConfig;
import io.customer.android.sample.java_layout.R;
import io.customer.android.sample.java_layout.buildinfo.BuildInfoMetadata;

public class ViewUtils {
public static void prepareForAutomatedTests(@NonNull View view, @StringRes int contentDescResId) {
Expand Down Expand Up @@ -55,38 +51,8 @@ public static void setError(@NonNull TextInputLayout textInputLayout, @Nullable
}

public static void setBuildInfo(@NonNull TextView textView) {
String buildInfo = String.format(
Locale.ENGLISH,
"SDK version: %s\n" +
"Build date: %s\n" +
"Branch: %s\n" +
"Default workspace: Native iOS & Android\n" +
"App version: %s",
getSdkVersion(),
getBuildTime(),
getBranchName(),
BuildConfig.VERSION_CODE
);
textView.setText(buildInfo);
}

private static String getBuildTime() {
return DateFormat.getDateTimeInstance().format(new Date(BuildConfig.BUILD_TIMESTAMP));
}

private static String getSdkVersion() {
if (isEmptyOrUnset(BuildConfig.SDK_VERSION)) return "as source code";
return BuildConfig.SDK_VERSION;
}

private static String getBranchName() {
if (isEmptyOrUnset(BuildConfig.BRANCH)) return "local development";
return BuildConfig.BRANCH + "." + BuildConfig.COMMIT;
}

private static boolean isEmptyOrUnset(String text) {
// When local properties are not set, they have a string value of "null"
return TextUtils.isEmpty(text) || "null".equalsIgnoreCase(text);
BuildInfoMetadata buildInfo = new BuildInfoMetadata();
textView.setText(buildInfo.toFormattedString());
}

@NonNull
Expand Down
37 changes: 33 additions & 4 deletions samples/sample-app.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,52 @@ android {
Closure<String> getConfigWithPrefix = { String key ->
localProperties."${configKeyPrefix}${key}" ?: localProperties."${key}"
}
// Helper methods to retrieve language and UI framework from prefix
Closure<String> getLanguageFromPrefix = { String prefix ->
String normalizedPrefix = prefix.toLowerCase()
if (normalizedPrefix.startsWith("java")) {
return "Java"
} else if (normalizedPrefix.startsWith("kotlin")) {
return "Kotlin"
}
return null
}
Closure<String> getUIFrameworkFromPrefix = { String prefix ->
String normalizedPrefix = prefix.toLowerCase()
if (normalizedPrefix.contains("layout")) {
return "Android XML"
} else if (normalizedPrefix.contains("compose")) {
return "Jetpack Compose"
}
return null
}

// Retrieve API keys using the helper method to allow key prefixing
// e.g. Java Layout sample app has prefix javaLayout_ for API keys
// javaLayout_cdpApiKey=KEY has higher priority than cdpApiKey=KEY
// cdpApiKey=KEY can be used as a fallback for all sample apps
String cdpApiKey = getConfigWithPrefix("cdpApiKey")
String siteId = getConfigWithPrefix("siteId")
String workspace = getConfigWithPrefix("workspace")
String language = getConfigWithPrefix("language") ?: getLanguageFromPrefix(configKeyPrefix)
String uiFramework = getConfigWithPrefix("uiFramework") ?: getUIFrameworkFromPrefix(configKeyPrefix)
String sdkIntegration = "Maven"
String sdkVersion = localProperties["sdkVersion"]
String branch = localProperties["branch"]
String commit = localProperties["commit"]
String branchName = localProperties["branchName"]
String commitHash = localProperties["commitHash"]
String commitsAheadCount = localProperties["commitsAheadCount"]

// Set build config fields for API keys
buildConfigField "String", "CDP_API_KEY", "\"${cdpApiKey}\""
buildConfigField "String", "SITE_ID", "\"${siteId}\""
buildConfigField "String", "DEFAULT_WORKSPACE", "\"${workspace}\""
buildConfigField "String", "LANGUAGE", "\"${language}\""
buildConfigField "String", "UI_FRAMEWORK", "\"${uiFramework}\""
buildConfigField "String", "SDK_INTEGRATION", "\"${sdkIntegration}\""
buildConfigField "String", "SDK_VERSION", "\"${sdkVersion}\""
buildConfigField "String", "BRANCH", "\"${branch}\""
buildConfigField "String", "COMMIT", "\"${commit}\""
buildConfigField "String", "BRANCH_NAME", "\"${branchName}\""
buildConfigField "String", "COMMIT_HASH", "\"${commitHash}\""
buildConfigField "String", "COMMITS_AHEAD_COUNT", "\"${commitsAheadCount}\""
buildConfigField "long", "BUILD_TIMESTAMP", System.currentTimeMillis() + "L"
}
// Avoid redefining signing configs in sample apps to avoid breaking release
Expand Down
Loading