Skip to content

Commit 716027c

Browse files
Merge branch 'main' into ea_profilingmanager_v2_docs_snippets_anr_casestudy
2 parents f86ffef + 95aeebd commit 716027c

File tree

19 files changed

+1246
-85
lines changed

19 files changed

+1246
-85
lines changed

compose/snippets/src/main/java/com/example/compose/snippets/layouts/AdaptiveLayoutSnippets.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import androidx.window.core.layout.WindowSizeClass
4848
// [START android_compose_adaptive_layouts_basic]
4949
@Composable
5050
fun MyApp(
51-
windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
51+
windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo(supportLargeAndXLargeWidth = true).windowSizeClass
5252
) {
5353
// Decide whether to show the top app bar based on window size class.
5454
val showTopAppBar = windowSizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND)

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ coil = "2.7.0"
3939
compileSdk = "36"
4040
compose-latest = "1.9.4"
4141
composeUiTooling = "1.5.4"
42-
coreSplashscreen = "1.0.1"
42+
coreSplashscreen = "1.2.0"
4343
coroutines = "1.10.2"
4444
dataStore = "1.1.7"
4545
datastoreCore = "1.1.7"

misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java

Lines changed: 19 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public class MainActivityJava extends Activity {
2727
// [END android_profiling_manager_anr_case_study_java_snippet_2]
2828
public static final String TAG = "ProfilingManager";
2929

30+
public static final String TAG = "ProfilingManager";
31+
3032
@Override
3133
public void onCreate(Bundle savedInstanceState) {
3234
super.onCreate(savedInstanceState);
@@ -96,101 +98,37 @@ public void recordWithTrigger() {
9698
new Consumer<ProfilingResult>() {
9799
@Override
98100
public void accept(ProfilingResult profilingResult) {
99-
// ...
100101
if (profilingResult.getErrorCode() == ProfilingResult.ERROR_NONE) {
101-
Log.d(TAG,
102-
"Received profiling result. file: " + profilingResult.getResultFilePath());
102+
Log.d(
103+
"ProfileTest",
104+
"Received profiling result file=" + profilingResult.getResultFilePath());
105+
setupProfileUploadWorker(profilingResult.getResultFilePath());
106+
} else {
107+
Log.e(
108+
"ProfileTest",
109+
"Profiling failed errorcode="
110+
+ profilingResult.getErrorCode()
111+
+ " errormsg="
112+
+ profilingResult.getErrorMessage());
103113
}
104114
}
105115
};
106116
profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback);
107117
profilingManager.addProfilingTriggers(triggers);
108118

119+
// [START_EXCLUDE silent]
109120
Choreographer.getInstance().postFrameCallback((f) -> {
110121
// This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted.
111122
reportFullyDrawn();
112123
});
124+
// [END_EXCLUDE silent]
113125
}
114126
// [END android_profiling_manager_triggered_trace_java]
115127

116-
// [START android_profiling_manager_anr_case_study_java_snippet_1]
117-
public void addANRTrigger() {
118-
ProfilingManager profilingManager = getApplicationContext().getSystemService(ProfilingManager.class);
119-
List<ProfilingTrigger> triggers = new ArrayList<>();
120-
ProfilingTrigger.Builder triggerBuilder = new ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_ANR);
121-
triggers.add(triggerBuilder.build());
122-
Executor mainExecutor = Executors.newSingleThreadExecutor();
123-
Consumer<ProfilingResult> resultCallback =
124-
profilingResult -> {
125-
// Handle uploading trace to your back-end
126-
};
127-
profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback);
128-
profilingManager.addProfilingTriggers(triggers);
128+
// [START android_profiling_manager_triggered_trace_setup_upload_job_java]
129+
public void setupProfileUploadWorker(String resultFilePath) {
130+
// Setup job to upload the profiling result file.
129131
}
130-
// [END android_profiling_manager_anr_case_study_java_snippet_1]
131-
132-
// [START android_profiling_manager_anr_case_study_java_snippet_2]
133-
public void setupButtonCallback() {
134-
findViewById(R.id.submit).setOnClickListener(submitButtonView -> {
135-
Trace.beginSection("MyApp:SubmitButton");
136-
onClickSubmit();
137-
Trace.endSection();
138-
});
139-
}
140-
141-
public void onClickSubmit() {
142-
prepareNetworkRequest();
143-
144-
boolean networkRequestSuccess = false;
145-
int maxAttempts = 10;
146-
while (!networkRequestSuccess && maxAttempts > 0) {
147-
networkRequestSuccess = performNetworkRequest(NETWORK_TIMEOUT_MILLISECS);
148-
maxAttempts--;
149-
}
150-
151-
if (networkRequestSuccess) {
152-
handleNetworkResponse();
153-
}
154-
}
155-
156-
boolean performNetworkRequest(int timeoutMiliseconds) {
157-
// [START_EXCLUDE]
158-
cpuIntensiveComputation(20);
159-
try {
160-
if (Math.random() < 0.2) {
161-
// Simulate performing a network request by waiting a random period of time
162-
int networkRequestTimeMs = (int)(Math.random() * timeoutMiliseconds);
163-
Thread.sleep(networkRequestTimeMs);
164-
return true;
165-
} else {
166-
// Simulate a timeout
167-
Thread.sleep(timeoutMiliseconds);
168-
}
169-
} catch (InterruptedException e) {}
170-
return false;
171-
// [END_EXCLUDE]
172-
}
173-
174-
// [START_EXCLUDE silent]
175-
void cpuIntensiveComputation(int durationMs) {
176-
long start = System.currentTimeMillis();
177-
while (System.currentTimeMillis() - start < durationMs) {}
178-
}
179-
// [END_EXCLUDE silent]
180-
181-
void prepareNetworkRequest() {
182-
// [START_EXCLUDE]
183-
cpuIntensiveComputation(1000);
184-
// [END_EXCLUDE]
185-
}
186-
187-
public void handleNetworkResponse() {
188-
Trace.beginSection("handleNetworkResponse");
189-
// [START_EXCLUDE]
190-
cpuIntensiveComputation(2000);
191-
// [END_EXCLUDE]
192-
Trace.endSection();
193-
}
194-
// [END android_profiling_manager_anr_case_study_java_snippet_2]
132+
// [END android_profiling_manager_triggered_trace_setup_upload_job_java]
195133
}
196134
}

misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,35 @@ class ProfilingManagerKotlinSnippets {
106106

107107
val resultCallback = Consumer<ProfilingResult> { profilingResult ->
108108
if (profilingResult.errorCode == ProfilingResult.ERROR_NONE) {
109-
Log.d(TAG, "Received profiling result. file: ${profilingResult.resultFilePath}")
109+
Log.d(
110+
"ProfileTest",
111+
"Received profiling result file=" + profilingResult.resultFilePath
112+
)
113+
setupProfileUploadWorker(profilingResult.resultFilePath)
114+
} else {
115+
Log.e(
116+
"ProfileTest",
117+
"Profiling failed errorcode=" + profilingResult.errorCode + " errormsg=" + profilingResult.errorMessage
118+
)
110119
}
111120
}
112121

113122
profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback)
114123
profilingManager.addProfilingTriggers(triggers)
115124

125+
// [START_EXCLUDE silent]
116126
Choreographer.getInstance().postFrameCallback { frameTimeNanos ->
117127
// This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted.
118128
reportFullyDrawn()
119129
}
130+
// [END_EXCLUDE silent]
120131
}
121132
// [END android_profiling_manager_triggered_trace]
133+
134+
// [START android_profiling_manager_triggered_trace_setup_upload_job]
135+
fun setupProfileUploadWorker(resultFilePath: String?) {
136+
// Setup job to upload the profiling result file.
137+
}
138+
// [END android_profiling_manager_triggered_trace_setup_upload_job]
122139
}
123140
}

wear/src/main/AndroidManifest.xml

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
See the License for the specific language governing permissions and
1515
limitations under the License.
1616
-->
17-
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
17+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
18+
xmlns:tools="http://schemas.android.com/tools">
1819

1920
<uses-permission android:name="android.permission.WAKE_LOCK" />
2021
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
@@ -29,6 +30,23 @@
2930
android:label="@string/app_name"
3031
android:supportsRtl="true"
3132
android:theme="@android:style/Theme.DeviceDefault">
33+
34+
<!-- [START android_wear_splash_manifest] -->
35+
<activity
36+
android:name=".snippets.SplashScreenActivity"
37+
android:exported="true"
38+
android:taskAffinity=""
39+
android:theme="@style/Theme.App.Starting">
40+
<!-- ... -->
41+
<!-- [START_EXCLUDE silent] -->
42+
<intent-filter>
43+
<action android:name="android.intent.action.MAIN" />
44+
<category android:name="android.intent.category.LAUNCHER" />
45+
</intent-filter>
46+
<!-- [END_EXCLUDE] -->
47+
</activity>
48+
<!-- [END android_wear_splash_manifest] -->
49+
3250
<uses-library
3351
android:name="com.google.android.wearable"
3452
android:required="true" />
@@ -328,6 +346,36 @@
328346
<!-- [END android_wear_complication_intent_filter] -->
329347
</activity>
330348

349+
<service
350+
android:name=".snippets.m3.tile.StateTile"
351+
android:label="@string/tile_label"
352+
android:description="@string/tile_description"
353+
android:icon="@mipmap/ic_launcher"
354+
android:exported="true"
355+
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
356+
<intent-filter>
357+
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
358+
</intent-filter>
359+
360+
<meta-data android:name="androidx.wear.tiles.PREVIEW"
361+
android:resource="@drawable/tile_preview" />
362+
</service>
363+
364+
<!-- [START android_wear_datalayerlistener_intent_filter] -->
365+
<service
366+
android:name=".snippets.datalayer.DataLayerListenerService"
367+
android:exported="true"
368+
tools:ignore="ExportedService" >
369+
<intent-filter>
370+
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
371+
<data
372+
android:scheme="wear"
373+
android:host="*"
374+
android:path="/start-activity" />
375+
</intent-filter>
376+
</service>
377+
<!-- [END android_wear_datalayerlistener_intent_filter] -->
378+
331379
</application>
332380

333381
</manifest>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2021 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.wear.snippets
18+
19+
import android.os.Bundle
20+
import androidx.activity.ComponentActivity
21+
import androidx.activity.compose.setContent
22+
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
23+
24+
// [START android_wear_splash_activity]
25+
class SplashScreenActivity : ComponentActivity() {
26+
override fun onCreate(savedInstanceState: Bundle?) {
27+
installSplashScreen()
28+
super.onCreate(savedInstanceState)
29+
30+
setContent {
31+
WearApp()
32+
}
33+
}
34+
}
35+
// [END android_wear_splash_activity]
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2025 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.wear.snippets.alwayson
18+
19+
import android.os.Bundle
20+
import androidx.activity.ComponentActivity
21+
import androidx.wear.ambient.AmbientLifecycleObserver
22+
23+
// [START android_wear_ongoing_activity_ambientlifecycleobserver]
24+
val ambientCallback = object : AmbientLifecycleObserver.AmbientLifecycleCallback {
25+
override fun onEnterAmbient(ambientDetails: AmbientLifecycleObserver.AmbientDetails) {
26+
// ... Called when moving from interactive mode into ambient mode.
27+
// Adjust UI for low-power state: dim colors, hide non-essential elements.
28+
}
29+
30+
override fun onExitAmbient() {
31+
// ... Called when leaving ambient mode, back into interactive mode.
32+
// Restore full UI.
33+
}
34+
35+
override fun onUpdateAmbient() {
36+
// ... Called by the system periodically (typically once per minute)
37+
// to allow the app to update its display while in ambient mode.
38+
}
39+
}
40+
// [END android_wear_ongoing_activity_ambientlifecycleobserver]
41+
42+
class AmbientLifecycleActivity : ComponentActivity() {
43+
44+
private val activity = this // rename so the snippet reads better
45+
// [START android_wear_ongoing_activity_ambientlifecycleobserver_oncreate]
46+
private val ambientObserver = AmbientLifecycleObserver(activity, ambientCallback)
47+
48+
override fun onCreate(savedInstanceState: Bundle?) {
49+
super.onCreate(savedInstanceState)
50+
lifecycle.addObserver(ambientObserver)
51+
52+
// ...
53+
}
54+
// [END android_wear_ongoing_activity_ambientlifecycleobserver_oncreate]
55+
56+
// [START android_wear_ongoing_activity_ambientlifecycleobserver_ondestroy]
57+
override fun onDestroy() {
58+
super.onDestroy()
59+
lifecycle.removeObserver(ambientObserver)
60+
61+
// ...
62+
}
63+
// [END android_wear_ongoing_activity_ambientlifecycleobserver_ondestroy]
64+
}

0 commit comments

Comments
 (0)