Android - dlopen失败:库

时间:2016-02-04 23:32:32

标签: java android

我正在为我的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 
    }
}



}

2 个答案:

答案 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)

我有同样的问题,我能够解决的唯一方法是:

  1. https://github.com/Fazecast/jSerialComm/tree/master/src/main/java/com/fazecast/jSerialComm中的文件复制到我的项目中,保留与原始文件相同的软件包名称。
  2. https://mvnrepository.com/artifact/com.fazecast/jSerialComm/1.3.11下载jar 并提取它,复制\ jSerialComm-1.3.11 \ Android \
  3. 中的所有文件夹
  4. 粘贴项目src / main / jniLibs
  5. 中的所有文件夹
  6. 调用System.loadLibrary(&#34; jSerialComm&#34;);在做任何方法调用之前。
  7. 之后

    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