我正在为我的 arduino 汽车制作一个远程控制应用程序。所使用的代码首先使用 Java 在 Eclipse 中进行了测试,现在我尝试对 Android 应用程序使用相同的代码。
我使用了jSerialComm库,根据Android Studio我的代码没有错误,但是当我运行它时,它找不到该库?我收到以下错误:
FATAL EXCEPTION: main Process: com.sahragard.avengrecontroller, PID: 11728 java.lang.UnsatisfiedLinkError: dlopen failed: file offset for the library "/data/user/0/com.sahragard.avengrecontroller/cache/1454627726168-libjSerialComm.so"
block 引用>= file size: 0 >= 0 at java.lang.Runtime.load(Runtime.java:332) at java.lang.System.load(System.java:1069) at com.fazecast.jSerialComm.SerialPort.(SerialPort.java:181) at com.sahragard.avengrecontroller.Conn.getPorts(Conn.java:19) at com.sahragard.avengrecontroller.MainActivity.onCreate(MainActivity.java:25) at android.app.Activity.performCreate(Activity.java:6237) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
我在谷歌上搜索了很多小时,并按照我找到的提示进行操作,但无论我做什么,总是出现同样的错误。我已经根据这篇文章添加了库: https://stackoverflow.com/a/16628496/4582696
非常感谢我能得到的任何帮助!提前致谢。
编辑:
MainActivity类是对包含Swing接口(interface)的类的改编,其代码添加在这段代码下面
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 } } }
最佳答案
我遇到了同样的问题,解决这个问题的唯一方法是:
- 从 https://github.com/Fazecast/jSerialComm/tree/master/src/main/java/com/fazecast/jSerialComm 复制文件进入我的项目,保持与原始包名称相同的包名称。
- 从 https://mvnrepository.com/artifact/com.fazecast/jSerialComm/1.3.11 下载 jar 并解压它,复制\jSerialComm-1.3.11\Android\内的所有文件夹
- 粘贴项目 src/main/jniLibs 中的所有文件夹
- 调用System.loadLibrary("jSerialComm");在进行任何方法调用之前。
之后
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
关于java - Android - dlopen 失败 : file offset for the library,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35213730/