diff --git a/README.md b/README.md
index 59746f6..e03a72c 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,75 @@
A .NET 8, NativeAOT example on Android.
+## Example using SkiaSharp
+
+This sample has a C++ Android Studio project:
+
+* Uses [Native Activity](https://developer.android.com/ndk/samples/sample_na)
+* No Java/Kotlin code
+* Configures OpenGL
+* Calls into C# / managed code
+* Managed code uses SkiaSharp for rendering a random Skia shader
+* Tap input randomly changes the shader
+
+Some screenshots of the Skia content:
+
+
+
+
+
+(Note these look completely smooth on a Pixel 5, I just tried to snap quick gifs with Vysor)
+
+The C# side is a:
+
+* .NET 8 class library
+* Built with RID `linux-bionic-arm64`
+* Uses the SkiaSharp NuGet package, as one would.
+ * Used a nightly build of SkiaSharp, as I wanted a feature from Skia 3.0
+
+## App Size
+
+The release `.apk` file of the SkiaSharp sample is ~4,528kb.
+
+A breakdown of the files inside:
+
+```
+> 7z l app-release.apk
+ Date Time Attr Size Compressed Name
+------------------- ----- ------------ ------------ ------------------------
+1981-01-01 01:01:02 ..... 56 52 META-INF\com\android\build\gradle\app-metadata.properties
+1981-01-01 01:01:02 ..... 1524 753 classes.dex
+1981-01-01 01:01:02 ..... 8525024 3733033 lib\arm64-v8a\libSkiaSharp.so
+1981-01-01 01:01:02 ..... 1971400 846961 lib\arm64-v8a\libdotnet.so
+1981-01-01 01:01:02 ..... 19504 6869 lib\arm64-v8a\libnativeaot.so
+1981-01-01 01:01:02 ..... 2376 867 AndroidManifest.xml
+1981-01-01 01:01:02 ..... 7778 7778 res\-6.webp
+1981-01-01 01:01:02 ..... 548 239 res\0K.xml
+1981-01-01 01:01:02 ..... 5696 987 res\0w.xml
+1981-01-01 01:01:02 ..... 788 347 res\9s.xml
+1981-01-01 01:01:02 ..... 548 239 res\BW.xml
+1981-01-01 01:01:02 ..... 1404 1404 res\MO.webp
+1981-01-01 01:01:02 ..... 1572 703 res\PF.xml
+1981-01-01 01:01:02 ..... 2884 2884 res\Sn.webp
+1981-01-01 01:01:02 ..... 982 982 res\d2.webp
+1981-01-01 01:01:02 ..... 2898 2898 res\fq.webp
+1981-01-01 01:01:02 ..... 5914 5914 res\j_.webp
+1981-01-01 01:01:02 ..... 1900 1900 res\qs.webp
+1981-01-01 01:01:02 ..... 3844 3844 res\sK.webp
+1981-01-01 01:01:02 ..... 3918 3918 res\u5.webp
+1981-01-01 01:01:02 ..... 1772 1772 res\yw.webp
+1981-01-01 01:01:02 ..... 2036 2036 resources.arsc
+1981-01-01 01:01:02 ..... 2085 1127 META-INF\CERT.SF
+1981-01-01 01:01:02 ..... 1167 1017 META-INF\CERT.RSA
+1981-01-01 01:01:02 ..... 2011 1050 META-INF\MANIFEST.MF
+------------------- ----- ------------ ------------ ------------------------
+1981-01-01 01:01:02 10569629 4629574 25 files
+```
+
+`libdotnet.so` is ~1.9MB, and `libSkiaSharp.so` is ~8.5MB!
+
+## "Hello World" Example
+
I had this managed code:
```csharp
@@ -47,9 +116,3 @@ Instead, we can p/invoke into:
[DllImport("log", EntryPoint = "__android_log_print", CallingConvention = CallingConvention.Cdecl)]
public static extern int LogPrint(LogPriority priority, string tag, string format);
```
-
-## TODO
-
-* `Console.WriteLine()` didn't work inside managed code. Why?
-
-* Try something more complicated. SkiaSharp?
diff --git a/docs/screenshot1.gif b/docs/screenshot1.gif
new file mode 100644
index 0000000..0550818
Binary files /dev/null and b/docs/screenshot1.gif differ
diff --git a/docs/screenshot2.gif b/docs/screenshot2.gif
new file mode 100644
index 0000000..248eb5a
Binary files /dev/null and b/docs/screenshot2.gif differ
diff --git a/docs/screenshot3.gif b/docs/screenshot3.gif
new file mode 100644
index 0000000..3195974
Binary files /dev/null and b/docs/screenshot3.gif differ