如何在Android studio中调用.so库中的方法

时间:2016-01-09 14:02:37

标签: android serial-port shared-libraries native

编辑:看我的第一个答案。

我想在我的项目中使用android serialport api。这样做我有很多麻烦。关于如何配置旧版本的gradle或如何使用NDK进行编译存在大量相互矛盾的信息,这些信息都不是很有用。我完全迷失了。

我发现的唯一可能是正确的是以下步骤:

进步#1。我将libserial_port.so放在src / main / jnilibs / armeabi中。当我将其作为zip文件打开时,它出现在apk中。

但是如何告诉编译器使用这个库?如何判断将其包含在项目输出中?如何引用此库中的方法? (有一个SerialPort.c和一个SerialPort.h)?在哪里放这些.mk文件?

我感觉我完全错过了每个人似乎都认为的信息。在api示例中,也没有引用本机库。

进度#2:在我的代码中,我尝试使用
加载库     的System.loadLibrary(" libserial_port&#34);

此行抛出UnsatisfiedLinkError。 本机代码库无法加载.java.lang.UnsatisfiedLinkError:无法从加载器dalvik.system.PathClassLoader加载libserial_port [DexPathList [[zip文件" /data/app/myapp.apk"], nativeLibraryDirectories = [/ data / app-lib / myapp.apk,/ vendor / lib,/ system / lib]]]:findLibrary返回null

进度#3:链接器不支持带下划线的库名。

进度#4:链接器采用lib-prefix。你应该将它从loadlibrary命令中删除。

现在我调用System.loadLibrary(" serialport");我的图书馆名为libserialport.so。现在我再也没有得到UnsatisfiedLinkError了!

现在关闭以了解如何从lib引用方法。

1 个答案:

答案 0 :(得分:8)

回答我的所有问题。适用于2016年1月的gradle 2.2.1的android studio 1.5.1。

  1. 使用android studio,.so文件应该放在/ app / src / main / jniLibs / [armeabi | armeabi-v7a | x86 | etcetera]。对于eclipse,它是一个不同的目录。

  2. 我们不需要标题,c文件或mk文件来实现此目的。

  3. Loadlibrary假设" lib"搜索库时的前缀,如果你想加载libdoesstuff.so,那么命令应该是System.loadLibrary(" doesstuff");我还发现了一些不支持lib名称中的下划线的语句(虽然没有测试)。

  4. serialport api文件应该在它自己的包中(参见这个问题的答案:How to unit test serial ports in Java on Android)。将SerialPort.java和SerialPortFinder.java放在/ src / java / android_serialport_api中并将它们保留在默认包中(不要将它们移动到您的项目包中,他们不会在那里工作,不要这样做问我怎么样。

  5. 在您要使用SerialPort类的java文件中,添加行import android_serialport_api。*;

  6. 如果您不想编译c代码,则无需安装NDK(很多指南都假设这样)。

  7. 从当前发布的gradle版本(2.2.1)开始,无需更改任何gradle构建文件(SO上的很多评论都会告诉您这样做)。

  8. 您无法在Android Studio的项目设置中添加.so文件。将lib放在jniLibs中会将.so添加到APK。

  9. 完整示例(线程读取串行输入)。

    package com.yourpackage;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.io.StringWriter;import java.util.Set;
    import android_serialport_api.SerialPort;
    
    public class SerialPortReader {
        private Thread readSerialDataThread;
        private SerialPort serialPort;
        private InputStream inStream;
        private OutputStream outStream;
        private boolean shouldRun = true;
    
        public SerialPortReader() { }
    
        protected void start() {
            try {
                File portLocation = new File("/dev/ttyS1");
                serialPort = new SerialPort(portLocation, 9600, 0);
                inStream = serialPort.getInputStream();
                outStream = serialPort.getOutputStream();
                sendBytes();
            } catch (IOException e) {
                Log.e("SerialPort", "IOException while opening serial port: " + e.getMessage());
                e.printStackTrace();
            }
            startThread();
        }
    
        protected void stop() {
            // break thread
            this.shouldRun = false;
            try {
                readSerialDataThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            serialPort.close();
        }
    
        private void sendBytes() {
            // example how to send data to the opened serial port
            byte[] data = new byte[]{(byte) 0xFF, (byte) 0xAA, (byte) 0x64};
            try {
                outStream.write(data);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private void startThread() {
            readSerialDataThread = new Thread(new Runnable() {
                public void run() {
                    while (shouldRun) {
                        int dataSize = 0;
                        try {
                            dataSize = inStream.available();
                            byte[] data = new byte[dataSize];
                            inStream.read(data);
                            processData(data);
                            Thread.sleep(50); // my serial sensor gives 20 Hz updates
                        } catch (IOException e) {
                            e.printStackTrace();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            readSerialDataThread.start();
        }
    }