1 编写底层平台
这一步视不同主板而定,不同主板可能所用的外围硬件不同,驱动部分也就要区别对待。比如有的是用IC芯片进行控制的,有的直接使用GPIO控制。总的来说,虽然硬件不同,但驱动部分提给上层的接口要做到通用。
2 编写控制JNI
现在做android开发的大多采用android studio来进行开发。可以先android studio来自动生成,然后添加进android源码中。大致步骤如下
1)定义一个MyBreathLed类并在其中添加如下代码:
public class MyBreathLed {
static {
static {
//装载库文件
System.loadLibrary("mybreathled");--------->注意:没有lib前缀系统会自动为其自动添加的
}
System.loadLibrary("mybreathled");--------->注意:没有lib前缀系统会自动为其自动添加的
}
//JNI中定义的函数
public native void turnonallleds();
public native void turnoffallleds();
public native void selectleds(int which);
public native void turnonallleds();
public native void turnoffallleds();
public native void selectleds(int which);
//封装JNI函数
public void turnonled(){
turnonallleds();
}
public void turnoffled(){
turnoffallleds();
}
public void selectmyleds(int which){
selectleds(which);
}
}
public void turnonled(){
turnonallleds();
}
public void turnoffled(){
turnoffallleds();
}
public void selectmyleds(int which){
selectleds(which);
}
}
2)在中断下输入\app\build\intermediates\classes\debug进入生成的类目录接着输入
javah com.example.tony.jnidemo.JNITest-------->需要生成的JNI名称
3)在app/src/main目录下创建jni目录(一定要是小写的)
4) debug目录中的.h文件粘贴到jni目录中
5)在jni目录中创建.c文件,文件名称自己取,将头文件中函数申明直接拷来,稍作修改并实现具体功能就搞定了
6) 编写Android.mk编译成库,代码如下,编译其他的库只要将其中的SRC和MODULE部分修改就可以了
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES := \
libmybreathled_jni.cLOCAL_C_INCLUDES := $(JNI_H_INCLUDE)LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llogLOCAL_SHARED_LIBRARIES := libcutils
LOCAL_PRELINK_MODULE := falseLOCAL_MODULE := libmybreathledinclude $(BUILD_SHARED_LIBRARY)
7)将代码放到android的合适位置
8)在device.mk添加PRODUCT_PACKAGES += libmybreathled,好让库打包到内核中
涉及的源码如下:
Created by root on 1/9/17.
libmybreathled_jni---->命名规则lib+名称+_lib
#include <jni.h>
/* Header for class com_dayin_breathled_MyBreathLed */
#include <jni.h>
/* Header for class com_dayin_breathled_MyBreathLed */
#ifndef _Included_com_dayin_breathled_MyBreathLed
#define _Included_com_dayin_breathled_MyBreathLed
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_dayin_breathled_MyBreathLed
* Method: turnonallleds
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_dayin_breathled_MyBreathLed_turnonallleds
(JNIEnv *, jobject);/*
* Class: com_dayin_breathled_MyBreathLed
* Method: turnoffallleds
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_dayin_breathled_MyBreathLed_turnoffallleds
(JNIEnv *, jobject);/*
* Class: com_dayin_breathled_MyBreathLed
* Method: selectleds
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_dayin_breathled_MyBreathLed_selectleds
(JNIEnv *, jobject, jint);#ifdef __cplusplus
}
#endif
#endif
libmybreathled_jni.c----命名规则lib+名称+_lib
// Created by root on 1/9/17.
//
// Created by root on 1/9/17.
//
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <pthread.h>
#include <linux/serial.h>
#include <string.h>
#include "libmybreathled_jni.h"
#include <linux/serial.h>
#include <sys/system_properties.h>
#include<android/log.h>#define BREATHLED_NAME "/dev/breathled"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_dayin_breathled_MyBreathLed
* Method: turnonallleds
* Signature: ()V
*/
JNIEXPORT void JNICALL turnonallleds(JNIEnv *env, jobject thiz)
{
int res = 0;
int fd = 0;
unsigned char buf[2];
fd = open(BREATHLED_NAME, O_RDWR);
buf[0] = 0x31;
res = write(fd,buf,1);
if(fd != -1)
{
close(fd) ;
fd = -1;
}
}/*
* Class: com_dayin_breathled_MyBreathLed
* Method: turnoffallleds
* Signature: ()V
*/
JNIEXPORT void JNICALL turnoffallleds(JNIEnv *env, jobject thiz)
{
int res = 0;
int fd = 0;
unsigned char buf[2];
fd = open(BREATHLED_NAME, O_RDWR);
buf[0] = 0x32;
res = write(fd,buf,1);
if(fd != -1)
{
close(fd) ;
fd = -1;
}
}
/*
* Class: com_dayin_breathled_MyBreathLed
* Method: selectleds
* Signature: (I)V
*/
JNIEXPORT void JNICALL selectleds(JNIEnv *env, jobject thiz, jint dat)
{int res = 0;
int fd = 0;
unsigned char buf[2];
fd = open(BREATHLED_NAME, O_RDWR);
buf[0] = dat;
res = write(fd, buf, 1);
if (fd != -1) {
close(fd);
fd = -1;
}}#ifdef __cplusplus
}
#endif
//JNI register
static const char *classPathName = "com/dayin/breathled/MyBreathLed";static JNINativeMethod methods[] = {
{"turnonallleds", "()V", (void*)turnonallleds },
{"turnoffallleds", "()V", (void*)turnoffallleds },
{"selectleds", "(I)V", (void*)selectleds },
};/*
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;clazz = (*env)->FindClass(env, className);
if (clazz == NULL) {
//LOGE("Native registration unable to find class '%s'", className);
return JNI_FALSE;
}
if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
//LOGE("RegisterNatives failed for '%s'", className);
return JNI_FALSE;
}return JNI_TRUE;
}/*
* Register native methods for all classes we know about.
*
* returns JNI_TRUE on success.
*/
static int registerNatives(JNIEnv* env)
{
if (!registerNativeMethods(env, classPathName,
methods, sizeof(methods) / sizeof(methods[0]))) {
return JNI_FALSE;
}return JNI_TRUE;
}
// ----------------------------------------------------------------------------/*
* This is called by the VM when the shared library is first loaded.
*/
typedef union {
JNIEnv* env;
void* venv;
} UnionJNIEnvToVoid;jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
UnionJNIEnvToVoid uenv;
uenv.venv = NULL;
jint result = -1;
JNIEnv* env = NULL;
//LOGI("JNI_OnLoad");
if ((*vm)->GetEnv(vm, &uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
//LOGE("ERROR: GetEnv failed");
goto bail;
}
env = uenv.env;if (registerNatives(env) != JNI_TRUE) {
//LOGE("ERROR: registerNatives failed");
goto bail;
}
result = JNI_VERSION_1_4;
bail:
return result;
}
3 添加服务类
1)将MyBreathLed.java考到framework/base/core/java/android/app/目录下
2)在framework/base/core/java/android/app目录下新建IMyBreathLedManager.aidl。并添加以下代码,声明接口
/* //device/java/android/android/app/INotificationManager.aidl
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.app;/**
*
* {@hide}
*/interface IMyBreathLedManager
{
void turnonmyleds();
void turnoffmyleds();
void selectmyleds(int which);
}
3)在framework/base目录下的Android.mk中的添加aidl,好让系统编译到。
4)新建MyBreathLedServceManagerService.java,添加如下代码,实现接口功能
package com.android.server;import java.util.ArrayList;import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.IMyBreathLedManager;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import com.dayin.breathled.MyBreathLed;
import android.app.MyBreathLedManager;public class MyBreathLedManagerService extends IMyBreathLedManager.Stub{
private static final String TAG = "MyBreathLedManagerService";
private final Context mContext;
private MyBreathLed myled = new MyBreathLed();MyBreathLedManagerService(Context context) {
super();
mContext = context;
}
public void turnonmyleds() {
myled.turnonled();
}
public void turnoffmyleds() {
myled.turnoffled();
}public void selectmyleds(int which) {
myled.selectmyleds(which);
}
}
5)在framework/base/services/java/com/android/server/SystemServer.java中先导入包
import com.android.server.MyBreathLedManagerService;
接着在startotherService函数中添加如下代码,将服务注册进系统
HallcoverManagerService hallCover = null;
...
try {
Slog.i(TAG, "mybreathled Service");
mybreathled = new MyBreathLedManagerService(context);
Slog.i(TAG, "aa mybreathled Service = "+mybreathled);
ServiceManager.addService(Context.MYBREATH_LED_SERVICE, mybreathled);
Slog.i(TAG, "bb mybreathled Service = "+mybreathled);
} catch (Throwable e) {
Slog.e(TAG, "starting mybreathled Service", e);
Slog.i(TAG, "mybreathled Service");
mybreathled = new MyBreathLedManagerService(context);
Slog.i(TAG, "aa mybreathled Service = "+mybreathled);
ServiceManager.addService(Context.MYBREATH_LED_SERVICE, mybreathled);
Slog.i(TAG, "bb mybreathled Service = "+mybreathled);
} catch (Throwable e) {
Slog.e(TAG, "starting mybreathled Service", e);
6)添加设备权限和相关操作权限
7)编译系统
4 编写app测试
1)将android编译后的out/target/common/obj/JAVA_LIBARIES/framework_intermate文件夹下的classes.jar以模块到如到android工程中
2)编写app代码,其中使用以下语句调用服务:
IMyBreathLedManager manage = IMyBreathLedManager.Stub.anInterface(ServiceManager.getService("mybreathled"));
manager.selectmyleds(0x37);
manager.turnonmyleds();
manager.turnoffmyleds();
3)在app的build.gradle文件中添加如下代码解决编译报错问题
apply plugin: 'com.android.application'android {
compileSdkVersion 24
buildToolsVersion "24.0.1"defaultConfig {
applicationId "dayin.breathled"
minSdkVersion 8
targetSdkVersion 24
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions{
javaMaxHeapSize "4g"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.1.1'
compile project(':classes')
compile 'com.android.support:multidex:1.0.0'
}