Android *.so included*.jar中的库包含不满意的链接错误

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

我用本机共享库(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放入其中

第二个项目:
/libs/armeabi/libnativeext.so
/libs/javaext.jar

当我构建项目时,我会查看second.apk:


/lib/armeabi/libnativeext.so如果无法将*.so库从包含的*.jar打包到最终的*.apk中,我可以自己解决这个问题

我写了LibraryLoader,它:

  • 尝试使用System.loadLibrary()加载库

  • 如果失败,则加载程序在应用程序存储中搜索库,如果找到,则使用System.load()加载库

  • 如果在应用程序存储中找不到库,则它将查找.apk文件,并在那里搜索,如果loader find library-将其复制到应用程序存储,然后使用System.load()将其加载

  • 在这里张贴代码-可能对某人有帮助

        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