Android(安卓)GPIO 控制方案
16lz
2021-01-25
此方案实现Android APP控制CPU GPIO,支持设置IO方向、输出、输入、按键功能。
[toc]
移植驱动与Framework gpio service
源码
API调用方法
demo
方法1 依赖Framework jar包(不推荐)
- 引入Android定制后的Framework jar包,out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
- 将classes.jar拷贝到app/libs/目录下
- 修改项目根目录build.gradle,在allprojects段内增加下面代码:
allprojects { repositories { google() jcenter() } gradle.projectsEvaluated { tasks.withType(JavaCompile) { options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\classes.jar') } }}
- 修改app/build.gradle,如下:
android{ defaultConfig { multiDexEnabled true }}dependencies { compileOnly files('libs/classes.jar')}preBuild { doLast { def imlFile = file(project.name + ".iml") println('Change ' + project.name + '.iml order') try { def parsedXml = (new XmlParser()).parse(imlFile) def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' } parsedXml.component[1].remove(jdkNode) def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform" new groovy.util.Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK']) groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile)) } catch (FileNotFoundException e) { // nop, iml not found } }}
- 调用
SystemGpio gpioService = (SystemGpio) context.getSystemService("gpio");
方法二 反射调用(==推荐==)
- 在APP源码src/main目录下新建aidl/android/os/这样的目录结构
- 在aidl/android/os/目录下新建IGpioService.aidl文件,内容如下:
package android.os; /** {@hide} */interface IGpioService{ int gpioWrite(int gpio, int value); int gpioRead(int gpio); int gpioDirection(int gpio, int direction, int value); int gpioRegKeyEvent(int gpio); int gpioUnregKeyEvent(int gpio); int gpioGetNumber();}
- 反射调用
Method method = null;try { method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class); IBinder binder = (IBinder) method.invoke(null, new Object[]{"gpio"}); IGpioService gpioService = IGpioService.Stub.asInterface(binder);} catch (Exception e) { e.printStackTrace();}
API使用说明
获取GPIO数量
在使用GPIO前建议先获取GPIO数量,当调用其它方法需要传入参数“gpio”时可以使用0~Number之间的值。
如:gpioGetNumber()返回7,说明一共有7个GPIO,那么传入参数可以为:0、1、2、3、4、5、6。
/** * Get GPIO number * @return <0: error other: GPIO number */public int gpioGetNumber() { if (null != mGpioService) { return mGpioService.gpioGetNumber(); } return -1;}
设置输入输出模式
/** * GPIO direction * @param gpio 0~Number * @param direction 0: input 1: output * @param value 0: Low 1: High */public void gpioDirection(int gpio, int direction, int value) { if (null != mGpioService) { mGpioService.gpioDirection(gpio, direction, value); }}
控制GPIO输出
/** * GPIO write * @param gpio 0~Number * @param value 0: Low 1: High */public void gpioWrite(int gpio, int value) { if (null != mGpioService) { mGpioService.gpioWrite(gpio, value); }}
控制GPIO输入
/** * GPIO read * @param gpio 0~Number * @return 0: Low 1: High other:error */public int gpioRead(int gpio) { if (null != mGpioService) { return mGpioService.gpioRead(gpio); } return -1;}
设置GPIO为按键模式
/** * GPIO register key event * @param gpio 0~Number */public void gpioRegKeyEvent(int gpio) { if (null != mGpioService) { mGpioService.gpioRegKeyEvent(gpio); }}
设置为按键模式后,当GPIO有电平翻转时会上报按键事件,GPIO与KeyCode对应关系如下:
GPIO_0 KeyEvent.KEYCODE_GPIO_0GPIO_1 KeyEvent.KEYCODE_GPIO_1GPIO_2 KeyEvent.KEYCODE_GPIO_2GPIO_3 KeyEvent.KEYCODE_GPIO_3GPIO_4 KeyEvent.KEYCODE_GPIO_4GPIO_5 KeyEvent.KEYCODE_GPIO_5GPIO_6 KeyEvent.KEYCODE_GPIO_6GPIO_7 KeyEvent.KEYCODE_GPIO_7GPIO_8 KeyEvent.KEYCODE_GPIO_8GPIO_9 KeyEvent.KEYCODE_GPIO_9
- 当GPIO变为低电平将上报:KeyEvent.ACTION_DOWN
- 当GPIO变为高电平将上报:KeyEvent.ACTION_UP
如果要取消按键模式则调用如下方法:
/** * GPIO unregister key event * @param gpio 0~Number */public void gpioUnregKeyEvent(int gpio) { if (null != mGpioService) { mGpioService.gpioUnregKeyEvent(gpio); }}
例
依赖Framework jar方式参考源码:
package com.ayst.item;import android.annotation.SuppressLint;import android.content.Context;import android.os.SystemGpio;/** * Created by Administrator on 2018/11/6. */public class GpioTest { private SystemGpio mGpioService; @SuppressLint("WrongConstant") public GpioTest(Context context) { mGpioService = (SystemGpio) context.getSystemService("gpio"); } /** * GPIO write * @param gpio 0~Number * @param value 0: Low 1: High */ public void gpioWrite(int gpio, int value) { if (null != mGpioService) { mGpioService.gpioWrite(gpio, value); } } /** * GPIO read * @param gpio 0~Number * @return 0: Low 1: High other:error */ public int gpioRead(int gpio) { if (null != mGpioService) { return mGpioService.gpioRead(gpio); } return -1; } /** * GPIO direction * @param gpio 0~Number * @param direction 0: input 1: output * @param value 0: Low 1: High */ public void gpioDirection(int gpio, int direction, int value) { if (null != mGpioService) { mGpioService.gpioDirection(gpio, direction, value); } } /** * GPIO register key event * @param gpio 0~Number */ public void gpioRegKeyEvent(int gpio) { if (null != mGpioService) { mGpioService.gpioRegKeyEvent(gpio); } } /** * GPIO unregister key event * @param gpio 0~Number */ public void gpioUnregKeyEvent(int gpio) { if (null != mGpioService) { mGpioService.gpioUnregKeyEvent(gpio); } } /** * Get GPIO number * @return <0: error other: GPIO number */ public int gpioGetNumber() { if (null != mGpioService) { return mGpioService.gpioGetNumber(); } return -1; }}
反射方式参考源码:
package com.ayst.item;import android.annotation.SuppressLint;import android.content.Context;import android.os.IBinder;import android.os.IGpioService;import android.os.RemoteException;import java.lang.reflect.Method;/** * Created by Administrator on 2018/11/6. */public class GpioTest { private IGpioService mGpioService; @SuppressLint("WrongConstant") public GpioTest(Context context) { Method method = null; try { method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class); IBinder binder = (IBinder) method.invoke(null, new Object[]{"gpio"}); mGpioService = IGpioService.Stub.asInterface(binder); } catch (Exception e) { e.printStackTrace(); } } /** * GPIO write * * @param gpio 0~Number * @param value 0: Low 1: High */ public void gpioWrite(int gpio, int value) { if (null != mGpioService) { try { mGpioService.gpioWrite(gpio, value); } catch (RemoteException e) { e.printStackTrace(); } } } /** * GPIO read * * @param gpio 0~Number * @return 0: Low 1: High other:error */ public int gpioRead(int gpio) { if (null != mGpioService) { try { return mGpioService.gpioRead(gpio); } catch (RemoteException e) { e.printStackTrace(); } } return -1; } /** * GPIO direction * * @param gpio 0~Number * @param direction 0: input 1: output * @param value 0: Low 1: High */ public void gpioDirection(int gpio, int direction, int value) { if (null != mGpioService) { try { mGpioService.gpioDirection(gpio, direction, value); } catch (RemoteException e) { e.printStackTrace(); } } } /** * GPIO register key event * * @param gpio 0~Number */ public void gpioRegKeyEvent(int gpio) { if (null != mGpioService) { try { mGpioService.gpioRegKeyEvent(gpio); } catch (RemoteException e) { e.printStackTrace(); } } } /** * GPIO unregister key event * * @param gpio 0~Number */ public void gpioUnregKeyEvent(int gpio) { if (null != mGpioService) { try { mGpioService.gpioUnregKeyEvent(gpio); } catch (RemoteException e) { e.printStackTrace(); } } } /** * Get GPIO number * * @return <0: error other: GPIO number */ public int gpioGetNumber() { if (null != mGpioService) { try { return mGpioService.gpioGetNumber(); } catch (RemoteException e) { e.printStackTrace(); } } return -1; }}
更多相关文章
- ContentProvider实现数据共享1
- Android8.0 PackageManagerService相关 -- APK安装和install 的
- android 中的一些小case
- fanfou(饭否) android客户端 代码学习2
- Android调用摄像头拍照(兼容7.0)
- Android学习整理-2-TabLayout的学习
- android下调用隐藏源码的问题
- Android(安卓)-- 自定义 View XML属性详解
- Android(安卓)隐藏底部虚拟键