Compare commits
3
Commits
| 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
|
||||
|
||||
@@ -126,21 +126,41 @@ pub fn load_class_from_classloader<'env>(
|
||||
class_name: &str,
|
||||
) -> Result<JClass<'env>> {
|
||||
let binary_name = class_name.replace('/', ".");
|
||||
let activity_class = env.get_object_class(activity)?;
|
||||
let loader = env
|
||||
.call_method(
|
||||
&activity_class,
|
||||
"getClassLoader",
|
||||
"()Ljava/lang/ClassLoader;",
|
||||
&[],
|
||||
)?
|
||||
.l()?;
|
||||
let class_name_jstring = new_string(env, &binary_name)?;
|
||||
|
||||
// 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