我正在为我的arduino汽车制作一个遥控应用程序。所使用的代码首先在Eclipse中使用Java进行了测试,现在我试图为Android应用程序使用相同的代码。
我使用过jSerialComm库,根据Android Studio,我的代码没有错误,但是当我运行它时,它无法找到库?我收到以下错误:
致命的例外:主要 过程:com.sahragard.avengrecontroller,PID:11728 java.lang.UnsatisfiedLinkError:dlopen失败:文件偏移量 图书馆 " /data/user/0/com.sahragard.avengrecontroller/cache/1454627726168-libjSerialComm.so"
=文件大小:0> = 0 在java.lang.Runtime.load(Runtime.java:332) 在java.lang.System.load(System.java:1069) 在com.fazecast.jSerialComm.SerialPort。(SerialPort.java:181) 在com.sahragard.avengrecontroller.Conn.getPorts(Conn.java:19) 在 com.sahragard.avengrecontroller.MainActivity.onCreate(MainActivity.java:25) 在android.app.Activity.performCreate(Activity.java:6237) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 在android.app.ActivityThread.-wrap11(ActivityThread.java) 在 android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1344) 在android.os.Handler.dispatchMessage(Handler.java:102) 在android.os.Looper.loop(Looper.java:148) 在android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) 在 com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
我用谷歌搜索了几个小时并按照我发现的提示,但无论我做什么,它总是一样的错误。我根据这篇文章添加了库: https://stackoverflow.com/a/16628496/4582696
我感谢任何帮助!提前谢谢。
修改
MainActivity类是包含Swing接口的类的改编,其代码添加在此代码下面
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Spinner conSpinner =(Spinner) findViewById(R.id.spinner);
String[] a = new String[Conn.getPorts().length];
for(int i=0; i<Conn.getPorts().length; i++){
a[i] = Conn.getPorts()[i].getSystemPortName();
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, a);
conSpinner.setAdapter(adapter);
final Button disconnectButton = (Button) findViewById(R.id.disconnect);
disconnectButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Conn.disconnect();
}
});
final Button connectButton = (Button) findViewById(R.id.connect);
connectButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Conn.connect(conSpinner.getSelectedItemPosition());
Runnable run = new Runnable() {
public void run() {
Conn.listen();
}
};
Conn.listen = new Thread(run);
Conn.listen.start();
}
});
final Button up = (Button) findViewById(R.id.upButton);
up.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Conn.sendMsg("w");
}
});
final Button down = (Button) findViewById(R.id.downButton);
down.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Conn.sendMsg("s");
}
});
final Button left = (Button) findViewById(R.id.leftButton);
left.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Conn.sendMsg("a");
}
});
final Button right = (Button) findViewById(R.id.rightButton);
right.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Conn.sendMsg("d");
}
});
}
}
原始Remote_Interface类
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import com.fazecast.jSerialComm.SerialPort;
import javax.swing.JComboBox;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JTextPane;
import java.awt.SystemColor;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Remote_Interface extends JFrame {
private JPanel contentPane;
private JTextField textField;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Remote_Interface frame = new Remote_Interface();
frame.setVisible(true);
// Conn.listen();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Remote_Interface() {
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 270, 268);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JComboBox<String> comboBox = new JComboBox<String> ();
comboBox.setBounds(20, 46, 214, 20);
for(int i=0; i<Conn.getPorts().length; i++){
comboBox.addItem(Conn.getPorts()[i].getSystemPortName());
}
contentPane.add(comboBox);
textField = new JTextField();
textField.setBounds(20, 131, 214, 20);
contentPane.add(textField);
textField.setColumns(10);
textField.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
Conn.sendMsg(e.getActionCommand());
textField.setText("");
}
});
JButton btnNewButton = new JButton("Send");
btnNewButton.setBounds(20, 162, 89, 23);
contentPane.add(btnNewButton);
JTextPane txtpnPleaseSelectA = new JTextPane();
txtpnPleaseSelectA.setBackground(SystemColor.control);
txtpnPleaseSelectA.setText("Please select a port to connect");
txtpnPleaseSelectA.setEditable(false);
txtpnPleaseSelectA.setBounds(10, 11, 214, 20);
contentPane.add(txtpnPleaseSelectA);
btnNewButton.setEnabled(false);
textField.setEnabled(false);
JButton btnNewButton_1 = new JButton("Connect");
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Conn.connect(comboBox.getSelectedIndex());
btnNewButton.setEnabled(true);
textField.setEnabled(true);
Runnable run = new Runnable(){
public void run(){
Conn.listen();
}
};
Conn.listen = new Thread(run);
Conn.listen.start();
}
});
btnNewButton_1.setBounds(143, 77, 89, 23);
contentPane.add(btnNewButton_1);
JButton btnD = new JButton("Disconnect");
btnD.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Conn.disconnect();
btnNewButton.setEnabled(false);
textField.setEnabled(false);
}
});
btnD.setBounds(20, 77, 89, 23);
contentPane.add(btnD);
}
}
和康恩班
import com.fazecast.jSerialComm.*;
import java.io.PrintWriter;
import java.util.Scanner;
public class Conn {
static PrintWriter out;
static SerialPort[] ports;
static SerialPort port;
static Scanner in;
static Thread listen;
public static SerialPort[] getPorts(){
ports = SerialPort.getCommPorts();
return ports;
}
public static void sendMsg(String s){
out.println(s);
out.flush();
}
public static void connect(int i){
port = ports[i];
port.openPort();
port.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);
out = new PrintWriter(port.getOutputStream());
in = new Scanner(port.getInputStream());
}
public static void disconnect(){
port.closePort();
}
public static void listen(){// handle the input from the Arduino chip
while(in.hasNextLine()){
System.out.println(in.nextLine());// just print it out to the console
}
}
}
答案 0 :(得分:1)
假设这个代码在Android设备上运行得非常好,老实说我不明白你为什么会得到任何错误,因为很明显库是在堆栈跟踪中加载的,否则你会得到编译错误和类找不到异常。
无论如何,这就是正在发生的事情......
final Spinner conSpinner =(Spinner) findViewById(R.id.spinner);
String[] a = new String[Conn.getPorts().length];
for(int i=0; i<Conn.getPorts().length; i++){
a[i] = Conn.getPorts()[i].getSystemPortName();
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, a);
conSpinner.setAdapter(adapter);
以后再做
Conn.connect(conSpinner.getSelectedItemPosition());
...(大致)调用
public static void connect(int i){
port = SerialPort.getCommPorts()[i];
port.openPort();
...
}
我认为当你明确想要一个实例变量时,你不应该使用静态方法。
我知道这段代码没有&#34;重要&#34; per-say,但我将您的类修改为适当的实例变量,这是保存Conn
变量状态的首选方法。
我会解释static
和非静态变量之间的区别,但这对于您显示的错误而言过于宽泛。
以下是包含评论的更新Conn.java
。
注意我可能打错了或其他一些错误,我没有尝试编译这个
import com.fazecast.jSerialComm.*;
import java.io.PrintWriter;
import java.util.Scanner;
public class Conn {
/* These are instance variables for *THIS* Conn object */
private PrintWriter out;
// static SerialPort[] ports; // unneccessary
private SerialPort port;
private Scanner in;
// static Thread listen; // unused
// this acts like the connect method
// it initializes all your stuff
public Conn(int i) {
this.port = SerialPort.getCommPorts()[i];
// maybe you should check this to see it was opened
boolean opened = port.openPort();
if (!opened) {
System.err.println("Oh no! The port wasn't opened");
}
this.port.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0);
this.out = new PrintWriter(port.getOutputStream());
this.in = new Scanner(port.getInputStream());
}
// not needed here, just call SerialPort.getCommPorts() in any other class
/*
public static SerialPort[] getPorts(){
ports = SerialPort.getCommPorts();
return ports;
}
*/
public void sendMsg(String s){
this.out.println(s);
this.out.flush();
}
// Maybe propogate whether you successfully closed the Connection
public boolean disconnect(){
return this.port.closePort();
}
// You probably want this on a separate thread since this will block the main thread
// ... that's another topic though
public void listen(){// handle the input from the Arduino chip
while(this.in.hasNextLine()){
System.out.println(in.nextLine());// just print it out to the console
}
}
}
这是一个更新的Activity,只有几个按钮监听器供参考。请注意所有方法中的私有conn
字段和conn
小写c
以及连接按钮中的conn = new Conn(position)
。你并不需要一个静态课程,我试图在这里展示,真的...
import com.fazecast.jSerialComm.*;
public class MainActivity extends AppCompatActivity {
private conn Conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Spinner conSpinner =(Spinner) findViewById(R.id.spinner);
SerialPort[] ports = SerialPort.getCommPorts()
String[] a = new String[ports.length];
for(int i=0; i<ports.length; i++){
a[i] = ports[i].getSystemPortName();
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, a);
conSpinner.setAdapter(adapter);
final Button connectButton = (Button) findViewById(R.id.connect);
connectButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
conn = new Conn(conSpinner.getSelectedItemPosition());
Runnable run = new Runnable() {
public void run() {
conn.listen();
}
};
new Thread(run).start();
}
});
final Button disconnectButton = (Button) findViewById(R.id.disconnect);
disconnectButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
if (conn != null) {
conn.disconnect();
}
}
});
final Button up = (Button) findViewById(R.id.upButton);
up.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
if (conn != null) {
conn.sendMsg("w");
}
}
});
}
}
答案 1 :(得分:1)
我有同样的问题,我能够解决的唯一方法是:
之后
SerialPort myPort = SerialPort.getCommPort("/dev/ttyMT2");
给出了相应的对象,没有任何UnsatisfiedLinkError。
*另一件事,如果您使用/ dev文件夹,可能需要进行android构建,其中SeLinux权限模式设置为Disabled或Permissive。 https://www.centos.org/docs/5/html/5.1/Deployment_Guide/sec-sel-enable-disable.html