Compare commits
3
Commits
aeb5568727
...
v0.7.10-sw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
275fc84a4a | ||
|
|
657e6f2125 | ||
|
|
48baafc3ff |
No files matched your search
@@ -17,7 +17,7 @@
|
||||
{{{ raw_manifest }}}
|
||||
|
||||
<application android:hasCode="true" android:icon="@mipmap/ic_launcher"
|
||||
android:extractNativeLibs="true"
|
||||
android:extractNativeLibs="false"
|
||||
android:allowNativeHeapPointerTagging="false"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="{{#if supports_rtl}}{{ supports_rtl }}{{else}}true{{/if}}"
|
||||
|
||||
@@ -4,7 +4,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:8.7.0")
|
||||
classpath("com.android.tools.build:gradle:8.13.0")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -398,7 +398,7 @@ impl FfiBridgeParser {
|
||||
// Use with_activity which returns Option<R>, wrapping our Result in the Option
|
||||
let inner_result: Option<Result<Self, String>> = manganis::android::with_activity(|mut env, activity| {
|
||||
// Find the class
|
||||
let class_result = env.find_class(#class_name_lit);
|
||||
let class_result = manganis::android::load_class_from_classloader(env, activity, #class_name_lit);
|
||||
let class = match class_result {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Some(Err(format!("Failed to find class {}: {:?}", #class_name_lit, e))),
|
||||
|
||||
@@ -111,17 +111,56 @@ pub fn request_permissions_via_helper(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Load a Java class from the APK's classloader
|
||||
/// Load a Java class from the APK's classloader.
|
||||
///
|
||||
/// `JNIEnv::find_class` resolves against the *system* classloader on a thread that
|
||||
/// was attached from native code (`JavaVM::attach_current_thread`), which cannot see
|
||||
/// classes packaged in the APK, so it raises `ClassNotFoundException`. The activity's
|
||||
/// own classloader can, so we ask the activity for it and call `loadClass` on it.
|
||||
///
|
||||
/// `class_name` may be given in either JNI form (`com/example/Foo`) or binary form
|
||||
/// (`com.example.Foo`); `loadClass` requires the binary form, so slashes are converted.
|
||||
pub fn load_class_from_classloader<'env>(
|
||||
env: &mut JNIEnv<'env>,
|
||||
activity: &JObject<'_>,
|
||||
class_name: &str,
|
||||
) -> Result<JClass<'env>> {
|
||||
let class_name_jstring = new_string(env, class_name)?;
|
||||
let class = env.call_static_method(
|
||||
"java/lang/Class",
|
||||
"forName",
|
||||
let binary_name = class_name.replace('/', ".");
|
||||
|
||||
// Ask the activity INSTANCE for its classloader. `Activity` is a `Context`, and
|
||||
// `Context.getClassLoader()` is documented to return a loader for the application
|
||||
// package unconditionally. Do not route this through `get_object_class(activity)`:
|
||||
// that calls `Class.getClassLoader()`, which asks which loader loaded the Activity's
|
||||
// own class and is specified to return null for anything the bootstrap loader
|
||||
// loaded -- a null receiver that then fails obscurely at the `loadClass` below.
|
||||
let loader = env.call_method(activity, "getClassLoader", "()Ljava/lang/ClassLoader;", &[]);
|
||||
let loader = describe_and_clear(env, loader)?.l()?;
|
||||
|
||||
let class_name_jstring = new_string(env, &binary_name);
|
||||
let class_name_jstring = describe_and_clear(env, class_name_jstring)?;
|
||||
|
||||
let class = env.call_method(
|
||||
&loader,
|
||||
"loadClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;",
|
||||
&[JValue::Object(&class_name_jstring)],
|
||||
)?;
|
||||
);
|
||||
let class = describe_and_clear(env, class)?;
|
||||
Ok(class.l()?.into())
|
||||
}
|
||||
|
||||
/// Log and clear a pending Java exception before returning an `Err`.
|
||||
///
|
||||
/// jni 0.21 does NOT clear the pending exception when a call returns `Err`
|
||||
/// (see its `JNIEnv` docs), and any later JNI call made while one is pending
|
||||
/// aborts the process with "JNI DETECTED ERROR IN APPLICATION: ... called with
|
||||
/// pending exception". That is what turns a recoverable `ClassNotFoundException`
|
||||
/// into an unreadable ART abort. Describe it to logcat so the cause is visible,
|
||||
/// then clear it so the `Err` can travel normally.
|
||||
fn describe_and_clear<T>(env: &mut JNIEnv<'_>, result: Result<T>) -> Result<T> {
|
||||
if result.is_err() && env.exception_check().unwrap_or(false) {
|
||||
let _ = env.exception_describe();
|
||||
let _ = env.exception_clear();
|
||||
}
|
||||
result
|
||||
}
|
||||
Reference in new issue
Block a user