diff --git a/.gitignore b/.gitignore
index eb5a316..a9d37c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 target
+Cargo.lock
diff --git a/android-activity/src/game_activity/mod.rs b/android-activity/src/game_activity/mod.rs
index 7cf3894..333de52 100644
--- a/android-activity/src/game_activity/mod.rs
+++ b/android-activity/src/game_activity/mod.rs
@@ -8,6 +8,7 @@ use std::ptr;
 use std::ptr::NonNull;
 use std::sync::Weak;
 use std::sync::{Arc, Mutex, RwLock};
+use std::task::{RawWaker, RawWakerVTable, Waker};
 use std::time::Duration;
 
 use libc::c_void;
@@ -118,6 +119,27 @@ impl AndroidAppWaker {
             ALooper_wake(self.looper.as_ptr());
         }
     }
+
+    /// Creates a [`Waker`] that wakes up the [`AndroidApp`].
+    ///
+    /// This is useful for using this crate in `async` environments.
+    ///
+    /// [`Waker`]: std::task::Waker
+    pub fn waker(self) -> Waker {
+        const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake, drop);
+
+        unsafe fn clone(data: *const ()) -> RawWaker {
+            RawWaker::new(data, &VTABLE)
+        }
+
+        unsafe fn wake(data: *const ()) {
+            ndk_sys::ALooper_wake(data as *const _ as *mut _)
+        }
+
+        unsafe fn drop(_: *const ()) {}
+
+        unsafe { Waker::from_raw(RawWaker::new(self.looper.as_ptr() as *const (), &VTABLE)) }
+    }
 }
 
 impl AndroidApp {
diff --git a/android-activity/src/native_activity/mod.rs b/android-activity/src/native_activity/mod.rs
index 2adcd52..d6e0b2b 100644
--- a/android-activity/src/native_activity/mod.rs
+++ b/android-activity/src/native_activity/mod.rs
@@ -6,6 +6,7 @@ use std::panic::AssertUnwindSafe;
 use std::ptr;
 use std::ptr::NonNull;
 use std::sync::{Arc, Mutex, RwLock, Weak};
+use std::task::{RawWaker, RawWakerVTable, Waker};
 use std::time::Duration;
 
 use libc::c_void;
@@ -83,6 +84,27 @@ impl AndroidAppWaker {
             ndk_sys::ALooper_wake(self.looper.as_ptr());
         }
     }
+
+    /// Creates a [`Waker`] that wakes up the [`AndroidApp`].
+    ///
+    /// This is useful for using this crate in `async` environments.
+    ///
+    /// [`Waker`]: std::task::Waker
+    pub fn waker(self) -> Waker {
+        const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake, drop);
+
+        unsafe fn clone(data: *const ()) -> RawWaker {
+            RawWaker::new(data, &VTABLE)
+        }
+
+        unsafe fn wake(data: *const ()) {
+            ndk_sys::ALooper_wake(data as *const _ as *mut _)
+        }
+
+        unsafe fn drop(_: *const ()) {}
+
+        unsafe { Waker::from_raw(RawWaker::new(self.looper.as_ptr() as *const (), &VTABLE)) }
+    }
 }
 
 impl AndroidApp {