编辑:看我的第一个答案。
我想在我的项目中使用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引用方法。
答案 0 :(得分:8)
回答我的所有问题。适用于2016年1月的gradle 2.2.1的android studio 1.5.1。
使用android studio,.so文件应该放在/ app / src / main / jniLibs / [armeabi | armeabi-v7a | x86 | etcetera]。对于eclipse,它是一个不同的目录。
我们不需要标题,c文件或mk文件来实现此目的。
Loadlibrary假设" lib"搜索库时的前缀,如果你想加载libdoesstuff.so,那么命令应该是System.loadLibrary(" doesstuff");我还发现了一些不支持lib名称中的下划线的语句(虽然没有测试)。
serialport api文件应该在它自己的包中(参见这个问题的答案:How to unit test serial ports in Java on Android)。将SerialPort.java和SerialPortFinder.java放在/ src / java / android_serialport_api中并将它们保留在默认包中(不要将它们移动到您的项目包中,他们不会在那里工作,不要这样做问我怎么样。
在您要使用SerialPort类的java文件中,添加行import android_serialport_api。*;
如果您不想编译c代码,则无需安装NDK(很多指南都假设这样)。
从当前发布的gradle版本(2.2.1)开始,无需更改任何gradle构建文件(SO上的很多评论都会告诉您这样做)。
您无法在Android Studio的项目设置中添加.so文件。将lib放在jniLibs中会将.so添加到APK。
完整示例(线程读取串行输入)。
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();
}
}