Skip to content

Commit

Permalink
Add datalayer-phone-ui with Install App prompt feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
luizgrp committed Nov 22, 2023
1 parent 4bbd268 commit ed36a82
Show file tree
Hide file tree
Showing 18 changed files with 710 additions and 15 deletions.
17 changes: 17 additions & 0 deletions datalayer/phone-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# DataLayer Phone UI library

[![Maven Central](https://img.shields.io/maven-central/v/com.google.android.horologist/horologist-datalayer-phone-ui)](https://search.maven.org/search?q=g:com.google.android.horologist)

For more information, visit the documentation: https://google.github.io/horologist/datalayer

## Download

```groovy
repositories {
mavenCentral()
}
dependencies {
implementation "com.google.android.horologist:horologist-datalayer-phone-ui:<version>"
}
```
32 changes: 32 additions & 0 deletions datalayer/phone-ui/api/current.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Signature format: 4.0
package com.google.android.horologist.datalayer.phone.ui {

@com.google.android.horologist.annotations.ExperimentalHorologistApi public final class PhoneUiDataLayerHelper {
ctor public PhoneUiDataLayerHelper();
method public void showInstallAppPrompt(android.app.Activity activity, String appName, String watchName, String message, optional int requestCode);
}

public final class PhoneUiDataLayerHelperKt {
}

}

package com.google.android.horologist.datalayer.phone.ui.play {

public final class PlayLauncherKt {
method public static void launchPlay(android.content.Context, String packageName);
}

}

package com.google.android.horologist.datalayer.phone.ui.prompt {

public final class InstallAppDialogActivityKt {
}

public final class InstallAppDialogKt {
method @androidx.compose.runtime.Composable public static void InstallAppDialog(String appName, String watchName, String message, kotlin.jvm.functions.Function0<kotlin.Unit> icon, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function0<kotlin.Unit> onConfirmation);
}

}

135 changes: 135 additions & 0 deletions datalayer/phone-ui/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

plugins {
id("com.android.library")
id("org.jetbrains.dokka")
id("me.tylerbwong.gradle.metalava")
alias(libs.plugins.dependencyAnalysis)
kotlin("android")
}

android {
compileSdk = 34

defaultConfig {
minSdk = 21

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

buildFeatures {
buildConfig = false
compose = true
}

kotlinOptions {
jvmTarget = "11"

freeCompilerArgs = freeCompilerArgs +
listOf(
"-opt-in=kotlin.RequiresOptIn",
"-opt-in=com.google.android.horologist.annotations.ExperimentalHorologistApi",
)
}

composeOptions {
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
}

packaging {
resources {
excludes +=
listOf(
"/META-INF/AL2.0",
"/META-INF/LGPL2.1",
)
}
}

testOptions {
unitTests {
isIncludeAndroidResources = true
}
animationsDisabled = true
}

lint {
checkReleaseBuilds = false
textReport = true
}

resourcePrefix = "horologist_"

namespace = "com.google.android.horologist.datalayer.phone.ui"
}

project.tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
// Workaround for https://youtrack.jetbrains.com/issue/KT-37652
if (!this.name.endsWith("TestKotlin") && !this.name.startsWith("compileDebug")) {
this.kotlinOptions {
freeCompilerArgs = freeCompilerArgs + "-Xexplicit-api=strict"
}
}
}

metalava {
sourcePaths.setFrom("src/main")
filename.set("api/current.api")
reportLintsAsErrors.set(true)
}

dependencies {
api(libs.compose.runtime)
api(libs.compose.ui)
api(projects.annotations)

implementation(libs.androidx.activity.compose)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.corektx)
implementation(libs.compose.ui.toolingpreview)
implementation(libs.compose.material3)
implementation(libs.material)
implementation(platform(libs.compose.bom))

testImplementation(libs.junit)

androidTestImplementation(libs.androidx.test.ext)
androidTestImplementation(libs.androidx.test.espressocore)
}

dependencyAnalysis {
issues {
onAny {
severity("fail")
}
}
}

tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial>().configureEach {
dokkaSourceSets {
configureEach {
moduleName.set("datalayer-phone-ui")
}
}
}

apply(plugin = "com.vanniktech.maven.publish")
3 changes: 3 additions & 0 deletions datalayer/phone-ui/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
POM_ARTIFACT_ID=horologist-datalayer-phone-ui
POM_NAME=Horologist DataLayer Phone UI library
POM_PACKAGING=aar
17 changes: 17 additions & 0 deletions datalayer/phone-ui/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.google.android.horologist.datalayer.phone.ui">

<uses-sdk
android:minSdkVersion="21"
tools:ignore="GradleOverrides" />

<application>
<activity
android:name=".prompt.InstallAppDialogActivity"
android:excludeFromRecents="true"
android:exported="false"
android:theme="@style/HorologistTheme.PromptDialog" />
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.android.horologist.datalayer.phone.ui

import android.app.Activity
import androidx.annotation.DrawableRes
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.datalayer.phone.ui.prompt.InstallAppDialogActivity

private const val NO_RESULT_REQUESTED_REQUEST_CODE = -1

/**
* Data layer related helper features, for use on phones.
*/
@ExperimentalHorologistApi
public class PhoneUiDataLayerHelper {

public fun showInstallAppPrompt(
activity: Activity,
appName: String,
watchName: String,
message: String,
@DrawableRes image: Int,
requestCode: Int = NO_RESULT_REQUESTED_REQUEST_CODE,
) {
activity.startActivityForResult(
InstallAppDialogActivity.getIntent(
context = activity,
appName = appName,
watchName = watchName,
message = message,
image = image,
),
requestCode,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.android.horologist.datalayer.phone.ui.play

import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.core.content.ContextCompat

private const val PLAY_STORE_APP_URI_PREFIX = "market://details?id="
private const val PLAY_STORE_WEB_URL_PREFIX = "https://play.google.com/store/apps/details?id="

/**
* Launch Google Play app, requesting to display app with specified [package name][packageName].
*/
public fun Context.launchPlay(packageName: String) {
try {
ContextCompat.startActivity(
this,
Intent(
Intent.ACTION_VIEW,
Uri.parse(PLAY_STORE_APP_URI_PREFIX + packageName),
),
Bundle(),
)
} catch (anfe: ActivityNotFoundException) {
// Handle scenario where Google Play app is not installed
ContextCompat.startActivity(
this,
Intent(
Intent.ACTION_VIEW,
Uri.parse(PLAY_STORE_WEB_URL_PREFIX + packageName),
),
Bundle(),
)
}
}
Loading

0 comments on commit ed36a82

Please sign in to comment.