如何通过JNI调用WallpaperManager的getDrawable/peekDrawable方法及解决报错
Android JNI调用WallpaperManager获取壁纸问题解决
错误根源
- 调用
WallpaperManager.getInstance(nullptr)传入了空Context:getInstance必须接收有效Context(如Activity实例)才能访问系统服务,空Context会触发NullPointerException。 peekDrawable()方法签名错误:该方法返回Drawable类型,正确签名为()Landroid/graphics/drawable/Drawable;,而非你写的()Landroid/app/WallpaperManager;。
修正后的JNI代码
// 1. 获取有效的GameActivity实例(Context不能为空) jobject gameActivity = FAndroidApplication::GetGameActivityThis(); if (!gameActivity) { // 处理Activity为空的场景,比如打日志 return nullptr; } // 2. 查找WallpaperManager类 jclass wallpaperManagerCls = JEnv->FindClass("android/app/WallpaperManager"); if (!wallpaperManagerCls) { return nullptr; } // 3. 获取getInstance静态方法ID jmethodID getInstanceMtd = JEnv->GetStaticMethodID( wallpaperManagerCls, "getInstance", "(Landroid/content/Context;)Landroid/app/WallpaperManager;" ); if (!getInstanceMtd) { JEnv->DeleteLocalRef(wallpaperManagerCls); return nullptr; } // 4. 获取WallpaperManager实例 jobject wallpaperManager = JEnv->CallStaticObjectMethod( wallpaperManagerCls, getInstanceMtd, gameActivity ); if (!wallpaperManager) { JEnv->DeleteLocalRef(wallpaperManagerCls); return nullptr; } // 5. 获取peekDrawable方法ID(替换为getDrawable方法名即可调用对应接口) jmethodID peekDrawableMtd = JEnv->GetMethodID( wallpaperManagerCls, "peekDrawable", "()Landroid/graphics/drawable/Drawable;" ); if (!peekDrawableMtd) { JEnv->DeleteLocalRef(wallpaperManager); JEnv->DeleteLocalRef(wallpaperManagerCls); return nullptr; } // 6. 调用方法获取壁纸Drawable jobject wallpaperDrawable = JEnv->CallObjectMethod( wallpaperManager, peekDrawableMtd ); // 7. 清理本地引用,避免内存泄漏 JEnv->DeleteLocalRef(wallpaperManager); JEnv->DeleteLocalRef(wallpaperManagerCls); // 返回获取到的壁纸Drawable return wallpaperDrawable;
额外提示
- 权限要求:Android 10及以下需申请
READ_EXTERNAL_STORAGE权限;Android 11+需申请ACCESS_MEDIA_LOCATION权限,否则可能无法获取壁纸。 - 如果你使用
getDrawable(),只需将代码中的peekDrawable替换为getDrawable即可,两者方法签名完全一致。 - 若使用
NewScopedJavaObject管理引用,注意其自动释放机制,避免手动调用DeleteLocalRef导致冲突。
内容的提问来源于stack exchange,提问作者codenicks
相关产品推荐
相关产品推荐

