1. buzzer实验之APK测试
- APK安装测试
注意硬件连接,参考开发板驱动入门之点亮一个灯
注意需要使用新版本的内核驱动
APK是AndroidPackage的缩写,即Android安装包(apk)。 - 测试步骤
PC上安装应用宝管家
启动开发板,开发板稳定后,连接OTG线(启动后无法连接热拔插一下)
打开\我的手机\应用\我的应用\连接手机
打开下载的buzzertestAndroid工程文件夹,进入\buzzertest\bin双击buzzertest.apk应用安装
- 如果升级失败,提示:apk应用程序文件认证不一致,无法安装,建议取消这个任务 可以先卸载应用
2.buzzer实验平台介绍
-
Java(需要掌握一点Java的语言知识,类库的概念,面向对象的概念)
Java是最接近自然语言的编程语言
没有Java的知识,有C的基础,需要学习Java的面向对象概念
百度java教程,推荐马士兵java视频教程,不要多看,看到常用类就可以不看了 -
Android(掌握基本的概念,布局管理器,基本组件,硬件抽象层等)
熟悉Android开发环境的基本结构,库的调用
百度android学习视频,轻松几步学Android开发
3. 如何导入工程
- File/Import
选择Android工程(因为Eslipse支持很多中程序语言,当然也要下载相对应的包)
Import Projects/Browse选择buzzer文件
Finish
4.Android程序activity_main.xml的分析
- 打开工程文件res/layout/ activity_main.xml,这里可以切换到代码模式或者图形模式。
代码可以看出Java是最接近自然语言的编程语言 - activity(关键词Android四大组件)
Activity是Android组件中最基本也是最为常见用的四大组件之一
android:id="@+id/button1": button1为身份表示
android:layout : button位置
android:text=“Start” />: text按钮显示内容
5.Android程序MainActivity.java 分析
- 打开工程src/com.topeet.buzzertest/ MainActivity.java/MainActivity
package com.topeet.buzzertest;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.Button;
import android.widget.EditText;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
class buzzer {
public native int Open();
public native int Close();
public native int Ioctl(int num, int en);
}
public class MainActivity extends Activity {
/* add by cym 20140618 */
buzzer buzzer = new buzzer();
private Button start;
private Button stop;
/* end add */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* add by cym 20140618 */
start = (Button)findViewById(R.id.button1);
stop = (Button)findViewById(R.id.button2);
buzzer.Open();
start.setOnClickListener(new manager());
stop.setOnClickListener(new manager());
/* end add */
}
class manager implements OnClickListener{
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
buzzer.Ioctl(0, 1);
break;
case R.id.button2:
buzzer.Ioctl(0, 0);
break;
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/* add by cym 20140617 */
static {
System.loadLibrary("buzzer");
}
/* end add */
}
-
src/MainActivity.java
这是主程序程序的入口 -
package com.topeet.buzzertest;
将程序打包,封装成类 -
import android.os.Bundle;
每个extends 了Activity的类中 oncreat方法都需要传递一个bundle 参数 -
class buzzer
定义buzzer类,要和硬件抽象层联系到一起,在Java中,native表示一个方法只可以调用不能编写 -
public class MainActivity extends Activity
定义MainActivity 类 -
buzzer buzzer = new buzzer()
new一个buzzer -
private Button start
“定义局部变量”
private 局部有效 -
onCreate
OnCreate是Andorid中的一个特别的函数,来“表示一个窗口正在生成”
对应import android.os.Bundle -
super.onCreate(savedInstanceState)
扫描二维码关注公众号,回复: 9481226 查看本文章 -
setContentView(R.layout.activity_main)
activity_main就是当前项目res下的layout里的activity_main.xml文件
setContentView就是设置当前的Activity显示的内容按activity_main.xml布局。super.onCreate(savedInstanceState)就是调用父类的onCreate构造函数,savedInstanceState是保存当前Activity的状态信息。 -
start = (Button)findViewById(R.id.button1)
android 的用户界面一般使用xml文件做的,对应的xml文件在layout包下如果xml里放了个按钮什么的,在activity中要获取该按钮就用 findViewById(R.id.xml文件中对应的id) -
buzzer.Open()
打开
在JAVA中 native关键字表示一个方法只可以调用,但是不能编写! -
start.setOnClickListener(new manager())
将这个内部类的对象传入按钮的setOnClickListener方法中,监听,回调 -
class manager implements OnClickListener
你创建的一个名为manager的类实现一个叫做OnClickListener的接口 -
public void onClick(View v)
触发事件 -
public boolean onCreateOptionsMenu(Menu menu)
创建菜单 -
System.loadLibrary
调用JNI/lib中的libbuzzer.so文件 -
Android硬件抽象层
Android的硬件抽象层,简单来说,就是对Linux内核驱动程序的封装,向上提供接口,屏蔽底层的实现细节
6. 硬件抽象层在哪个地方呢
- 进入JNI中的.c文件
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdint.h>
#include <termios.h>
#include <android/log.h>
#include <sys/ioctl.h>
#include "com_topeet_buzzertest_buzzer.h"
#undef TCSAFLUSH
#define TCSAFLUSH TCSETSF
#ifndef _TERMIOS_H_
#define _TERMIOS_H_
#endif
int fd=0;
/*
* Class: com_topeet_buzzertest_buzzer
* Method: Open
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_topeet_buzzertest_buzzer_Open
(JNIEnv *env, jobject obj)
{
if(fd<=0)fd = open("/dev/buzzer_ctl", O_RDWR|O_NDELAY|O_NOCTTY);
if(fd <=0 )__android_log_print(ANDROID_LOG_INFO, "serial", "open /dev/buzzer_ctl Error");
else __android_log_print(ANDROID_LOG_INFO, "serial", "open /dev/buzzer_ctl Sucess fd=%d",fd);
}
/*
* Class: com_topeet_buzzertest_buzzer
* Method: Close
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_topeet_buzzertest_buzzer_Close
(JNIEnv *env, jobject obj)
{
if(fd > 0)close(fd);
}
/*
* Class: com_topeet_buzzertest_buzzer
* Method: Ioctl
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_topeet_buzzertest_buzzer_Ioctl
(JNIEnv *env, jobject obj, jint num, jint en)
{
ioctl(fd, en, num);
}
-
JNIEXPORT
在Jni编程中所有本地语言实现Jni接口的方法前面都有一个"JNIEXPORT",这个可以看做是Jni的一个标志 -
jint
可以传递数值 -
JNICALL
可以理解为Jni 和Call两个部分,和起来的意思就是 Jni调用XXX(后面的XXX就是JAVA的方法名)。 -
Java_com_topeet_buzzertest_buzzer_Open
-
Java_com_topeet_buzzertest_buzzer_Close
-
Java_com_topeet_buzzertest_buzzer_Ioctl
Java_com_topeet对应mainactivity中的com.topeet.buzzertest
buzzer对应其中的class buzzer
Open,Close,Ioctl对应buzzer中的操作
我们在MainActivity.java中操作open,close等函数时,因为有调用so库,对应的就会调用JNI文件中的本地方法,对应的方法名,Java+(mainactivity的包名)+类名+本地方法名 -
JNIEnv env, jobject obj
Android通过这两个参数调用该文件中的操作
jint num, jint en 表示传输的数值