DO NOT SUBMIT

Add an R8-optimized example app

This change adds a new example project under examples/r8-optimized to demonstrate building an Android application with R8 optimization and resource shrinking enabled. The example includes both android_binary and android_application targets, along with their corresponding ProGuard configuration files.

PiperOrigin-RevId: 967426373
Change-Id: I1f2369c157adc91f3b6a391d2e9164febadf376a
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 0e06c8e..19e597d 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -18,6 +18,25 @@
 rules_flags: &rules_flags
   ? "--enable_bzlmod=false"
   ? "--enable_workspace=true"
+bzlmod_flags: &bzlmod_flags
+  <<: *rules_flags
+  ? "--enable_bzlmod"
+  ? "--enable_workspace=false"
+
+# These flags are used to build the app using the mobile-install aspect
+# Note that this does not actually run an install, just validates
+# that at least the build part of MI works.
+# Note to users: Do NOT run bazel build with these aspect and output_group
+# flags. These are for testing purposes only!
+mi_aspect_flags: &mi_aspect_flags
+  <<: *bzlmod_flags
+  # Do NOT put these in your bazelrc. Do NOT use these for mobile-install or build/run/test commands.
+  ? "--aspects=@rules_android//mobile_install:mi.bzl%MIASPECT"
+  ? "--output_groups=mobile_install_INTERNAL_,mobile_install_launcher_INTERNAL_,-_,-defaults"
+  # Latest bazel's JavaBuilder is build at java 21. For some reason the MI aspect + bazel build throws
+  # a classcode version conflict, and not the other tests in this presubmit, so the below flag
+  # is a crude workaround for that problem.
+  ? "--tool_java_runtime_version=21"
 
 tools: &tools
   name: "Tools"
@@ -110,6 +129,31 @@
     ? "--enable_workspace=false"
     ? "--//rules/flags:manifest_merge_order=legacy"
 
+basicapp: &basicapp
+  platform: ${{ platform }}
+  bazel: ${{ bazel }}
+  working_directory: examples/basicapp
+  build_flags:
+    <<: *rules_flags
+  build_targets:
+    - "//java/com/basicapp:basic_app"
+    - "//java/com/basicapp:basic_app_bundle"
+basicapp_bzlmod: &basicapp_bzlmod
+  <<: *basicapp
+  build_flags:
+    <<: *bzlmod_flags
+
+r8_app: &r8_app
+  <<: *basicapp
+  working_directory: examples/r8-optimized
+  build_targets:
+    - "//:r8_app"
+    - "//:r8_app_bundle"
+r8_app_bzlmod: &r8_app_bzlmod
+  <<: *r8_app
+  build_flags:
+    <<: *bzlmod_flags
+
 tasks:
   tools:
     platform: ${{ platform }}
@@ -155,69 +199,46 @@
 #    <<: *rules_coverage
   basicapp:
     name: "Basic app"
-    platform: ${{ platform }}
-    bazel: ${{ bazel }}
-    working_directory: examples/basicapp
-    build_flags:
-      <<: *rules_flags
-    build_targets:
-      - "//java/com/basicapp:basic_app"
-      - "//java/com/basicapp:basic_app_bundle"
+    <<: *basicapp
   basicapp_bzlmod:
     name: "Basic app bzlmod"
-    platform: ${{ platform }}
-    bazel: ${{ bazel }}
-    working_directory: examples/basicapp
-    build_flags:
-      <<: *rules_flags
-      ? "--enable_bzlmod"
-      ? "--enable_workspace=false"
-    build_targets:
-      - "//java/com/basicapp:basic_app"
-      - "//java/com/basicapp:basic_app_bundle"
+    <<: *basicapp_bzlmod
   windows_basicapp:
     name: "Basic app windows"
     platform: "windows"
-    bazel: ${{ bazel }}
-    working_directory: examples/basicapp
-    build_flags:
-      <<: *rules_flags
-    build_targets:
-      - "//java/com/basicapp:basic_app"
-      - "//java/com/basicapp:basic_app_bundle"
+    <<: *basicapp
   windows_basicapp_bzlmod:
     name: "Basic app windows bzlmod"
     platform: "windows"
-    bazel: ${{ bazel }}
-    working_directory: examples/basicapp
-    build_flags:
-      <<: *rules_flags
-      ? "--enable_bzlmod"
-      ? "--enable_workspace=false"
-    build_targets:
-      - "//java/com/basicapp:basic_app"
-      - "//java/com/basicapp:basic_app_bundle"
+    <<: *basicapp_bzlmod
   basicapp_mi_aspect:
     # Build the app using the mobile-install aspect
-    # Note that this does not actually run an install, just validates
-    # that at least the build part of MI works.
-    # Note to users: Do NOT run bazel build with these aspect and output_group
-    # flags. These are for testing purposes only!
     name: "Basic app mobile-install aspect"
-    platform: ${{ platform }}
-    bazel: ${{ bazel }}
-    working_directory: examples/basicapp
+    <<: *basicapp
     build_flags:
-      <<: *rules_flags
-      ? "--enable_bzlmod"
-      ? "--enable_workspace=false"
-      # Do NOT put these in your bazelrc. Do NOT use these for mobile-install or build/run/test commands.
-      ? "--aspects=@rules_android//mobile_install:mi.bzl%MIASPECT"
-      ? "--output_groups=mobile_install_INTERNAL_,mobile_install_launcher_INTERNAL_,-_,-defaults"
-      # Latest bazel's JavaBuilder is build at java 21. For some reason the MI aspect + bazel build throws
-      # a classcode version conflict, and not the other tests in this presubmit, so the below flag
-      # is a crude workaround for that problem.
-      ? "--tool_java_runtime_version=21"
+      <<: *mi_aspect_flags
     build_targets:
       - "//java/com/basicapp:basic_app"
+  r8_app:
+    name: "R8 app"
+    <<: *r8_app
+  r8_app_bzlmod:
+    name: "R8 app bzlmod"
+    <<: *r8_app_bzlmod
+  windows_r8_app:
+    name: "R8 app windows"
+    platform: "windows"
+    <<: *r8_app
+  windows_r8_app_bzlmod:
+    name: "R8 app windows bzlmod"
+    platform: "windows"
+    <<: *r8_app_bzlmod
+  r8_app_mi_aspect:
+    # Build the app using the mobile-install aspect
+    name: "R8 app mobile-install aspect"
+    <<: *r8_app
+    build_flags:
+      <<: *mi_aspect_flags
+    build_targets:
+      - "//:r8_app"
 
diff --git a/examples/r8-optimized/.bazelrc b/examples/r8-optimized/.bazelrc
new file mode 100644
index 0000000..08999d7
--- /dev/null
+++ b/examples/r8-optimized/.bazelrc
@@ -0,0 +1,37 @@
+# Config for library desugaring
+common:core_library_desugaring --desugar_java8_libs
+
+# Flags to enable mobile-install v3
+mobile-install --mode=skylark --mobile_install_aspect=@rules_android//mobile_install:mi.bzl --mobile_install_supported_rules=android_binary
+# Required to build Android builder tools
+common --java_language_version=17
+common --java_runtime_version=17
+common --tool_java_language_version=17
+# Required to invoke the Studio deployer jar
+common --tool_java_runtime_version=17
+
+# Workaround for a rules_java + bazel < 8.3.0 issue. It should only be relevant
+# for bazel@HEAD and rolling releases.
+# https://github.com/bazelbuild/bazel/pull/26119
+common --repositories_without_autoloads=bazel_features_version,bazel_features_globals,cc_compatibility_proxy
+
+# Newer versions of protobuf require downstream transitive projects to set C++ language version flags.
+common:linux --cxxopt=-std=c++17
+common:linux --host_cxxopt=-std=c++17
+common:macos --cxxopt=-std=c++17
+common:macos --host_cxxopt=-std=c++17
+common:windows --cxxopt=/std:c++17
+common:windows --host_cxxopt=/std:c++17
+# Suppress warnings from external repos
+common:linux --per_file_copt=external/.*@-w
+common:linux --host_per_file_copt=external/.*@-w
+common:macos --per_file_copt=external/.*@-w
+common:macos --host_per_file_copt=external/.*@-w
+common:windows --per_file_copt=external/.*@/w
+common:windows --host_per_file_copt=external/.*@/w
+
+# Enable protobuf MSVC support on Windows
+build:windows --define=protobuf_allow_msvc=true
+
+common --enable_platform_specific_config
+
diff --git a/examples/r8-optimized/.gitignore b/examples/r8-optimized/.gitignore
new file mode 100644
index 0000000..63f1fef
--- /dev/null
+++ b/examples/r8-optimized/.gitignore
@@ -0,0 +1 @@
+*.lock
diff --git a/examples/r8-optimized/BUILD b/examples/r8-optimized/BUILD
new file mode 100644
index 0000000..bfc96d7
--- /dev/null
+++ b/examples/r8-optimized/BUILD
@@ -0,0 +1,30 @@
+load(
+    "@rules_android//android:rules.bzl",
+    "android_application",
+    "android_binary",
+)
+
+android_binary(
+    name = "r8_app",
+    custom_package = "com.r8app",
+    manifest = "//java/com/r8app:AndroidManifest.xml",
+    proguard_generate_mapping = True,
+    proguard_specs = [
+        "proguard-android-optimize.txt",
+        "proguard-rules.pro",
+    ],
+    shrink_resources = True,
+    deps = ["//java/com/r8app:r8_lib"],
+)
+
+android_application(
+    name = "r8_app_bundle",
+    # bundle_config_file or feature_modules must be specified to get an aab
+    bundle_config_file = "//java/com/r8app:bundle_config.pb.json",
+    manifest = "//java/com/r8app:AndroidManifest.xml",
+    manifest_values = {
+        "applicationId": "com.r8app",
+        "versionCode": "1",
+    },
+    deps = ["//java/com/r8app:r8_lib"],
+)
diff --git a/examples/r8-optimized/MODULE.bazel b/examples/r8-optimized/MODULE.bazel
new file mode 100644
index 0000000..717217b
--- /dev/null
+++ b/examples/r8-optimized/MODULE.bazel
@@ -0,0 +1,38 @@
+module(
+    name = "r8app",
+)
+
+bazel_dep(name = "rules_java", version = "9.0.3")
+bazel_dep(name = "bazel_skylib", version = "1.8.1")
+bazel_dep(name = "rules_jvm_external", version = "6.7")
+
+bazel_dep(
+    name = "rules_android",
+    version = "0.8.0",
+)
+
+
+# Local override to enable this app to be used for rules_android presubmit
+# integration testing. If you're basing your app's MODULE file on this
+# example, you do *not* need the following override.
+local_path_override(
+    module_name = "rules_android",
+    path = "../../",
+)
+
+remote_android_extensions = use_extension(
+    "@rules_android//bzlmod_extensions:android_extensions.bzl",
+    "remote_android_tools_extensions")
+use_repo(remote_android_extensions, "android_tools")
+
+android_sdk_repository_extension = use_extension("@rules_android//rules/android_sdk_repository:rule.bzl", "android_sdk_repository_extension")
+use_repo(android_sdk_repository_extension, "androidsdk")
+
+register_toolchains("@androidsdk//:sdk-toolchain", "@androidsdk//:all")
+
+# NOTE: It's not actually necessary to add protobuf as a dep to the example app.
+# This is only here to enable setting --@protobuf//bazel/flags:prefer_prebuilt_protoc
+# in order to make internal presubmit faster. This quirk is really only relevant
+# to protobuf ~33.4 or so, as that flag will become true by default in 34+.
+# See https://protobuf.dev/news/2026-01-16/
+bazel_dep(name = "protobuf", version = "33.4", repo_name = "com_google_protobuf")
diff --git a/examples/r8-optimized/README.md b/examples/r8-optimized/README.md
new file mode 100644
index 0000000..0f809a3
--- /dev/null
+++ b/examples/r8-optimized/README.md
@@ -0,0 +1,60 @@
+# R8 Optimized Android App Example
+
+This example demonstrates how to build and optimize a simple Android application using **R8**.
+
+## What is R8 and Why Use It?
+
+[R8](https://developer.android.com/build/shrink-code) is the code shrinker, optimizer, and dexer for Android developed by Google. In a single step, R8 handles:
+
+- **Code Shrinking (Tree Shaking)**: Detects and safely removes unused classes, methods, fields, and attributes from your application and third-party dependencies.
+- **Code Optimization**: Inspects and rewrites code to improve runtime performance, inline methods, remove dead branches, and eliminate unused arguments.
+- **Name Obfuscation**: Renames types and members with short names to minimize DEX size.
+- **Resource Shrinking**: When paired with `shrink_resources = True`, removes unused Android resources that are no longer referenced after code shrinking.
+- **Dexing**: Directly converts Java bytecode to optimized Android DEX format.
+
+Using R8 significantly reduces APK/AAB download and install sizes and memory footprint, decreases app startup time, and keeps method counts within optimal limits.
+
+For in-depth details on configuring ProGuard/R8 keep rules and optimization flags, see [docs/r8-optimization.md](../../docs/r8-optimization.md).
+
+## Building the Targets
+
+Ensure that the `ANDROID_HOME` environment variable is set to the path of your Android SDK:
+
+```bash
+export ANDROID_HOME=/path/to/android/sdk
+```
+
+### 1. Build the Optimized APK (`android_binary`)
+
+To build the standalone optimized APK:
+
+```bash
+bazel build //:r8_app
+```
+
+Output: `bazel-bin/r8_app.apk`
+
+### 2. Build the Optimized Android App Bundle (`android_application`)
+
+To build the optimized Android App Bundle (AAB):
+
+```bash
+bazel build //:r8_app_bundle
+```
+
+Output: `bazel-bin/r8_app_bundle_unsigned.aab`
+
+### 3. Fast Incremental Installation with Mobile-Install
+
+To build and install the application directly onto a connected Android device or running emulator:
+
+```bash
+bazel mobile-install //:r8_app
+```
+
+## Configuration Files
+
+- **`BUILD`**: Defines the `android_binary` (`r8_app`) and `android_application` (`r8_app_bundle`) targets with `proguard_specs` and `shrink_resources = True`.
+- **`proguard-rules.pro`**: App-specific keep rules for preserving entry points like `MainActivity`.
+- **`proguard-android-optimize.txt`**: Default Android optimization rules for R8.
+- **`.bazelrc`**: Flags and settings needed to build the app with `rules_android`.
\ No newline at end of file
diff --git a/examples/r8-optimized/WORKSPACE.bzlmod b/examples/r8-optimized/WORKSPACE.bzlmod
new file mode 100644
index 0000000..5321e34
--- /dev/null
+++ b/examples/r8-optimized/WORKSPACE.bzlmod
@@ -0,0 +1 @@
+workspace(name = "r8app")
diff --git a/examples/r8-optimized/java/com/r8app/AndroidManifest.xml b/examples/r8-optimized/java/com/r8app/AndroidManifest.xml
new file mode 100644
index 0000000..f9d853e
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.r8app" >
+
+    <uses-sdk
+        android:minSdkVersion="21"
+        android:targetSdkVersion="36" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name" >
+        <activity
+            android:name="com.r8app.MainActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/examples/r8-optimized/java/com/r8app/BUILD b/examples/r8-optimized/java/com/r8app/BUILD
new file mode 100644
index 0000000..62f8821
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/BUILD
@@ -0,0 +1,17 @@
+load(
+    "@rules_android//android:rules.bzl",
+    "android_library",
+)
+
+exports_files([
+    "AndroidManifest.xml",
+    "bundle_config.pb.json",
+])
+
+android_library(
+    name = "r8_lib",
+    srcs = ["MainActivity.java"],
+    manifest = "AndroidManifest.xml",
+    resource_files = glob(["res/**"]),
+    visibility = ["//:__pkg__"],
+)
diff --git a/examples/r8-optimized/java/com/r8app/MainActivity.java b/examples/r8-optimized/java/com/r8app/MainActivity.java
new file mode 100644
index 0000000..442b823
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/MainActivity.java
@@ -0,0 +1,59 @@
+// Copyright 2022 The Bazel Authors. All rights reserved.
+//
+// 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
+//
+//    http://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.r8app;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * The main activity of the R8 Sample App.
+ */
+public class MainActivity extends Activity {
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.main_activity);
+
+    final Button buttons[] = {
+      findViewById(R.id.button_id_fizz), findViewById(R.id.button_id_buzz),
+    };
+
+    for (var b : buttons) {
+      b.setOnClickListener(
+          new View.OnClickListener() {
+            public void onClick(View v) {
+              TextView tv = findViewById(R.id.text_hello);
+              if (v.getId() == R.id.button_id_fizz) {
+                tv.setText("fizz");
+              } else if (v.getId() == R.id.button_id_buzz) {
+                tv.setText("buzz");
+              }
+            }
+          });
+    }
+  }
+
+  @Override
+  public boolean onCreateOptionsMenu(Menu menu) {
+    // Inflate the menu; this adds items to the action bar if it is present.
+    getMenuInflater().inflate(R.menu.menu, menu);
+    return true;
+  }
+}
diff --git a/examples/r8-optimized/java/com/r8app/bundle_config.pb.json b/examples/r8-optimized/java/com/r8app/bundle_config.pb.json
new file mode 100644
index 0000000..2d5b540
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/bundle_config.pb.json
@@ -0,0 +1,12 @@
+// https://github.com/google/bundletool/blob/master/src/main/proto/config.proto
+{
+  "optimizations": {
+    "splitsConfig": {
+      "splitDimension": [
+        {
+          "value": "LANGUAGE"
+        }
+      ]
+    }
+  }
+}
diff --git a/examples/r8-optimized/java/com/r8app/res/drawable-hdpi/ic_launcher.png b/examples/r8-optimized/java/com/r8app/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..6ab2add
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/examples/r8-optimized/java/com/r8app/res/drawable-mdpi/ic_launcher.png b/examples/r8-optimized/java/com/r8app/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c0a73c3
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/examples/r8-optimized/java/com/r8app/res/drawable-xhdpi/ic_launcher.png b/examples/r8-optimized/java/com/r8app/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..014b0f1
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/examples/r8-optimized/java/com/r8app/res/drawable-xxhdpi/ic_launcher.png b/examples/r8-optimized/java/com/r8app/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..20703a1
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/examples/r8-optimized/java/com/r8app/res/layout/main_activity.xml b/examples/r8-optimized/java/com/r8app/res/layout/main_activity.xml
new file mode 100644
index 0000000..f84199c
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/res/layout/main_activity.xml
@@ -0,0 +1,23 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/text_hello"
+        android:text="@string/hello_world"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+     <Button
+        android:id="@+id/button_id_fizz"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:text="fizz" />
+     <Button
+        android:id="@+id/button_id_buzz"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:text="buzz" />
+
+</LinearLayout>
diff --git a/examples/r8-optimized/java/com/r8app/res/menu/menu.xml b/examples/r8-optimized/java/com/r8app/res/menu/menu.xml
new file mode 100644
index 0000000..02ec528
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/res/menu/menu.xml
@@ -0,0 +1,8 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:context="com.r8app.MainActivity" >
+    <item android:id="@+id/action_settings"
+        android:title="@string/action_settings"
+        android:orderInCategory="100" />
+</menu>
diff --git a/examples/r8-optimized/java/com/r8app/res/values-b+es/strings.xml b/examples/r8-optimized/java/com/r8app/res/values-b+es/strings.xml
new file mode 100644
index 0000000..986ffd6
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/res/values-b+es/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="hello_world" translatable="false">¡Hola Mundo!</string>
+</resources>
diff --git a/examples/r8-optimized/java/com/r8app/res/values/dimens.xml b/examples/r8-optimized/java/com/r8app/res/values/dimens.xml
new file mode 100644
index 0000000..47c8224
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/res/values/dimens.xml
@@ -0,0 +1,5 @@
+<resources>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/examples/r8-optimized/java/com/r8app/res/values/strings.xml b/examples/r8-optimized/java/com/r8app/res/values/strings.xml
new file mode 100644
index 0000000..31dac87
--- /dev/null
+++ b/examples/r8-optimized/java/com/r8app/res/values/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name" translatable="false">r8app</string>
+    <string name="hello_world" translatable="false">Hello world!</string>
+    <string name="action_settings" translatable="false">Settings</string>
+
+</resources>
diff --git a/examples/r8-optimized/proguard-android-optimize.txt b/examples/r8-optimized/proguard-android-optimize.txt
new file mode 100644
index 0000000..9894014
--- /dev/null
+++ b/examples/r8-optimized/proguard-android-optimize.txt
@@ -0,0 +1,84 @@
+# These are the baseline recommended ProGuard / R8 settings for Android apps.
+# See https://developer.android.com/r/tools/r8/keep-rules for more details.
+# Do not edit this file. Add custom rules for your project to proguard-rules.pro.
+
+-allowaccessmodification
+
+# Preserve some attributes that may be required for reflection.
+-keepattributes AnnotationDefault,
+                EnclosingMethod,
+                InnerClasses,
+                RuntimeVisibleAnnotations,
+                RuntimeVisibleParameterAnnotations,
+                RuntimeVisibleTypeAnnotations,
+                Signature
+
+-keep public class com.google.vending.licensing.ILicensingService
+-keep public class com.android.vending.licensing.ILicensingService
+-keep public class com.google.android.vending.licensing.ILicensingService
+-dontnote com.android.vending.licensing.ILicensingService
+-dontnote com.google.vending.licensing.ILicensingService
+-dontnote com.google.android.vending.licensing.ILicensingService
+
+# For native methods, see https://www.guardsquare.com/manual/configuration/examples#native
+-keepclasseswithmembernames,includedescriptorclasses class * {
+    native <methods>;
+}
+
+# Keep setters in Views so that animations can still work.
+-keepclassmembers public class * extends android.view.View {
+    void set*(***);
+    *** get*();
+}
+
+# We want to keep methods in Activity that could be used in the XML attribute onClick.
+-keepclassmembers class * extends android.app.Activity {
+    public void *(android.view.View);
+}
+
+# For enumeration classes, see https://www.guardsquare.com/manual/configuration/examples#enumerations
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keepclassmembers class * implements android.os.Parcelable {
+    public static final ** CREATOR;
+}
+
+# Preserve annotated Javascript interface methods.
+-keepclassmembers class * {
+    @android.webkit.JavascriptInterface <methods>;
+}
+
+# The support libraries contains references to newer platform versions.
+# Don't warn about those in case this app is linking against an older
+# platform version. We know about them, and they are safe.
+-dontnote android.support.**
+-dontnote androidx.**
+-dontwarn android.support.**
+-dontwarn androidx.**
+
+# Understand the @Keep support annotation.
+-keep class android.support.annotation.Keep
+
+-keep @android.support.annotation.Keep class * {*;}
+
+-keepclasseswithmembers class * {
+    @android.support.annotation.Keep <methods>;
+}
+
+-keepclasseswithmembers class * {
+    @android.support.annotation.Keep <fields>;
+}
+
+-keepclasseswithmembers class * {
+    @android.support.annotation.Keep <init>(...);
+}
+
+# These classes are duplicated between android.jar and org.apache.http.legacy.jar.
+-dontnote org.apache.http.**
+-dontnote android.net.http.**
+
+# These classes are duplicated between android.jar and core-lambda-stubs.jar.
+-dontnote java.lang.invoke.**
diff --git a/examples/r8-optimized/proguard-rules.pro b/examples/r8-optimized/proguard-rules.pro
new file mode 100644
index 0000000..f8fcb03
--- /dev/null
+++ b/examples/r8-optimized/proguard-rules.pro
@@ -0,0 +1,6 @@
+# Proguard / R8 configuration for r8app
+
+# Keep the entry point activity
+-keep class com.r8app.MainActivity {
+    <init>(...);
+}