如何在Android Studio中的.so库上调用方法 [英] How to call methods on .so library in Android studio

查看:87
本文介绍了如何在Android Studio中的.so库上调用方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请参阅我的第一个答案.

我想在我的项目中使用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");

此行引发UnsatisfiedLinkError. 本机代码库无法加载.java.lang.UnsatisfiedLinkError:无法从加载程序dalvik.system.PathClassLoader [DexPathList [[zip file"/data/app/myapp.apk"],nativeLibraryDirectories=[/data/app]中加载libserial_port -lib/myapp.apk,/vendor/lib,/system/lib]]]:findLibrary返回null

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

进度4:链接器采用lib前缀.您应该将其保留在loadlibrary命令之外.

现在我调用System.loadLibrary("serialport");我的库名为libserialport.so.现在,我不再收到UnsatisfiedLinkError了!

现在开始查找如何从lib中引用方法.

解决方案

回答我所有的问题.适用于带有gradle 2.2.1一月2016年的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文件应位于其自己的程序包中(请参阅此问题的答案:

Edit: see my first answer.

I'd like to use the android serialport api in my project. I have a lot of trouble doing so. There is an enormous amount of conflicting information about how to configure older versions of gradle or how to compile with NDK which both aren't useful. I am completely lost.

The only thing I found that is probably correct is the following step:

Progress #1. I placed the libserial_port.so in src/main/jnilibs/armeabi. It appears in the apk when I open it as a zip file.

But how do I tell the compiler to use this library? How to tell to include it in the project output? How can I reference methods in this library? (there are a SerialPort.c and a SerialPort.h)?. And where to put these .mk files?

I have the feeling I am completely missing a piece of information that everyone seems to assume. In the api samples there is no referencing to native libraries as well.

Progress #2: In my code I try to load the library using
System.loadLibrary("libserial_port");

This line throws an UnsatisfiedLinkError. Native code library failed to load.java.lang.UnsatisfiedLinkError: Couldn't load libserial_port from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/myapp.apk"],nativeLibraryDirectories=[/data/app-lib/myapp.apk, /vendor/lib, /system/lib]]]: findLibrary returned null

Progress #3: the linker doesn't support library names with underscores.

Progress #4: the linker assumes the lib-prefix. You should leave it out of the loadlibrary command.

Now I call System.loadLibrary("serialport"); and my library is named libserialport.so. Now I don't get the UnsatisfiedLinkError anymore!

Now off to find out how to reference methods from the lib.

解决方案

Answers to all my questions. Valid for android studio 1.5.1 with gradle 2.2.1 january 2016.

  1. With android studio, the .so files should be placed /app/src/main/jniLibs/[armeabi|armeabi-v7a|x86|etcetera]. For eclipse it is a different directory.

  2. We don't need header, c files or mk files for this to work.

  3. Loadlibrary assumes the "lib" prefix when searching for a library so if you want to load libdoesstuff.so the command should be System.loadLibrary("doesstuff"); I also found some statements that underscores in the lib name are not supported (did not test this though).

  4. The serialport api files should be in it's own package (see the answer to this question: How to unit test serial ports in Java on Android). Place the SerialPort.java and SerialPortFinder.java in /src/java/android_serialport_api and leave them in the default package (don't move them to your project package, they won't work there, don't ask me how).

  5. In your java file where you want to use the SerialPort class, add the line import android_serialport_api.*;

  6. There is no need to install the NDK if you don't want to compile c code (a lot of guides assume this).

  7. As of current release version of gradle (2.2.1) there is no need to change any of the gradle build files (a lot of comments here on SO will tell you to do so).

  8. You cannot add the .so files in the project settings in Android Studio. Placing the lib in jniLibs will add the .so to the APK.

  9. Full example (threaded reading of the serial input).

    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();
        }
    }
    

这篇关于如何在Android Studio中的.so库上调用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆