├── .gitignore ├── GameActivity ├── Cargo.toml ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── co │ │ │ └── realfit │ │ │ └── example │ │ │ └── MainActivity.java │ │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ └── values │ │ ├── colors.xml │ │ └── themes.xml ├── build.gradle ├── build.sh ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── clipboard.rs │ ├── controls.rs │ ├── frag.wgsl │ ├── java.rs │ ├── lib.rs │ ├── scene.rs │ └── vert.wgsl ├── LICENSE ├── NativeActivity ├── Cargo.toml ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── co │ │ │ └── realfit │ │ │ └── example │ │ │ └── MainActivity.java │ │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ └── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp ├── build.gradle ├── build.sh ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── clipboard.rs │ ├── controls.rs │ ├── frag.wgsl │ ├── java.rs │ ├── lib.rs │ ├── scene.rs │ └── vert.wgsl ├── README.md ├── pixel_1.png ├── pixel_2.png ├── pixel_3.png ├── watch_1.png ├── watch_2.png └── watch_3.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | local.properties 4 | .DS_Store 5 | build 6 | captures 7 | .externalNativeBuild 8 | .cxx 9 | *.so 10 | 11 | .idea 12 | jniLibs 13 | Cargo.lock 14 | target 15 | -------------------------------------------------------------------------------- /GameActivity/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "android-iced-example" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | name = "example" 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | log = "0.4" 12 | android_logger = "0.14.1" 13 | android-activity = { version = "0.6", features = ["game-activity"] } 14 | ndk-context = "0.1" 15 | jni = { version = "0.21", features = ["invocation"] } 16 | # ndk-sys = "0.6.0" 17 | # ndk = "0.9.0" 18 | futures = "0.3" 19 | 20 | [dependencies.iced_core] 21 | git = "https://github.com/ibaryshnikov/iced.git" 22 | rev = "009bf6c" 23 | # path = "../../iced/core" 24 | 25 | [dependencies.iced_widget] 26 | git = "https://github.com/ibaryshnikov/iced.git" 27 | rev = "009bf6c" 28 | # path = "../../iced/widget" 29 | features = ["wgpu"] 30 | 31 | [dependencies.iced_winit] 32 | git = "https://github.com/ibaryshnikov/iced.git" 33 | rev = "009bf6c" 34 | # path = "../../iced/winit" 35 | 36 | [dependencies.iced_wgpu] 37 | git = "https://github.com/ibaryshnikov/iced.git" 38 | rev = "009bf6c" 39 | # path = "../../iced/wgpu" 40 | 41 | [patch.crates-io] 42 | softbuffer = { git = "https://github.com/MarijnS95/softbuffer.git", rev = "d5cc95a" } # branch = "android" 43 | # android-activity = { path = "../../android-activity/android-activity" } 44 | -------------------------------------------------------------------------------- /GameActivity/README.md: -------------------------------------------------------------------------------- 1 | # Example of building android app with iced 2 | 3 | This is a `GameActivity` example, based on `agdk-mainloop` from 4 | [android-activity](https://github.com/rust-mobile/android-activity) 5 | 6 | **Important:** there's an [issue](https://github.com/rust-mobile/android-activity/issues/79) 7 | with event filters in emulator. To use touch screen in emulator, 8 | you'll have to clone `android-activity` and change the default filter. 9 | 10 | 11 | ## Building and running 12 | 13 | Check `android-activity` crate for detailed instructions. 14 | During my tests I was running the following command and using android studio afterwards: 15 | 16 | ```bash 17 | export ANDROID_NDK_HOME="path/to/ndk" 18 | export ANDROID_HOME="path/to/sdk" 19 | 20 | rustup target add x86_64-linux-android 21 | cargo install cargo-ndk 22 | 23 | cargo ndk -t x86_64 -o app/src/main/jniLibs/ build 24 | ``` 25 | -------------------------------------------------------------------------------- /GameActivity/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /GameActivity/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | ndkVersion "25.2.9519653" 7 | compileSdk 35 8 | 9 | defaultConfig { 10 | applicationId "co.realfit.example" 11 | minSdk 28 12 | targetSdk 35 13 | versionCode 1 14 | versionName "1.0" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | debug { 23 | minifyEnabled false 24 | //packagingOptions { 25 | // doNotStrip '**/*.so' 26 | //} 27 | //debuggable true 28 | } 29 | } 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | namespace 'co.realfit.example' 35 | } 36 | 37 | dependencies { 38 | 39 | implementation "androidx.core:core:1.5.0" 40 | implementation "androidx.constraintlayout:constraintlayout:2.0.4" 41 | implementation 'androidx.fragment:fragment:1.2.5' 42 | implementation 'com.google.oboe:oboe:1.5.0' 43 | 44 | // To use the Android Frame Pacing library 45 | //implementation "androidx.games:games-frame-pacing:1.9.1" 46 | 47 | // To use the Android Performance Tuner 48 | //implementation "androidx.games:games-performance-tuner:1.5.0" 49 | 50 | // To use the Games Activity library 51 | implementation "androidx.games:games-activity:2.0.2" 52 | 53 | // To use the Games Controller Library 54 | //implementation "androidx.games:games-controller:2.0.2" 55 | 56 | // To use the Games Text Input Library 57 | //implementation "androidx.games:games-text-input:2.0.2" 58 | } 59 | 60 | -------------------------------------------------------------------------------- /GameActivity/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /GameActivity/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /GameActivity/app/src/main/java/co/realfit/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package co.realfit.example; 2 | 3 | import android.content.ClipData; 4 | import android.content.ClipboardManager; 5 | import android.content.Context; 6 | import androidx.core.view.WindowCompat; 7 | import androidx.core.view.WindowInsetsCompat; 8 | import androidx.core.view.WindowInsetsControllerCompat; 9 | 10 | import com.google.androidgamesdk.GameActivity; 11 | 12 | import android.os.Bundle; 13 | import android.util.Log; 14 | import android.view.inputmethod.InputMethodManager; 15 | import android.content.pm.PackageManager; 16 | import android.os.Build.VERSION; 17 | import android.os.Build.VERSION_CODES; 18 | import android.view.View; 19 | import android.view.WindowManager; 20 | 21 | public class MainActivity extends GameActivity { 22 | 23 | static { 24 | // Load the STL first to workaround issues on old Android versions: 25 | // "if your app targets a version of Android earlier than Android 4.3 26 | // (Android API level 18), 27 | // and you use libc++_shared.so, you must load the shared library before any other 28 | // library that depends on it." 29 | // See https://developer.android.com/ndk/guides/cpp-support#shared_runtimes 30 | //System.loadLibrary("c++_shared"); 31 | 32 | // Load the native library. 33 | // The name "android-game" depends on your CMake configuration, must be 34 | // consistent here and inside AndroidManifect.xml 35 | System.loadLibrary("example"); 36 | } 37 | 38 | private void hideSystemUI() { 39 | // This will put the game behind any cutouts and waterfalls on devices which have 40 | // them, so the corresponding insets will be non-zero. 41 | if (VERSION.SDK_INT >= VERSION_CODES.P) { 42 | getWindow().getAttributes().layoutInDisplayCutoutMode 43 | = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 44 | } 45 | // From API 30 onwards, this is the recommended way to hide the system UI, rather than 46 | // using View.setSystemUiVisibility. 47 | View decorView = getWindow().getDecorView(); 48 | WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(getWindow(), 49 | decorView); 50 | controller.hide(WindowInsetsCompat.Type.systemBars()); 51 | controller.hide(WindowInsetsCompat.Type.displayCutout()); 52 | controller.setSystemBarsBehavior( 53 | WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); 54 | } 55 | 56 | @Override 57 | protected void onCreate(Bundle savedInstanceState) { 58 | // When true, the app will fit inside any system UI windows. 59 | // When false, we render behind any system UI windows. 60 | WindowCompat.setDecorFitsSystemWindows(getWindow(), false); 61 | hideSystemUI(); 62 | // You can set IME fields here or in native code using GameActivity_setImeEditorInfoFields. 63 | // We set the fields in native_engine.cpp. 64 | // super.setImeEditorInfoFields(InputType.TYPE_CLASS_TEXT, 65 | // IME_ACTION_NONE, IME_FLAG_NO_FULLSCREEN ); 66 | super.onCreate(savedInstanceState); 67 | } 68 | 69 | protected void onResume() { 70 | super.onResume(); 71 | hideSystemUI(); 72 | } 73 | 74 | public boolean isGooglePlayGames() { 75 | PackageManager pm = getPackageManager(); 76 | return pm.hasSystemFeature("com.google.android.play.feature.HPE_EXPERIENCE"); 77 | } 78 | 79 | private void showKeyboard() { 80 | Log.d("MainActivity", "showKeyboard instance method called"); 81 | InputMethodManager inputManager = getSystemService(InputMethodManager.class); 82 | inputManager.showSoftInput(getWindow().getDecorView(), InputMethodManager.SHOW_IMPLICIT); 83 | } 84 | 85 | private void hideKeyboard() { 86 | Log.d("MainActivity", "hideKeyboard instance method called"); 87 | InputMethodManager inputManager = getSystemService(InputMethodManager.class); 88 | inputManager.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0); 89 | } 90 | 91 | private String readClipboard() { 92 | ClipboardManager clipboardManager = (ClipboardManager) getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE); 93 | ClipData data = clipboardManager.getPrimaryClip(); 94 | if (data == null) { 95 | Log.d("MainActivity", "ClipData in readClipboard is null"); 96 | return ""; 97 | } 98 | ClipData.Item item = data.getItemAt(0); 99 | if (item == null) { 100 | Log.d("MainActivity", "Item in readClipboard is null"); 101 | return ""; 102 | } 103 | return item.coerceToText(this).toString(); 104 | } 105 | 106 | private void writeClipboard(String value) { 107 | ClipboardManager clipboardManager = (ClipboardManager) getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE); 108 | ClipData data = ClipData.newPlainText("MainActivity text", value); 109 | clipboardManager.setPrimaryClip(data); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibaryshnikov/android-iced-example/2fb4f2c6fec82f1bfdcf91f1e87126cbbae6b8fd/GameActivity/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /GameActivity/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 |