diff --git a/src/xrt/auxiliary/android/android_load_class.cpp b/src/xrt/auxiliary/android/android_load_class.cpp
index 75210d0e0..a0f04f864 100644
--- a/src/xrt/auxiliary/android/android_load_class.cpp
+++ b/src/xrt/auxiliary/android/android_load_class.cpp
@@ -12,6 +12,7 @@
 #include "util/u_logging.h"
 
 #include "wrap/android.content.h"
+#include "wrap/android.content.pm.h"
 #include "wrap/dalvik.system.h"
 
 #include "jni.h"
@@ -25,6 +26,8 @@ using wrap::dalvik::system::DexClassLoader;
 
 namespace xrt::auxiliary::android {
 
+static constexpr char kIntentAction[] = "org.khronos.openxr.OpenXRRuntimeService";
+
 /*!
  * Hacky way to retrieve runtime source dir.
  */
@@ -56,21 +59,41 @@ getAppInfo(std::string const &packageName, jobject application_context)
 		if (packageManager.isNull()) {
 			U_LOG_E(
 			    "getAppInfo: "
-			    "application_context.getPackageManager() returned "
-			    "null");
+			    "application_context.getPackageManager() returned null");
 			return {};
 		}
-		auto packageInfo = packageManager.getPackageInfo(
-		    packageName, PackageManager::GET_META_DATA | PackageManager::GET_SHARED_LIBRARY_FILES);
-
-		if (packageInfo.isNull()) {
+		auto intent = wrap::android::content::Intent::construct(kIntentAction);
+		auto resolutions = packageManager.queryIntentServices(
+		    intent, PackageManager::GET_META_DATA | PackageManager::GET_SHARED_LIBRARY_FILES);
+		if (resolutions.isNull() || resolutions.size() == 0) {
 			U_LOG_E(
 			    "getAppInfo: "
-			    "application_context.getPackageManager()."
-			    "getPackaegInfo() returned null");
+			    "application_context.getPackageManager().queryIntentServices() returned null or empty");
 			return {};
 		}
-		return packageInfo.getApplicationInfo();
+		const auto n = resolutions.size();
+		ApplicationInfo appInfo;
+		for (int32_t i = 0; i < n; ++i) {
+			wrap::android::content::pm::ResolveInfo resolution{resolutions.get(i)};
+			auto service = resolution.getServiceInfo();
+			if (service.isNull()) {
+				continue;
+			}
+			U_LOG_I("getAppInfo: Considering package %s", service.getPackageName().c_str());
+			if (service.getPackageName() == packageName) {
+				appInfo = service.getApplicationInfo();
+				break;
+			}
+		}
+
+		if (appInfo.isNull()) {
+			U_LOG_E(
+			    "getAppInfo: "
+			    "could not find a package advertising the intent %s named %s",
+			    kIntentAction, packageName.c_str());
+			return {};
+		}
+		return appInfo;
 	} catch (std::exception const &e) {
 		U_LOG_E("Could not get App Info: %s", e.what());
 		return {};
diff --git a/src/xrt/auxiliary/android/android_load_class.hpp b/src/xrt/auxiliary/android/android_load_class.hpp
index d08a03496..4fc13a941 100644
--- a/src/xrt/auxiliary/android/android_load_class.hpp
+++ b/src/xrt/auxiliary/android/android_load_class.hpp
@@ -24,6 +24,9 @@ using wrap::android::content::pm::ApplicationInfo;
  * @note Starting from Android 11, NameNotFoundException exception is thrown if application doesn't
  * specify either <queries> or "android.permission.QUERY_ALL_PACKAGES".
  * See https://developer.android.com/training/package-visibility for detail.
+ *
+ * We work around this by querying first for org.khronos.openxr.OpenXRRuntimeService, for which a query entry is
+ * added by the Loader manifest.
  */
 ApplicationInfo
 getAppInfo(std::string const &packageName, jobject application_context);