gpt4 book ai didi

android - 如何在 Android N 上为 NativeActivity 动态加载原生共享库 (.so)?

转载 作者:太空宇宙 更新时间:2023-11-04 11:57:21 47 4
gpt4 key购买 nike

我想为 NaticityActivity 加载自定义 .so 动态,但是当 NativeActivity.onCreate() 调用 classLoader 时出现错误.findLibrary("UE4");

这是 NativeActivity.onCreate() 的一部分

    BaseDexClassLoader classLoader = (BaseDexClassLoader) getClassLoader();
String path = classLoader.findLibrary(libname);

if (path == null) {
throw new IllegalArgumentException("Unable to find native library " + libname +
" using classloader: " + classLoader.toString());
}

byte[] nativeSavedState = savedInstanceState != null
? savedInstanceState.getByteArray(KEY_NATIVE_SAVED_STATE) : null;

mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
getAbsolutePath(getExternalFilesDir(null)),
Build.VERSION.SDK_INT, getAssets(), nativeSavedState,
classLoader, classLoader.getLdLibraryPath());

if (mNativeHandle == 0) {
throw new UnsatisfiedLinkError(
"Unable to load native library \"" + path + "\": " + getDlError());
}
super.onCreate(savedInstanceState);


//Hack classLoader nativeLibraryDirectories, add my .so file path


UnrealHelper.RequestPermission(this);

UnrealHelper.CopyFile(Environment.getExternalStorageDirectory().getPath() + "/libUE4.so", getFilesDir() + "/libUE4.so");

String TestA = System.mapLibraryName("gnustl_shared");
//libUE4.so
String fileName = System.mapLibraryName("UE4");

String TmpVal = "";
BaseDexClassLoader classLoader = (BaseDexClassLoader) getClassLoader();
try
{
Field pathListField = classLoader.getClass().getSuperclass().getDeclaredField("pathList");
pathListField.setAccessible(true);
Object pathListVal = pathListField.get(classLoader);
Field nativeLibPathField = pathListVal.getClass().getDeclaredField("nativeLibraryDirectories");
nativeLibPathField.setAccessible(true);
Object nativeLibPathVal = nativeLibPathField.get(pathListVal);
ArrayList nativeLibraryDirectories = (ArrayList)nativeLibPathVal;
//add my .so path to classLoader
nativeLibraryDirectories.add(getFilesDir());
//nativeLibPathField.set(pathListVal, nativeLibraryDirectories);
//pathListField.set(classLoader, pathListVal);

//ref: https://android.googlesource.com/platform/libcore-snapshot/+/ics-mr1/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
//ref: https://android.googlesource.com/platform/libcore-snapshot/+/ics-mr1/dalvik/src/main/java/dalvik/system/DexPathList.java
for (Object directory : nativeLibraryDirectories) {
File file = new File((File)directory, fileName);
if (file.exists() && file.isFile() && file.canRead()) {
//is valid
TmpVal = file.getPath();
}
}
}
catch(Exception Exp)
{
String ErrorMsg = Exp.toString();
System.out.print(ErrorMsg);
}

//test the path added, but got null
String path = classLoader.findLibrary("UE4");

enter image description here

最佳答案

您必须将您的共享库打包到您的 apk 中,这样 System.loadLibrary("your-lib-name")可以找到它。注意 System.loadLibrary将只接受库名称,而不是完整路径。


对于 System.load() ,我已经尝试了以下步骤,效果很好。您可以尝试您的项目,看看进展如何。

第 1 步:

确保在 manifest.xml 中配置了应用程序的外部存储权限,如下所示:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

并确保您已授予这些权限。

enter image description here

第 2 步:

假设您下载了 .so文件位于 /Download/您的外部 SD 卡,即 /Download/libnative-lib.so .下面的代码 fragment 将复制 libnative-lib.so/data/data/<your-app-id>/files/libnative-lib2.so并加载这个 libnative-lib2.so会成功的。

    String path_sd_card = Environment.getExternalStorageDirectory().getAbsolutePath();

FileOutputStream outputStream;
FileInputStream inputStream;

// 1. This path works.
//System.load("/data/data/com.arophix.jniexample/files/libnative-lib.so");
String filesDir = getFilesDir().getAbsolutePath();

try {
inputStream = new FileInputStream(new File(path_sd_card + "/Download/libnative-lib.so"));
outputStream = new FileOutputStream(new File(filesDir + "/libnative-lib2.so"));//openFileOutput("libnative-lib2.so", Context.MODE_PRIVATE);

FileChannel inChannel = inputStream.getChannel();
FileChannel outChannel = outputStream.getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inputStream.close();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

// This path works
System.load(filesDir + "/libnative-lib2.so");

注意:已在 Android Emulator Nexus 6P API 23 上验证。

关于android - 如何在 Android N 上为 NativeActivity 动态加载原生共享库 (.so)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53773791/

47 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com