├── .github └── workflows │ ├── android.yml │ └── rust.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── schuetz │ │ └── rustandroidios │ │ └── JniTests.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── schuetz │ │ │ └── rustandroidios │ │ │ ├── JniApi.kt │ │ │ └── MainActivity.kt │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── schuetz │ └── rustandroidios │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img ├── android1.png ├── ios1.png └── logos_.png ├── ios_app ├── .gitignore ├── Rust-Bridging-Header.h ├── build-rust-xcode.sh ├── core │ └── mobileapp-ios.h ├── ios_app.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ ├── ios_app.xcscheme │ │ └── ios_appTests.xcscheme ├── ios_app │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── 120.png │ │ │ ├── 152.png │ │ │ ├── 180.png │ │ │ ├── 76.png │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift └── ios_appTests │ ├── Info.plist │ └── ios_appTests.swift ├── settings.gradle └── src ├── ffi_android.rs ├── ffi_ios.rs └── lib.rs /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | instrumented_tests: 11 | name: Run Instrumented Tests 12 | runs-on: macos-latest 13 | 14 | steps: 15 | - name: Save logcat output 16 | uses: actions/upload-artifact@master 17 | if: failure() 18 | with: 19 | name: logcat 20 | path: artifacts/logcat.log 21 | - name: checkout 22 | uses: actions/checkout@v2 23 | - name: rust toolchain setup 24 | uses: actions-rs/toolchain@v1 25 | with: 26 | toolchain: stable 27 | - name: install cargo ndk 28 | uses: actions-rs/cargo@v1 29 | with: 30 | command: install 31 | args: cargo-ndk 32 | - name: setup build targets 33 | run: rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android 34 | - name: instrumented tests 35 | uses: reactivecircus/android-emulator-runner@v2 36 | with: 37 | api-level: 29 38 | script: ./gradlew connectedAndroidTest --stacktrace 39 | - name: Instrumented tests results 40 | uses: actions/upload-artifact@v2 41 | with: 42 | name: instrumented-tests-results 43 | path: app/build/reports/androidTests/connected/index.html 44 | 45 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Build 20 | run: cargo build --verbose 21 | - name: Run tests 22 | run: cargo test --verbose 23 | 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | .gradle 4 | /local.properties 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | target/ 10 | app/src/main/libs/ 11 | app/src/main/java/net/akaame/myapplication/Session.java 12 | app/src/main/java/net/akaame/myapplication/InternalPointerMarker.java 13 | 14 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aho-corasick" 5 | version = "0.7.6" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "android_log-sys" 13 | version = "0.1.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "android_logger" 18 | version = "0.8.6" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | dependencies = [ 21 | "android_log-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 22 | "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 23 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 24 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 25 | ] 26 | 27 | [[package]] 28 | name = "ascii" 29 | version = "0.9.3" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | 32 | [[package]] 33 | name = "atty" 34 | version = "0.2.13" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | dependencies = [ 37 | "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", 38 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 39 | ] 40 | 41 | [[package]] 42 | name = "byteorder" 43 | version = "1.3.4" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | 46 | [[package]] 47 | name = "cesu8" 48 | version = "1.1.0" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | 51 | [[package]] 52 | name = "cfg-if" 53 | version = "0.1.9" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | 56 | [[package]] 57 | name = "combine" 58 | version = "3.8.1" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | dependencies = [ 61 | "ascii 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", 62 | "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 63 | "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 64 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 65 | "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 66 | ] 67 | 68 | [[package]] 69 | name = "core-foundation" 70 | version = "0.6.4" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | dependencies = [ 73 | "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 74 | "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", 75 | ] 76 | 77 | [[package]] 78 | name = "core-foundation-sys" 79 | version = "0.6.2" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | 82 | [[package]] 83 | name = "either" 84 | version = "1.5.3" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | 87 | [[package]] 88 | name = "env_logger" 89 | version = "0.6.2" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | dependencies = [ 92 | "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", 93 | "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 94 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 95 | "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 96 | "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 97 | ] 98 | 99 | [[package]] 100 | name = "env_logger" 101 | version = "0.7.1" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | dependencies = [ 104 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 105 | "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 106 | ] 107 | 108 | [[package]] 109 | name = "error-chain" 110 | version = "0.12.2" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | dependencies = [ 113 | "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", 114 | ] 115 | 116 | [[package]] 117 | name = "humantime" 118 | version = "1.2.0" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | dependencies = [ 121 | "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 122 | ] 123 | 124 | [[package]] 125 | name = "jni" 126 | version = "0.16.0" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | dependencies = [ 129 | "cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 130 | "combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 131 | "error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", 132 | "jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 133 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 134 | "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 135 | ] 136 | 137 | [[package]] 138 | name = "jni-sys" 139 | version = "0.3.0" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | 142 | [[package]] 143 | name = "lazy_static" 144 | version = "1.3.0" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | 147 | [[package]] 148 | name = "libc" 149 | version = "0.2.60" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | 152 | [[package]] 153 | name = "log" 154 | version = "0.4.8" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | dependencies = [ 157 | "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 158 | ] 159 | 160 | [[package]] 161 | name = "log-panics" 162 | version = "2.0.0" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | dependencies = [ 165 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 166 | ] 167 | 168 | [[package]] 169 | name = "memchr" 170 | version = "2.2.1" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | 173 | [[package]] 174 | name = "quick-error" 175 | version = "1.2.2" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | 178 | [[package]] 179 | name = "regex" 180 | version = "1.2.1" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | dependencies = [ 183 | "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", 184 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 185 | "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", 186 | "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 187 | ] 188 | 189 | [[package]] 190 | name = "regex-syntax" 191 | version = "0.6.11" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | 194 | [[package]] 195 | name = "rust_android_ios" 196 | version = "0.0.1" 197 | dependencies = [ 198 | "android_logger 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", 199 | "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 200 | "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 201 | "jni 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", 202 | "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", 203 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 204 | "log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 205 | ] 206 | 207 | [[package]] 208 | name = "same-file" 209 | version = "1.0.6" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | dependencies = [ 212 | "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 213 | ] 214 | 215 | [[package]] 216 | name = "termcolor" 217 | version = "1.0.5" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | dependencies = [ 220 | "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 221 | ] 222 | 223 | [[package]] 224 | name = "thread_local" 225 | version = "0.3.6" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | dependencies = [ 228 | "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 229 | ] 230 | 231 | [[package]] 232 | name = "unreachable" 233 | version = "1.0.0" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | dependencies = [ 236 | "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 237 | ] 238 | 239 | [[package]] 240 | name = "version_check" 241 | version = "0.9.2" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | 244 | [[package]] 245 | name = "void" 246 | version = "1.0.2" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | 249 | [[package]] 250 | name = "walkdir" 251 | version = "2.3.1" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | dependencies = [ 254 | "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 255 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 256 | "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 257 | ] 258 | 259 | [[package]] 260 | name = "winapi" 261 | version = "0.3.7" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | dependencies = [ 264 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 265 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 266 | ] 267 | 268 | [[package]] 269 | name = "winapi-i686-pc-windows-gnu" 270 | version = "0.4.0" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | 273 | [[package]] 274 | name = "winapi-util" 275 | version = "0.1.2" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | dependencies = [ 278 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 279 | ] 280 | 281 | [[package]] 282 | name = "winapi-x86_64-pc-windows-gnu" 283 | version = "0.4.0" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | 286 | [[package]] 287 | name = "wincolor" 288 | version = "1.0.1" 289 | source = "registry+https://github.com/rust-lang/crates.io-index" 290 | dependencies = [ 291 | "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 292 | "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 293 | ] 294 | 295 | [metadata] 296 | "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" 297 | "checksum android_log-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8052e2d8aabbb8d556d6abbcce2a22b9590996c5f849b9c7ce4544a2e3b984e" 298 | "checksum android_logger 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8cbd542dd180566fad88fd2729a53a62a734843c626638006a9d63ec0688484e" 299 | "checksum ascii 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" 300 | "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" 301 | "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 302 | "checksum cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 303 | "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" 304 | "checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" 305 | "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" 306 | "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" 307 | "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" 308 | "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" 309 | "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" 310 | "checksum error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" 311 | "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" 312 | "checksum jni 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22bbdc25b49340bc4fc3d9c96dd84d878c4beeca35e3651efa53db51a68d7d4d" 313 | "checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 314 | "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" 315 | "checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" 316 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 317 | "checksum log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae0136257df209261daa18d6c16394757c63e032e27aafd8b07788b051082bef" 318 | "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" 319 | "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 320 | "checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" 321 | "checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" 322 | "checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 323 | "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" 324 | "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" 325 | "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" 326 | "checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" 327 | "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 328 | "checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" 329 | "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" 330 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 331 | "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" 332 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 333 | "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" 334 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_android_ios" 3 | version = "0.0.1" 4 | authors = ["Ivan Schuetz "] 5 | edition = "2018" 6 | 7 | [lib] 8 | name = "core" 9 | crate-type = ["cdylib", "staticlib"] 10 | 11 | [dependencies] 12 | log = "0.4.6" 13 | log-panics = "2.0" 14 | 15 | [target.'cfg(target_os="android")'.dependencies] 16 | jni = { version = "0.16", default-features = false } 17 | android_logger = "0.8" 18 | 19 | [target.'cfg(target_os = "ios")'.dependencies] 20 | libc = "0.2" 21 | core-foundation = "0.6.2" 22 | 23 | [build-dependencies] 24 | env_logger = "0.6" 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust core for native Android and iOS apps 2 | 3 | ![Rust](https://github.com/i-schuetz/rust_android_ios/workflows/Rust/badge.svg) 4 | ![Android](https://github.com/i-schuetz/rust_android_ios/workflows/Android/badge.svg) 5 | [[TODO](https://github.com/i-schuetz/rust_android_ios/issues/2) iOS badge] 6 | 7 | This is an example that shows how to use a shared Rust core in native Android and iOS apps. 8 | 9 | ⚠️ Looking for maintainers. If you want to help, just open an issue, or email me ivanhp978@gmail.com 10 | 11 | # Why? 12 | 13 | This approach gives us the best of all worlds: we prevent code duplication by using a shared library. Rust, as a highly performant and safe language is a great fit for mobile. We keep a fully native UI experience and uncomplicated access to the latest APIs of the platforms. 14 | 15 | It's also very flexible, allowing to migrate easily between different platforms, including conventional cross-platform frameworks like Flutter or React Native. For example, you can develop your MVP with Rust+React Native or Rust+Flutter, and migrate later to native iOS/Android, without having to rewrite everything. You even can reuse your core for a web-app, using WebAssembly, or desktop app (where again, you can use native or a cross-platform framework like Electron). 16 | 17 | # Project structure 18 | 19 | - Rust: Repo's root. 20 | - iOS app: `ios_app` directory. 21 | - Android app: Repo's root as well. TODO move it to a folder `android_app`, like the iOS app. 22 | 23 | # Possible setups 24 | 25 | There are different ways to integrate Rust: 26 | 27 | ## As source (like in this repo) 28 | 29 | - Simple setup. 30 | 31 | - Rust is built as part of the app's build process. 32 | 33 | - Not ideal if there are team members unfamiliar with Rust. 34 | 35 | ## As binary 36 | 37 | The Rust binary is distributed as an external dependency. 38 | 39 | - Better for teams with different skillsets. Everyone works mainly with their familiar tech stack. 40 | 41 | - Better separation of concerns / modularity. 42 | 43 | - Considerably more complicated to setup than monorepo (has to be done only once though). 44 | 45 | - Rust binaries have to be versioned and released. 46 | 47 | Note: it is possible to overwrite the external dependency with a local copy for local development. 48 | 49 | ## As "normal" library 50 | 51 | Here the external dependency contains the Rust binary and wrapper libraries for Android and iOS respectively (written in Kotlin and Swift), which hide the FFI/JNI, providing a simple and safe interface to the apps. This makes working with this dependency like with regular third parties. 52 | 53 | An example for this and the binary approaches can be found [here](https://github.com/Co-Epi/app-backend-rust). The Android build contains a wrapper library, which is imported in the Android app with [Gradle](https://github.com/Co-Epi/app-android/blob/54cffa441d27d18ba33d7719a34dc9b5c9125262/app/build.gradle#L168). The iOS build is distributed directly as a binary (no wrapper), using [Carthage](https://github.com/Co-Epi/app-ios/blob/develop/Cartfile#L2). 54 | 55 | # Note on concurrency 56 | 57 | While it's possible to use asynchronous code in core, it's recommended to use blocking apis and add concurrency in the apps. This simplifies the FFI/JNI interfaces (see the [CoEpi](https://github.com/Co-Epi/app-backend-rust) example, where the apps add concurrency via RxSwift/RxJava). 58 | 59 | # "Real world" examples 60 | 61 | ### [CoEpi](https://github.com/Co-Epi/app-backend-rust) 62 | 63 | A mobile contact tracing app for epidemics, with [Android](https://github.com/Co-Epi/app-android) and [iOS](https://github.com/Co-Epi/app-ios) frontends. 64 | 65 | ### [Xi editor](https://github.com/xi-editor/xi-editor) 66 | 67 | A text editor with a lot of frontends: MacOS, GTK, Electron and Windows, among others. 68 | 69 | # Other related projects 70 | 71 | ### [WASM-Rust-d3 example](https://github.com/i-schuetz/wasm-rust-d3) 72 | 73 | An example that shows how to display chart data with d3/JS, using a Rust core to fetch it. 74 | 75 | ### [yew-d3-example](https://github.com/i-schuetz/yew-d3-example) 76 | 77 | Similar to the above, but using the [Yew framework](https://github.com/yewstack/yew) 78 | 79 | # Quickstart 80 | 81 | Install [rustup](https://rustup.rs/) 82 | 83 | ## Android specific steps 84 | 85 | - Ensure the [NDK](https://developer.android.com/ndk/guides) is installed. 86 | 87 | - Set the NDK_HOME environment variable with path to the NDK, e.g: 88 | 89 | ``` 90 | export $NDK_HOME=$HOME/Library/Android/sdk/ndk/21.3.6528147/ 91 | ``` 92 | 93 | - Install [cargo ndk](https://github.com/bbqsrc/cargo-ndk): 94 | 95 | ``` 96 | cargo install cargo-ndk 97 | ``` 98 | 99 | - Add targets 100 | 101 | ``` 102 | rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android 103 | ``` 104 | 105 | - Run the project in Android Studio. This will build Rust, put the binaries in the correct place and start the app. 106 | 107 | ## iOS specific steps 108 | 109 | - Install rust-bitcode 1.46.0 with macOS binary support 110 | 111 | ``` 112 | wget https://github.com/getditto/rust-bitcode/releases/download/v1.46.0/rust-ios-arm64-1.46.0.zip 113 | unzip rust-ios-arm64-1.46.0.zip 114 | cd rust-ios-arm64-1.46.0 115 | ./install.sh 116 | ``` 117 | 118 | As the binaries are not signed, you'll have to convince macOS that it's safe to run them. 119 | One solution is to do the following: 120 | 121 | 1. `cd rust_android_ios/ios_app` 122 | 2. `cargo +ios-arm64-1.46.0 build --target aarch64-apple-ios --release --lib` 123 | 3. if it fails because macOS doesn't trust the binary, go to 124 | `System Preferences -> Security & Privacy` and `Allow to run binary` 125 | then go to 2. 126 | 127 | - Run the project in Xcode. This will build Rust, put the binaries in the correct place and start the app. 128 | 129 | ## Android specifics 130 | 131 | - Logcat doesn't show stdout and stderr, which means that you'll not see `println` or `panic` messages (unless specially configured, like done in this repo). 132 | - If you're having difficulties, try reproducing the problem in a plain (non Android) Kotlin (or Java) project. The JNI is the same, but it's easier to debug, among other things, because you can see stdout/stderr. 133 | 134 | ## iOS 135 | 136 | - iOS shows stdout/stderr as expected and is overall easier to worth with than Android, given the simpler FFI api. 137 | 138 | ## Inspecting binaries 139 | 140 | There are diverse tools to inspect the binaries, e.g. 141 | 142 | ``` 143 | nm -g libcore.so 144 | ``` 145 | 146 | Shows the external symbols, useful if you want to check that the library was generated correctly / contains the symbols from your sources. 147 | 148 | To look for a specific symbol: 149 | 150 | ``` 151 | nm -g libcore.so | grep greet 152 | ``` 153 | 154 | # Convenience 155 | 156 | ## iOS 157 | 158 | - [cbindgen](https://github.com/eqrion/cbindgen): generates headers for the FFI Rust declarations. In this project, this would mean that `mobileapp-ios.h` would be automatically generated. 159 | 160 | ## Android 161 | 162 | - [rust-swig](https://github.com/Dushistov/flapigen-rs): similarly to cbindgen for iOS, this generates the JNI api for the Rust declarations. In this project, this would mean that `JNIApi` would be generated, and `ffi_android.rs` mostly too. 163 | 164 | # Links 165 | 166 | [Official Rust FFI docs](https://doc.rust-lang.org/nomicon/ffi.html) 167 | 168 | [Rust FFI guide](https://michael-f-bryan.github.io/rust-ffi-guide/) 169 | 170 | [Official JNI docs](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html) (tutorials may be better to start...) 171 | 172 | [Android JNI tips](https://developer.android.com/training/articles/perf-jni) 173 | 174 | [Android supported ABIs](https://developer.android.com/ndk/guides/abis) 175 | 176 | # Contribute 177 | 178 | 1. Fork 179 | 2. Commit changes to a branch in your fork 180 | 3. Push your code and make a pull request 181 | 182 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 30 7 | buildToolsVersion "30.0.3" 8 | defaultConfig { 9 | applicationId "com.schuetz.rust_android_ios" 10 | minSdkVersion 21 11 | targetSdkVersion 30 12 | versionCode 1 13 | versionName "1.0.1" 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | } 16 | 17 | sourceSets { 18 | main { 19 | jni.srcDirs = [] 20 | jniLibs.srcDir 'src/main/libs' 21 | } 22 | } 23 | 24 | buildTypes { 25 | release { 26 | minifyEnabled true 27 | shrinkResources true 28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | } 32 | 33 | dependencies { 34 | implementation fileTree(dir: 'libs', include: ['*.jar']) 35 | testImplementation 'androidx.test.ext:junit:1.1.2' 36 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 37 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 38 | implementation 'androidx.appcompat:appcompat:1.2.0' 39 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 40 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 41 | } 42 | 43 | def rustBasePath = ".." 44 | def archTriplets = [ 45 | 'armeabi-v7a': 'armv7-linux-androideabi', 46 | 'arm64-v8a': 'aarch64-linux-android', 47 | 'x86_64': 'x86_64-linux-android', 48 | 'x86': 'i686-linux-android' 49 | ] 50 | 51 | // TODO: only pass --release if buildType is release 52 | archTriplets.each { arch, target -> 53 | 54 | // Build Rust lib 55 | tasks.create(name: "cargo-build-$arch", type: Exec, description: "Building core for $arch") { 56 | workingDir rustBasePath 57 | executable "cargo" 58 | args = ["ndk", "--platform", "29", "--target", target, "build", "--verbose"] 59 | } 60 | 61 | // Copy Rust lib into this app's libs directory 62 | tasks.create(name: "rust-deploy-$arch", type: Copy, dependsOn: "cargo-build-$arch", 63 | description: "Copy rust libs for ($arch) to libs") { 64 | 65 | from "$rustBasePath/target/$target/debug" 66 | include "*.so" 67 | into "$rustBasePath/app/src/main/libs/$arch" 68 | } 69 | 70 | // Hook up tasks to execute before building java 71 | tasks.withType(JavaCompile) { 72 | compileTask -> compileTask.dependsOn "rust-deploy-$arch" 73 | } 74 | } 75 | 76 | repositories { 77 | mavenCentral() 78 | } 79 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/evgeniy/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/schuetz/rustandroidios/JniTests.kt: -------------------------------------------------------------------------------- 1 | package com.schuetz.rustandroidios 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import org.junit.Assert.assertEquals 5 | import org.junit.Test 6 | import org.junit.runner.RunWith 7 | 8 | @RunWith(AndroidJUnit4::class) 9 | class JniTests { 10 | 11 | @Test 12 | fun initLogger() { 13 | JniApi().initLogger() 14 | // There's no result. Only testing that it doesn't crash. 15 | } 16 | 17 | @Test 18 | fun greet() { 19 | val res = JniApi().also { initLogger() }.greet("Ivan") 20 | assertEquals("Hello \uD83D\uDC4B Ivan!", res) 21 | } 22 | 23 | @Test 24 | fun add() { 25 | val res = JniApi().also { initLogger() }.add(111, 222) 26 | assertEquals(333, res) 27 | } 28 | 29 | @Test 30 | fun passClass() { 31 | JniApi().also { initLogger() }.passObject(Dummy("sfds", 2)) 32 | // There's no result. Only testing that it doesn't crash. 33 | } 34 | 35 | @Test 36 | fun returnClass() { 37 | val res = JniApi().also { initLogger() }.returnObject() 38 | assertEquals(Dummy("my string parameter", 123), res) 39 | } 40 | 41 | @Test 42 | fun registersCallback() { 43 | JniApi().also { initLogger() }.registerCallback(object : Callback { 44 | override fun call(string: String) { 45 | // Testing callbacks left as an exercise. This requires new dependencies and 46 | // it's not relatd with Rust. 47 | println("Callback called with: $string") 48 | } 49 | }) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/schuetz/rustandroidios/JniApi.kt: -------------------------------------------------------------------------------- 1 | package com.schuetz.rustandroidios 2 | 3 | class JniApi { 4 | init { 5 | try { 6 | System.loadLibrary("core") 7 | } catch (e: UnsatisfiedLinkError) { 8 | throw UnsatisfiedLinkError("Error linking Rust library. Check that the .so file " + 9 | "for the current architecture is in the libs directory. Error: $e") 10 | } 11 | } 12 | 13 | external fun initLogger() 14 | 15 | external fun add(value1: Int, value2: Int): Int 16 | external fun greet(who: String): String 17 | 18 | external fun passObject(dummy: Dummy) 19 | external fun returnObject(): Dummy 20 | 21 | external fun registerCallback(callback: Callback) 22 | } 23 | 24 | data class Dummy( 25 | val stringPar: String, 26 | val intPar: Int 27 | ) 28 | 29 | interface Callback { 30 | fun call(string: String) 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/schuetz/rustandroidios/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.schuetz.rustandroidios 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import com.schuetz.rustandroidios.R.layout.activity_main 6 | 7 | class MainActivity : AppCompatActivity() { 8 | 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContentView(activity_main) 12 | 13 | val jniApi = JniApi() 14 | 15 | jniApi.initLogger() 16 | 17 | val greetResult = jniApi.greet("MyName") 18 | println("JNI greetResult: $greetResult") 19 | 20 | val addResult = jniApi.add(1, 2) 21 | println("JNI addResult: $addResult") 22 | 23 | val passClassResult = jniApi.passObject(Dummy("foo", 1)) 24 | println("JNI passClassResult: $passClassResult") 25 | 26 | val returnClassResult = jniApi.returnObject() 27 | println("JNI returnClassResult: $returnClassResult") 28 | 29 | val myCallback = object: Callback { 30 | override fun call(string: String) { 31 | println("JNI callback called: $string") 32 | } 33 | } 34 | 35 | jniApi.registerCallback(myCallback) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ivnsch/rust_android_ios/be08231502b9fe15abc8805232950b37bd664e04/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Rust demo 3 | Returned class: %s 4 | Callback called with: %s 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |