草庐IT

android - 如何在Android studio中调用.so库的方法

coder 2023-12-19 原文

编辑:查看我的第一个答案。

我想在我的项目中使用 android serialport api。我这样做有很多麻烦。关于如何配置旧版本的 gradle 或如何使用 NDK 进行编译,存在大量相互矛盾的信息,但两者都没有用。我完全迷路了。

我发现唯一可能正确的是以下步骤:

进展#1。我将 libserial_port.so 放在了 src/main/jnilibs/armeabi 中。当我将它作为 zip 文件打开时,它出现在 apk 中。

但是我如何告诉编译器使用这个库呢?如何判断将其包含在项目输出中?我怎样才能引用这个库中的方法? (有一个 SerialPort.c 和一个 SerialPort.h)?将这些 .mk 文件放在哪里?

我觉得我完全错过了一条似乎每个人都假定的信息。在 api 示例中,也没有对 native 库的引用。

进展#2:在我的代码中,我尝试使用
加载库 System.loadLibrary("libserial_port");

这一行抛出一个 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

进步 #3:链接器不支持带下划线的库名称。

进展 #4:链接器采用 lib 前缀。您应该将其排除在 loadlibrary 命令之外。

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

现在开始了解如何从库中引用方法。

最佳答案

我所有问题的答案。适用于 2016 年 1 月带有 gradle 2.2.1 的 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 文件应该在它自己的包中(参见这个问题的答案:How to unit test serial ports in Java on Android)。将 SerialPort.java 和 SerialPortFinder.java 放在/src/java/android_serialport_api 中并将它们留在默认包中(不要将它们移动到您的项目包中,它们不会在那里工作,不要问我如何)。

  5. 在您要使用 SerialPort 类的 java 文件中,添加行 import android_serialport_api.*;

  6. 如果您不想编译 c 代码,则无需安装 NDK(很多指南都假定了这一点)。

  7. 从当前版本的 gradle (2.2.1) 开始,无需更改任何 gradle 构建文件(此处关于 SO 的很多评论会告诉您这样做)。

  8. 您不能在 Android Studio 的项目设置中添加 .so 文件。将 lib 放在 jniLibs 中会将 .so 添加到 APK。

  9. 完整示例(串行输入的线程读取)。

    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 - 如何在Android studio中调用.so库的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34694398/

有关android - 如何在Android studio中调用.so库的方法的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  5. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  6. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  7. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  8. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  9. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  10. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

随机推荐