- 硬件平台:tiny4412
- 系统:Android 5.0.2
- 编译器: arm-linux-gcc-4.5.1
(一)Android通过JNI访问硬件
http://blog.csdn.net/fengyuwuzu0519/article/details/55224423
(二)Android通过硬件访问服务访问硬件
http://blog.csdn.net/fengyuwuzu0519/article/details/55271199
(三)Android加入HAL层访问硬件
http://blog.csdn.net/fengyuwuzu0519/article/details/55274891
现在我们写一个Android APP软件,来操作硬件。本文重点在于说明如何写一个硬件访问服务的APP,重点不在于APP的编写。
一、通过XML编写界面(简单)
二、通过java编译activity内容实现逻辑(简单)
(1)获取组件
(2)监听事件
三、APP调用硬件访问服务的编写要点
1、java通过JNI直接操作硬件
(1)HardControl.JAVA
加载C库,JNI的第一步
package com.example.yangfei.hardlibrary;
public class HardControl {
public static native int ledCtrl(int which, int status);
public static native int ledOpen();
public static native void ledClose();
static {
try {
System.loadLibrary("hardcontrol");
} catch (Exception e) {
e.printStackTrace();
}
}
}
(2)修改build.gradle,添加
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
指定SO库的路径
(3)在app/libs下建armeabi子目录,放入so文件
(4)操作硬件
HardControl hardControl = new HardControl();//依赖硬件
HardControl hardControl = new HardControl();
HardControl.ledCtrl(2, 1);
(5)JNI编译出SO,注意里面包名的信息
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <android/log.h>
#if 0
typedef struct {
char *name;
char *signature;
void *fnPtr;
} JNINativeMethod;
#endif
static jint fd;
jint ledOpen(JNIEnv *env, jobject cls)
{
fd = open("/dev/leds", O_RDWR);
__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledOpen : %d", fd);
if (fd >= 0)
return 0;
else
return -1;
}
void ledClose(JNIEnv *env, jobject cls)
{
__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledClose ...");
close(fd);
}
jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
{
int ret = ioctl(fd, status, which);
__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledCtrl : %d, %d, %d", which, status, ret);
return ret;
}
static const JNINativeMethod methods[] = {
{"ledOpen", "()I", (void *)ledOpen},
{"ledClose", "()V", (void *)ledClose},
{"ledCtrl", "(II)I", (void *)ledCtrl},
};
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;
}
cls = (*env)->FindClass(env, "com/example/yangfei/hardlibrary/HardControl");
if (cls == NULL) {
return JNI_ERR;
}
if ((*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(methods[0])) < 0)
return JNI_ERR;
return JNI_VERSION_1_4;
}
从C文件编译出SO库:
arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so -I /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/include /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/liblog.so
为什么这么编译
-I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ : jni.h的存放目录
-nostdlib 不使用标准库 是android系统源码里的 如下:
/work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/libc.so : 指定libc.so,因为依赖于这个库
加入打印信息
__android_log_print(ANDROID_LOG_DEBUG,"LEDDemo", "native ledOpen ...");
–I /work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/include
/work/android-5.0.2/prebuilts/ndk/9/platforms/android-19/arch-arm/usr/lib/liblog.so
为什么这么编译SO详细见http://blog.csdn.net/fengyuwuzu0519/article/details/55224423
2、java通过硬件访问服务操作硬件
(1)操作硬件
import android.os.ILedService;
private ILedService iLedService = null ;
iLedService = ILedService.Stub.asInterface(ServiceManager.getService("led"));
iLedService.ledCtrl(1, 1);
(2)import android.os.ILedService;本地并没有所以:
需要包含点什么,参考:
http://stackoverflow.com/questions/7888191/how-do-i-build-the-android-sdk-with-hidden-and-internal-apis-available
怎么包含参考:
https://www.jetbrains.com/idea/help/configuring-module-dependencies-and-libraries.html
(3)import android.os.ServiceManager;
(4)iLedService.ledCtrl(i, 1)增加try catch
(5)编译报错 java.lang.OutOfMemoryError: GC overhead limitexceeded:
参考:
http://stackoverflow.com/questions/25013638/android-studio-google-jar-causing-gc-overhead-limit-exceeded-error
build.gradle android加入:
dexOptions {
javaMaxHeapSize "4g"
}
(5)编译报错: Too many field references
参考:
Building Apps with Over 65K Methods
https://developer.android.com/tools/building/multidex.html
AndroidManifest.xml增加:
<application
android:name=“android.support.multidex.MultiDexApplication”
build.gradle defaultConfig加入:
multiDexEnabled true
四、linux驱动之LED
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
static int led_gpios[] = {
EXYNOS4212_GPM4(0),
EXYNOS4212_GPM4(1),
EXYNOS4212_GPM4(2),
EXYNOS4212_GPM4(3),
};
static int led_open(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < 4; i++)
s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);
return 0;
}
static long led_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
if ((cmd != 0) && (cmd != 1))
return -EINVAL;
if (arg > 4)
return -EINVAL;
gpio_set_value(led_gpios[arg], !cmd);
return 0;
}
static struct file_operations leds_ops = {
.owner = THIS_MODULE,
.open = led_open,
.unlocked_ioctl = led_ioctl,
};
static int major;
static struct class *cls;
int leds_init(void)
{
major = register_chrdev(0, "leds", &leds_ops);
cls = class_create(THIS_MODULE, "leds");
device_create(cls, NULL, MKDEV(major, 0), NULL, "leds");
return 0;
}
void leds_exit(void)
{
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);
unregister_chrdev(major, "leds");
}
module_init(leds_init);
module_exit(leds_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("www.100ask.net");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)