Android *.so included*.jar中的库包含不满意的链接错误
我用本机共享库(libnativeext.so)编写了android应用程序 在应用程序中的java类内部,我加载libnativeext.so System.loadLibrary(“NativeText”)。 一切都很好。 编译本机代码,并libnativeext.so放置在/libs/armeabi/文件夹中。 最后一个first.apk文件包含/lib/armeabi/libnativeext.So,安装在设备上,所有工作正常 然后我在javaext.jar中导出项目 此时,javaext.jar在/libs/armeabi/中包含libnativeext.so 在新项目(第二个项目)中,我包括javaext.jar,并在java构建路径中将路径添加到javaext.jar。 项目生成时,在javaext.jar中仅对本机库发出警告。 我在eclipse首选项中禁用警告 但在我得到的设备上:java.lang.UnsatisfiedLinkError:无法加载NativeText:findLibrary返回null 奇怪,因为second.apk中有/libs/armeabi/libnativeext.so。我转到手机,发现手机上的文件夹/data/data/myapp/lib/是空的!当然System.loadLibrary也找不到libnativeText.so 我为自己找到了解决办法,但看起来很难看,我想找到更好的办法 我在现有的第二个proj/libs/文件夹armeabi中创建,并将libnativeext.so放入其中 第二个项目:Android *.so included*.jar中的库包含不满意的链接错误,android,jar,android-ndk,shared-libraries,Android,Jar,Android Ndk,Shared Libraries,我用本机共享库(libnativeext.so)编写了android应用程序 在应用程序中的java类内部,我加载libnativeext.so System.loadLibrary(“NativeText”)。 一切都很好。 编译本机代码,并libnativeext.so放置在/libs/armeabi/文件夹中。 最后一个first.apk文件包含/lib/armeabi/libnativeext.So,安装在设备上,所有工作正常 然后我在javaext.jar中导出项目 此时,javaex
/libs/armeabi/libnativeext.so
/libs/javaext.jar 当我构建项目时,我会查看second.apk:
/lib/armeabi/libnativeext.so如果无法将*.so库从包含的*.jar打包到最终的*.apk中,我可以自己解决这个问题 我写了LibraryLoader,它:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import android.content.Context;
import android.util.Log;
public class SharedLibraryLoader
{
private static Context context;
private static String libDir = "lib";
private static String shortLibName;
private static String fullLibName;
static public boolean loadLibrary(String libName, Context ctx)
{
context = ctx;
shortLibName = libName;
fullLibName = "lib" + libName + ".so";
try
{
Log.d("SharedLibraryLoader", "Trying to load library");
System.loadLibrary(shortLibName);
Log.d("SharedLibraryLoader", "Library was loaded from default location");
return true;
}
catch(UnsatisfiedLinkError e)
{
Log.d("SharedLibraryLoader","Lib wasn't found at default location. Trying to find in application private storage");
String path = null;
path = findInAppStorage(fullLibName);
if(path != null)
{
Log.d("SharedLibraryLoader","Lib was found in application private storage. Loading lib...");
System.load(path);
return true;
}
else
{
Log.d("SharedLibraryLoader","Lib was not found in application private storage. Trying to find in apk...");
path = findInApkAndCopyToAppStorage(fullLibName);
if(path != null)
{
Log.d("SharedLibraryLoader","Lib was found in apk and copied to application private storage. Loading lib...");
System.load(path);
return true;
}
else
{
Log.d("SharedLibraryLoader", "FAILED TO LOAD LIBRARY");
return false;
}
}
}
}
static private String findInAppStorage(String libName)
{
Log.d("SharedLibraryLoader","enter findInAppStorage()");
String basePath = context.getApplicationInfo().dataDir;
File dataDir = new File(basePath);
String[] listFiles;
String lib = null;
listFiles = dataDir.list();
for(int i=0; i < listFiles.length; i++)
{
lib = findInStorage(basePath + "/" +listFiles[i], libName);
if(lib != null)
{
return lib;
}
}
Log.d("SharedLibraryLoader", "Lib wasn't found.");
return null;
}
static private String findInStorage(String path, String nameOfLib)
{
File file = new File(path);
if(file.isDirectory())
{
Log.d("SharedLibraryLoader","Strorage__dir: " + path + "/");
String[] list = file.list();
String target = null;
for(int i = 0; i < list.length; i++)
{
target = findInStorage(path + "/" + list[i], nameOfLib);
if(target != null)
{
return target;
}
}
}
else
{
Log.d("SharedLibraryLoader","Strorage_file: " + path);
if(path.contains(nameOfLib))
{
Log.d("SharedLibraryLoader","Lib was found in: " + path);
return path;
}
}
return null;
}
static private String findInApkAndCopyToAppStorage(String libName)
{
Log.d("SharedLibraryLoader", "Enter findInApkAndCopyToStorage()");
// ---------------- ZIP - find path to .so inside .apk ------------------
String apkPath = context.getPackageResourcePath();
Log.d("SharedLibraryLoader", String.format("Path to Package resource is: %s", apkPath));
try
{
ZipFile zf = new ZipFile(apkPath);
Enumeration<ZipEntry> zipFiles = (Enumeration<ZipEntry>) zf.entries();
ZipEntry soZipEntry = null;
ZipEntry tempZipEntry;
String tmpString;
for ( ; zipFiles.hasMoreElements();)
{
tempZipEntry = zipFiles.nextElement();
tmpString = tempZipEntry.getName();
if(tmpString.contains(libName))
{
Log.d("SharedLibraryLoader", "Library " + fullLibName + " was found in: " + tmpString);
soZipEntry = tempZipEntry;
}
}
//----------now copy library---------------
Log.d("SharedLibraryLoader", "soZipEntry = " + soZipEntry.toString());
if(soZipEntry != null)
{
InputStream soInputStream = zf.getInputStream(soZipEntry);
File fileDir;
File soFile;
OutputStream outStream;
fileDir = context.getApplicationContext().getDir(libDir, Context.MODE_PRIVATE); // but "app_lib" was created!
String fullSoFilePath = fileDir.getAbsolutePath() + "/" + libName;
Log.d("SharedLibraryLoader", "New libpath is "+ fullSoFilePath);
soFile = new File(fullSoFilePath);
Log.d("SharedLibraryLoader", "Is file already exists? - " + soFile.exists());
outStream = new BufferedOutputStream(new FileOutputStream(soFile));
Log.d("SharedLibraryLoader", "Start copying library...");
byte[] byteArray = new byte[256];
int copiedBytes = 0;
while((copiedBytes = soInputStream.read(byteArray)) != -1)
{
outStream.write(byteArray, 0, copiedBytes);
}
Log.d("SharedLibraryLoader", "Finish copying library");
outStream.close();
soInputStream.close();
return fullSoFilePath;
}
else
{
Log.d("SharedLibraryLoader", "Library not Found in APK");
return null;
}
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
}
import java.io.BufferedOutputStream;
导入java.io.File;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.OutputStream;
导入java.util.Enumeration;
导入java.util.zip.ZipEntry;
导入java.util.zip.ZipFile;
导入android.content.Context;
导入android.util.Log;
公共类SharedLibraryLoader
{
私有静态语境;
私有静态字符串libDir=“lib”;
私有静态字符串shortLibName;
私有静态字符串fullLibName;
静态公共布尔加载库(字符串libName,上下文ctx)
{
上下文=ctx;
shortLibName=libName;
fullLibName=“lib”+libName+“.so”;
尝试
{
d(“SharedLibraryLoader”,“正在尝试加载库”);
System.loadLibrary(shortLibName);
d(“SharedLibraryLoader”,“库是从默认位置加载的”);
返回true;
}
捕获(未满足链接错误e)
{
Log.d(“SharedLibraryLoader”,“在默认位置未找到库。正在尝试在应用程序专用存储中查找”);
字符串路径=null;
路径=findInAppStorage(fullLibName);
if(路径!=null)
{
Log.d(“SharedLibraryLoader”,“在应用程序专用存储中找到了库。正在加载库…”);
系统负载(路径);
返回true;
}
其他的
{
Log.d(“SharedLibraryLoader”,“在应用程序专用存储中找不到库。正在apk中尝试查找…”);
path=findInApkAndCopyToAppStorage(fullLibName);
if(路径!=null)
{
Log.d(“SharedLibraryLoader”,“在apk中找到了库并复制到应用程序专用存储。正在加载库…”);
系统负载(路径);
返回true;
}
其他的
{
Log.d(“SharedLibraryLoader”,“加载库失败”);
返回false;
}
}
}
}
静态私有字符串findInAppStorage(字符串libName)
{
d(“SharedLibraryLoader”,“输入findInAppStorage()”;
字符串basePath=context.getApplicationInfo().dataDir;
文件数据目录=新文件(基本路径);
字符串[]列表文件;
字符串lib=null;
listFiles=dataDir.list();
对于(int i=0;i