Android底层驱动开发记录:01_JNI

2023-10-26

最近项目中需要用到了Android底层的开发,正好疫情居家所以又把韦老师的老教程第四期Android教程翻出来学习学习,手边也没有合适的板子,找了一块AIO-3288C的板子接了一块HDMI的屏来用。本来之前一直做单片机的,因此学起来还比较吃力,所以这里做一些记录,以备以后查看。

1. java学习,基本上跟着走了一遍,无波澜。C++因为会一点点就暂时跳过了,不行回来再补吧。

2. AIO-3288C环境搭建,最好是有一台真机 4G以上内存,硬盘至少100G,我这虚拟机空间有限编译不能通过,最后拿出很久之前买的腾讯云,Ubuntu18+2G内存+设置虚拟16G内存+100G硬盘,这个配置是偏低的但勉强用能编译SDK能通过。环境搭建上主要是open-7-jdk比较麻烦,可以参考我另一篇文章。最后达成结果就是,固件能完成RK3288C刷机,能Android studio联调app;mobaxterm ssh sftp获取云服务器资源调试源码(试图在腾讯云上装samba来着,很麻烦,放弃了);串口可以打印RK3288C启动日志;使用Android studio自带的adb设置一下环境变量用来adb调试RK3288C。

3. 开始敲代码吧。

(1)做一个APP,3288真机仿真一下,没难度,跟着做就好了。

package com.example.app_0001_leddemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Toast;
import com.example.hardlibrary.*;

public class MainActivity extends AppCompatActivity {

    private boolean ioonoff=false;
    private Button button=null;
    private CheckBox checkBox_io1=null;
    private CheckBox checkBox_io2=null;
    private CheckBox checkBox_io3=null;
    private CheckBox checkBox_io4=null;

    public void onCheckboxClicked(View view) {
        boolean checked= ((CheckBox)view).isChecked();

        switch (view.getId()){
            case R.id.checkbox_io1:
                if(checked){
                    Toast.makeText(getApplicationContext(), "checkbox1 on ",Toast.LENGTH_SHORT).show();
                    HardCtrl.ioCtrl(0,1);
                }else {
                    Toast.makeText(getApplicationContext(), "checkbox1 off",Toast.LENGTH_SHORT).show();
                    HardCtrl.ioCtrl(0,0);
                }
                break;
            case R.id.checkbox_io2:
                if(checked){
                    Toast.makeText(getApplicationContext(), "checkbox2 on ",Toast.LENGTH_SHORT).show();
                    HardCtrl.ioCtrl(1,1);
                }else {
                    Toast.makeText(getApplicationContext(), "checkbox2 off",Toast.LENGTH_SHORT).show();
                    HardCtrl.ioCtrl(1,0);
                }
                break;
            case R.id.checkbox_io3:
                if(checked){
                    Toast.makeText(getApplicationContext(), "checkbox3 on ",Toast.LENGTH_SHORT).show();
                    HardCtrl.ioCtrl(2,1);
                }else {
                    Toast.makeText(getApplicationContext(), "checkbox3 off",Toast.LENGTH_SHORT).show();
                    HardCtrl.ioCtrl(2,0);
                }
                break;
            case R.id.checkbox_io4:
                if(checked){
                    Toast.makeText(getApplicationContext(), "checkbox4 on ",Toast.LENGTH_SHORT).show();
                    HardCtrl.ioCtrl(3,1);
                }else {
                    Toast.makeText(getApplicationContext(), "checkbox4 off",Toast.LENGTH_SHORT).show();
                    HardCtrl.ioCtrl(3,0);
                }
                break;
        }
    }

    class MyButtonListener implements View.OnClickListener{
        @Override
        public void onClick(View v) {

            //HardCtrl hardCtrl = new HardCtrl();

            ioonoff = !ioonoff;
            if(ioonoff==true){
                button.setText("ALL OFF");
                checkBox_io1.setChecked(true);
                checkBox_io2.setChecked(true);
                checkBox_io3.setChecked(true);
                checkBox_io4.setChecked(true);

                for(int i=0;i<4;i++)
                    HardCtrl.ioCtrl(i,1);
            }else {
                button.setText("ALL ON");
                checkBox_io1.setChecked(false);
                checkBox_io2.setChecked(false);
                checkBox_io3.setChecked(false);
                checkBox_io4.setChecked(false);

                for(int i=0;i<4;i++)
                    HardCtrl.ioCtrl(i,0);
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        HardCtrl.ioOpen();

        button = (Button)findViewById(R.id.bottom_id1);
        checkBox_io1 = (CheckBox)findViewById(R.id.checkbox_io1);
        checkBox_io2 = (CheckBox)findViewById(R.id.checkbox_io2);
        checkBox_io3 = (CheckBox)findViewById(R.id.checkbox_io3);
        checkBox_io4 = (CheckBox)findViewById(R.id.checkbox_io4);

        button.setOnClickListener(new MyButtonListener());
//        button.setOnClickListener(new View.OnClickListener() {
//            public void onClick(View v) {
//                // Code here executes on main thread after user presses button
//
//                ioonoff = !ioonoff;
//                if(ioonoff==true){
//                    button.setText("ALL ON");
//                }else {
//                    button.setText("ALL OFF");
//                }
//            }
//        });
    }
}

(2)app加载jni部分,也没什么难度。

package com.example.hardlibrary;

public class HardCtrl{
    public static native int ioCtrl(int which,int status);
    public static native int ioOpen();
    public static native void ioClose();

    static {
        try {
            System.loadLibrary("hardctrl");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

(3)JNI部分,这部分稍微麻烦一些。完成c代码编写是第一步,第二步在我的腾讯云(TXY)上安装arm-linux-gcc 4.3.2(其他的交叉编译工具好像是有些问题搞这个),并编译jni c代码命令如下,

arm-linux-gcc  -fPIC -shared hardctrl.c -o libhardctrl.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -nostdlib /home/ubuntu/firefly_rk3288_android5.1/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so -I /home/ubuntu/firefly_rk3288_android5.1/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/include/ /home/ubuntu/firefly_rk3288_android5.1/prebuilts/ndk/9/platforms/android-14/arch-arm/usr/lib/liblog.so

没有-nostdlib  编译可以通过但调试会奔溃,因为libc的依赖库不对,可以用ldd xxx.so 查看库依赖。第三步编译好的so库放在app目录下app/libs中。第四步配置Android studio的app工程libs的路径,主要是sourceSets 和debug,好了可以调试仿真了。

   sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        debug {
            ndk {
                abiFilters "armeabi","x86"
            }
        }
    }

此时, 只是app上能点击IO开关了,还没有深入到硬件呢。下面是jni主要的代码。

static const JNINativeMethod methods[] = {
	{"ioOpen", "()I", (void *)ioopen},
	{"ioClose", "()V", (void *)ioclose},
	{"ioCtrl", "(II)I", (void *)ioctrl},
};




/* System.loadLibrary */
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
	JNIEnv *env;
	jclass cls;

	if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {
		return JNI_ERR; /* JNI version not supported */
	}
	cls = (*env)->FindClass(env, "com/example/hardlibrary/HardCtrl");
	if (cls == NULL) {
		return JNI_ERR;
	}

	/* 2. map java hello <-->c c_hello */
	if ((*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(methods[0])) < 0)
		return JNI_ERR;

	return JNI_VERSION_1_4;
}

(4)RK3288c开发板IO驱动编写,这个麻烦就大一些了。 按照其官网维基并结合正点教程完成了驱动。但jni open这个驱动却出现问题,纠其原因是该驱动 权限不足,导致jni open不了,这里找到两个办法解决,

                ① adb root,chmod 777 /dev/xxx  重启后无效

                ②可以在ueventd.rc中赋权比如:system/core/rootdir/ueventd.rc,

/dev/tty* 0777 root system
设备节点 修改权限 该节点的用户 所属的组

                       修改完成后,使用make bootimage 编译命令 会更新ramdisk.img,boot.img,   ueventd.rc

这一阶段的测试就到这里,源码在这里:https://download.csdn.net/download/bwolf1986/85473568?spm=1001.2014.3001.5501

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android底层驱动开发记录:01_JNI 的相关文章

随机推荐

  • [技术发展-16]:高级研修班-智能制造-重构工业制造体系,构建智能化工业互联网平台

    目录 作者主页 https blog csdn net HiWangWenBing 文章出处 https blog csdn net HiWangWenBing article details 118277050 前言 第一章 工业互联网平
  • CART-分类和回归树

    之前在博文 决策树归纳 中 我介绍了用决策树进行分类的算法 包括ID3和C4 5 然而决策树不仅可以用来做数据分类 也可用于做数据回归 1984年Breiman Friedman Olshen等人出版了著作 Classification a
  • 数据库原理期末考试题(经典题型)

    一 单选题 题数 4 共 20 0 分 1 在数据库的三级模式结构中 描述数据库中数据的全局逻辑结构和特征的是 A 外模式 B 内模式 C 存储模式 D 模式 我的答案 D 2 公司中有多个部门和多名职员 每个职员只能属于一个部门 一个部门
  • 必须收藏的python兼职网站大全

    当下python需求量还是挺大的 对于想要做兼职的程序员还是挺友好的 起码不用愁找不到 目前来看 其兼职方向大致有三 开发 爬虫 数据分析 就开发来说 目前python的轮子在Github上一抓一大把 开发成本和开发周期相比于其他语言会更低
  • 【Java】自动拆箱与自动装箱

    自动装箱 自动拆箱是 JDK1 5 提供的功能 自动装箱是把一个基本类型的数据直接赋值给对应的包装类型 自动拆箱是把一个包装类型的对象直接赋值给对应的基本类型 通过自动装箱 拆箱功能 可以大大简化基本类型变量和包装类对象之间的转换过程 Ja
  • MSP430F5529库函数学习——串口

    波特率计算网站 导入MSP430Ware 查看例程 原理图和中文开发手册获取 目录 GPIO setAsPeripheralModuleFunctionInputPin 和GPIO setAsPeripheralModuleFunction
  • pythonlist函数使用方法_python中的list() 函数如何用?

    如果一个地区做统计工作 汉字或者其他东西就可以用数字事先写进去 比如 01代表汉族 那么你在写民族的时候有下拉列表 你就可以打01 就会自动识别为汉族 列表的使用便于计算 查找 分析 处理数据 在python中 有内置函数list 函数用于
  • python之flask框架(一)

    python基础部分咱们基本已经掌握 前面也了解了tkinter的基本用法 这次给大家讲解一下很常见的web框架 就是这个flask框架 其实 python的web框架不仅仅是flask 还有Django Weppy Bottle等还有很多
  • shell中临时使用其他用户执行命令

    问题来源于chinaunix博客论坛 感觉比较实用 整理过来了 我在root中执行一个脚本 但是其中的一些命令或脚本必须用oracle用户来执行 bin sh oracle用户执行 su oracle bin cd xxxx xxx bin
  • 云计算基础——云服务

    目录 云服务概述 云服务简介 云服务的产生和发展 云服务产生的前提 接入云端的主要前端工具 云服务的优缺点 优点 缺点 云服务的类型 SaaS PaaS IaaS 云部署模型 云服务概述 云服务简介 云计算通过使计算分布在大量的分布式计算机
  • I18N多文件数据参数动态获取

    在我们的项目中 控制层获取信息 没有用到ResourceBundle getBundle 而是labelcode 的方式 java I18N 如果有多个配置文件 是怎么读取这些信息的 在控制层怎么读取出相对应的信息出来 参数properti
  • 从零开始学web开发之html5-h5概述

    前言 为了掌握多一门技术 于是开始了学习前端技术的脚步 虽然安卓还是没有深入地学习一些比较高端的知识 比如view绘制原理 事件分发机制 属性动画的绘制 没有深入地研究一些流行框架 最遗憾的是没有将rxjava应用到自己的工作中 更加没有学
  • 元宇宙通证-序一:“元宇宙”和“后人类社会”

    序一 元宇宙 和 后人类社会 一 1992年 尼尔 斯蒂芬森的科幻小说 雪崩 促办 好评如潮 雪崩 描述的是脱胎于现实世界的一代互联网人对两个平行世界的感知和认识 但是 不论是做作 还是书评者 都没预见到在30年之后 此书提出的 元宇宙 M
  • 【微服务部署】四、Jenkins一键打包部署NodeJS(Vue)前端项目步骤详解

    本文介绍使用Jenkins一键将NodeJS Vue 前端项目打包并上传到生产环境服务器 这里使用的是直接打包静态页面 发送到远程服务器Nginx配置目录的方式 首先确保服务器环境配置好 安装Nginx 运行目录 日志存放目录等 一 服务器
  • Flutter GetX 状态管理,路由管理,智能依赖注入

    直接上网址 GetX 关于GetX GetX 是 Flutter 上的一个轻量且强大的解决方案 高性能的状态管理 智能的依赖注入和便捷的路由管理 GetX 有3个基本原则 性能 GetX 专注于性能和最小资源消耗 GetX 打包后的apk占
  • java 工具篇(MySQL数据库工具) 数据库实体创建

    第一步 生成工具源代码 package com mysql util import java io File import java io FileWriter import java io IOException import java
  • Linux内核开发三:多进程编程

    1 什么是进程 我们可以通俗地把进程看作是正在运行着的二进制程序 占用内存空间消耗系统资源 例如使用 vim 命令编辑文件内容就会生成一个进程 进程是 OS 资源分配的基本单位 每个进程在操作系统中都执行着特定的任务 如网络服务 etc i
  • shell拷贝mongodb数据库

    拷贝mongodb数据库 mongodump h 服务器IP port 端口 u 用户名 p 密码 d 数据库 o 导出路径 h MongoDB 所在服务器地址 例如 127 0 0 1 当然也可以指定端口号 127 0 0 1 27017
  • VS2019 无法登录 许可证已过期 无法下载许可证

    许可证已过期 点击检查更新的许可证 报出错误 我们无法下载许可证 请检查你的网络连接或代理设置 解决方法 其实问题就在于嵌入式web浏览器的问题 选择账户选项 账户 登录选项 将嵌入式web浏览器改为系统web浏览器 随后就能登录了
  • Android底层驱动开发记录:01_JNI

    最近项目中需要用到了Android底层的开发 正好疫情居家所以又把韦老师的老教程第四期Android教程翻出来学习学习 手边也没有合适的板子 找了一块AIO 3288C的板子接了一块HDMI的屏来用 本来之前一直做单片机的 因此学起来还比较