Skip to content

Commit 0e26519

Browse files
authored
Install prompt snippet (#861)
* Install prompt snippet * Updates dependencies * Moves module
1 parent b17a509 commit 0e26519

14 files changed

Lines changed: 368 additions & 0 deletions

File tree

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ compose-latest = "1.10.5"
4747
composeUiTooling = "1.5.6"
4848
coreSplashscreen = "1.2.0"
4949
coroutines = "1.10.2"
50+
crossdeviceprompt = "0.0.1"
5051
dataStore = "1.2.1"
5152
datastoreCore = "1.2.1"
5253
datastorePreferencesRxjava2 = "1.2.1"
@@ -227,6 +228,7 @@ billing = { module = "com.android.billingclient:billing", version.ref = "playbil
227228
coil-kt-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
228229
compose-foundation = { module = "androidx.wear.compose:compose-foundation", version.ref = "wearComposeFoundation" }
229230
compose-ui-tooling = { module = "androidx.wear.compose:compose-ui-tooling", version.ref = "composeUiTooling" }
231+
crossdeviceprompt = { module = "com.google.android.play:crossdeviceprompt", version.ref = "crossdeviceprompt" }
230232
firebase-ai = { module = "com.google.firebase:firebase-ai" }
231233
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" }
232234
glide-compose = { module = "com.github.bumptech.glide:compose", version.ref = "glide" }

installprompt/.gitignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Android-specific
2+
/build
3+
/captures
4+
*.iml
5+
.externalNativeBuild
6+
.kotlin
7+
8+
# Release artifacts
9+
/release
10+
*.aab
11+
*.apk
12+
13+
# Local configuration
14+
local.properties
15+
16+
# OS-specific
17+
.DS_Store

installprompt/build.gradle.kts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
plugins {
2+
id("com.android.application")
3+
id("org.jetbrains.kotlin.plugin.compose")
4+
}
5+
6+
android {
7+
namespace = "com.example.crossdeviceinstallprompt"
8+
compileSdk = libs.versions.compileSdk.get().toInt()
9+
10+
defaultConfig {
11+
applicationId = "com.example.crossdeviceinstallprompt"
12+
minSdk = libs.versions.minSdk.get().toInt()
13+
targetSdk = libs.versions.targetSdk.get().toInt()
14+
versionCode = 7
15+
versionName = "1.0"
16+
}
17+
18+
buildTypes {
19+
release {
20+
isMinifyEnabled = false
21+
proguardFiles(
22+
getDefaultProguardFile("proguard-android-optimize.txt"),
23+
"proguard-rules.pro"
24+
)
25+
}
26+
}
27+
compileOptions {
28+
sourceCompatibility = JavaVersion.VERSION_17
29+
targetCompatibility = JavaVersion.VERSION_17
30+
}
31+
kotlin {
32+
jvmToolchain(17)
33+
}
34+
buildFeatures {
35+
compose = true
36+
}
37+
}
38+
39+
dependencies {
40+
implementation(platform(libs.androidx.compose.bom))
41+
42+
implementation(libs.androidx.core.ktx)
43+
implementation(libs.androidx.lifecycle.runtime)
44+
implementation(libs.androidx.activity.compose)
45+
implementation(libs.androidx.compose.ui)
46+
implementation(libs.androidx.compose.ui)
47+
implementation(libs.androidx.compose.ui.graphics)
48+
implementation(libs.androidx.compose.ui.tooling.preview)
49+
implementation(libs.androidx.compose.material3)
50+
51+
// [START android_installprompt_dependency]
52+
implementation(libs.crossdeviceprompt)
53+
// [END android_installprompt_dependency]
54+
55+
implementation(libs.kotlinx.coroutines.play.services)
56+
}

installprompt/proguard-rules.pro

Whitespace-only changes.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2026 The Android Open Source Project
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
18+
19+
<application
20+
android:allowBackup="true"
21+
android:icon="@mipmap/ic_launcher"
22+
android:label="Cross-Device Install Prompt"
23+
android:roundIcon="@mipmap/ic_launcher_round"
24+
android:supportsRtl="true"
25+
android:theme="@style/Theme.CrossDeviceInstallPrompt">
26+
<activity
27+
android:name=".MainActivity"
28+
android:exported="true"
29+
android:theme="@style/Theme.CrossDeviceInstallPrompt">
30+
<intent-filter>
31+
<action android:name="android.intent.action.MAIN" />
32+
<category android:name="android.intent.category.LAUNCHER" />
33+
</intent-filter>
34+
</activity>
35+
</application>
36+
37+
</manifest>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2026 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.crossdeviceinstallprompt
18+
19+
import android.app.Activity
20+
import android.os.Bundle
21+
import android.util.Log
22+
import androidx.activity.ComponentActivity
23+
import androidx.activity.compose.LocalActivity
24+
import androidx.activity.compose.setContent
25+
import androidx.activity.enableEdgeToEdge
26+
import androidx.compose.foundation.layout.Box
27+
import androidx.compose.foundation.layout.fillMaxSize
28+
import androidx.compose.foundation.layout.padding
29+
import androidx.compose.material3.Button
30+
import androidx.compose.material3.MaterialTheme
31+
import androidx.compose.material3.Scaffold
32+
import androidx.compose.material3.Text
33+
import androidx.compose.runtime.Composable
34+
import androidx.compose.runtime.rememberCoroutineScope
35+
import androidx.compose.ui.Alignment
36+
import androidx.compose.ui.Modifier
37+
import androidx.compose.ui.tooling.preview.Preview
38+
import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptException
39+
import com.google.android.play.core.crossdeviceprompt.CrossDevicePromptManagerFactory
40+
import com.google.android.play.core.crossdeviceprompt.model.CrossDevicePromptInstallationRequest
41+
import kotlinx.coroutines.launch
42+
import kotlinx.coroutines.tasks.await
43+
44+
const val TAG = "CrossDeviceInstallPrompt"
45+
46+
class MainActivity : ComponentActivity() {
47+
override fun onCreate(savedInstanceState: Bundle?) {
48+
super.onCreate(savedInstanceState)
49+
enableEdgeToEdge()
50+
setContent {
51+
MaterialTheme {
52+
App()
53+
}
54+
}
55+
}
56+
}
57+
58+
@Composable
59+
fun App() {
60+
val activity = LocalActivity.current
61+
val scope = rememberCoroutineScope()
62+
63+
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
64+
Box(
65+
modifier = Modifier
66+
.fillMaxSize()
67+
.padding(innerPadding),
68+
contentAlignment = Alignment.Center
69+
) {
70+
Button(onClick = {
71+
scope.launch {
72+
launchCrossDeviceInstallPrompt(activity!!)
73+
}
74+
}) {
75+
Text(text = "Launch prompt!")
76+
}
77+
}
78+
}
79+
}
80+
81+
private suspend fun launchCrossDeviceInstallPrompt(activity: Activity) {
82+
// [START android_installprompt_launch]
83+
val crossDevicePromptManager = CrossDevicePromptManagerFactory.create(activity)
84+
val request = CrossDevicePromptInstallationRequest.create()
85+
86+
try {
87+
val info = crossDevicePromptManager.requestInstallationPromptFlow(request).await()
88+
crossDevicePromptManager.launchPromptFlow(activity, info).await()
89+
} catch (e: CrossDevicePromptException) {
90+
Log.e(TAG, "Cross-device prompt failed with error: ${e.errorCode}", e)
91+
}
92+
// [END android_installprompt_launch]
93+
}
94+
95+
@Preview(showBackground = true)
96+
@Composable
97+
fun AppPreview() {
98+
MaterialTheme {
99+
App()
100+
}
101+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2026 The Android Open Source Project
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
18+
android:width="108dp"
19+
android:height="108dp"
20+
android:viewportWidth="108"
21+
android:viewportHeight="108">
22+
<path
23+
android:fillColor="#3DDC84"
24+
android:pathData="M0,0h108v108h-108z" />
25+
</vector>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2026 The Android Open Source Project
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
18+
android:width="108dp"
19+
android:height="108dp"
20+
android:viewportWidth="108"
21+
android:viewportHeight="108">
22+
<path
23+
android:fillColor="#FFFFFF"
24+
android:pathData="M30,30h48v48h-48z" />
25+
</vector>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2026 The Android Open Source Project
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
18+
<background android:drawable="@drawable/ic_launcher_background" />
19+
<foreground android:drawable="@drawable/ic_launcher_foreground" />
20+
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
21+
</adaptive-icon>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2026 The Android Open Source Project
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
18+
<background android:drawable="@drawable/ic_launcher_background" />
19+
<foreground android:drawable="@drawable/ic_launcher_foreground" />
20+
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
21+
</adaptive-icon>

0 commit comments

Comments
 (0)