简单的手电筒程序(基于系统驱动节点)
来源:互联网 发布:java移植安卓 编辑:程序博客网 时间:2024/05/01 00:58
上一篇文章 简单的手电筒程序(基于Camera类实现) 介绍了通过Camera类进行Flash操作,但是通过camera接口可能会有下面两个问题: 1. 因为是间接使用camera接口,所以时间上会有延时 ;2. 进行Camera相关操作,耗电会比较大。下面我们介绍另外一种方法,通过操作驱动节点进行操作,控制闪关灯亮灭。
我使用的手机是三星G5309W,节点文件为/sys/class/camera/flash/rear_flash,操作如下表:
Flash On写入 “1”Flash Off写入 “0”
我估计并不是每个手机都适用,可以用adb命令 “echo "1" >/sys/class/camera/flash/rear_flash ”验证下你的手机是否支持,当然,前提是root的,因为是system节点,节点的权限如下
如果你发现你的手机支持上面的节点,哈哈,很高兴和可以和你继续share这个有趣的应用,如果没有这个节点,也不用桑心,下面涉及JNI操作,如果你对这个知识点有兴趣也是有所裨益。
大概的思路 : JAVA层通过JNI调用Native层函数进行节点操作
1. Java层的代码比较简单,主要是声明以及调用native函数
package com.saberhao.bulbjni;import android.os.Bundle;import android.app.Activity;import android.graphics.drawable.Drawable;import android.view.Menu;import android.widget.CompoundButton;import android.widget.ImageView;import android.widget.ToggleButton;import android.widget.CompoundButton.OnCheckedChangeListener;public class BulbSwitch extends Activity {ToggleButton tb;static { // load the JNI so System.loadLibrary("BulbJNI"); }//declare the JNI function.plz pay attention to the key word -- "native"public native void TurnOn();public native void TurnOff();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_bulb_switch);tb = (ToggleButton)findViewById(R.id.BulbButton);tb.setOnCheckedChangeListener ( new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView,boolean isChecked){setBulbState(isChecked);} } ); }protected void setBulbState(boolean isChecked) {// TODO Auto-generated method stub ImageView iv=(ImageView)findViewById(R.id.ImageView);iv.setImageResource((isChecked)?R.drawable.bulb_on:R.drawable.bulb_off);if(isChecked)TurnOn();elseTurnOff();ToggleButton tb=(ToggleButton)findViewById(R.id.BulbButton); tb.setChecked(isChecked);} private void releaseImageViews() {ImageView iv=(ImageView)findViewById(R.id.ImageView); releaseImageView(iv); } private void releaseImageView(ImageView imageView) { Drawable d = imageView.getDrawable(); if (d != null) d.setCallback(null); imageView.setImageDrawable(null); imageView.setBackgroundDrawable(null); }}
2. 生成native h头文件
a .通过命令行进入工程目录(D:\workspace\BulbJNI)
#include <jni.h>/* Header for class com_saberhao_bulbjni_BulbSwitch */#ifndef _Included_com_saberhao_bulbjni_BulbSwitch#define _Included_com_saberhao_bulbjni_BulbSwitch#ifdef __cplusplusextern "C" {#endifJNIEXPORT void JNICALL Java_com_saberhao_bulbjni_BulbSwitch_TurnOn (JNIEnv *, jobject);JNIEXPORT void JNICALL Java_com_saberhao_bulbjni_BulbSwitch_TurnOff (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
当然,也可以通过NDK生成头文件,详情请参考文末的参考文献
3.编写Native处理函数
在JNI目录下新建一个Cpp文件,用于实现Native函数,这个也是本应用最重要的一步
#include<jni.h>#include<stdio.h>#include <fcntl.h>#include<sys/types.h>#include<sys/stat.h>#include"com_saberhao_bulbjni_BulbSwitch.h"#include <android/log.h>#include <unistd.h>#define LOG_TAG "BulbJNI"#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)#define TRUNON "1"#define TRUNOFF "0"FILE *fp;int fd;int fd0;JNIEXPORT void JNICALL Java_com_saberhao_bulbjni_BulbSwitch_TurnOn (JNIEnv *, jobject) {fd=open("/sys/class/camera/flash/rear_flash",O_WRONLY);if(fd < 0){LOGE("[turn on]open device error ");}else{LOGI("turn on the flash");write(fd,TRUNON,sizeof(TRUNON));}close(fd);if(fd0 < 0){LOGE("[turn on]open test0 device error ");}else{//rewind(fp);LOGI("turn on test0 the flash");write(fd0,TRUNON,sizeof(TRUNON));}close(fd0); }JNIEXPORT void JNICALL Java_com_saberhao_bulbjni_BulbSwitch_TurnOff (JNIEnv *, jobject) {fd=open("/sys/class/camera/flash/rear_flash",O_WRONLY);if(fd < 0){LOGE("[turn off]open device error ");}else{LOGI("turn off the flash");write(fd,TRUNOFF,sizeof(TRUNOFF));}close(fd); }这部分代码主要实现对节点的操作,也是本应用的核心,有一点是需要注意的,上文提到sys节点的权限,对同个所有者或者同个group是可写的,其他不赋予权限,所以在定义句柄fd的时候必须使用O_WRONLY(只写),而不能使用到 O_RDWR(可读可写),要不然会出现fd初始化失败的情况,这个问题也纠结了我很久~
4.编写JNI mk文件
native函数提供实现方法,需要编译成so文件,才能被JAVA层调用,在JNI文件夹下创建Android.mk
LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := engLOCAL_C_INCLUDES := \$(JNI_H_INCLUDE)LOCAL_PRELINK_MODULE := falseLOCAL_LDLIBS := -llog -lGLESv2LOCAL_MODULE := libBulbJNILOCAL_SRC_FILES :=BulbJNI.cppinclude $(BUILD_SHARED_LIBRARY)
LOCAL_LDLIBS := -llog -lGLESv2 //在Native函数中打log必须添加的lib
LOCAL_MODULE_TAGS := eng //在Eng模式下编译
LOCAL_SRC_FILES -编译的源文件
LOCAL_MODULE -编译的目标对象
5. 编译生成so文件
a. 配置NDK
打开Eclipse,点Window->Preferences->Android->NDK,设置NDK路径,例如D:\android-ndk-r9d-windows-x86\android-ndk-r9d
b. 点Properties->C/C++ Build的Building Settings中去掉Use default build command,然后输入${NDKROOT}/ndk-build.cmd
c. 在C/C++ Build中点击Environment,点Add...添加环境变量NDKROOT,值为NDK的根目录
全部编译之后,就可以再libs目录下看到对应的so文件
6. 添加app mk文件
由于节点 /sys/class/camera/flash/rear_flash 为系统节点,普通应用无法直接操作,需要在xml中添加
android:sharedUserId="android.uid.system"
同时需要在 app的android.mk中添加
LOCAL_CERTIFICATE := platform
才能进行操作,但是eclipse中无法添加Android.mk,所以必须在源代码环境中编译生成apk,添加的mk如下
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := engLOCAL_DEX_PREOPT := falseLOCAL_PRIVILEGED_MODULE := trueLOCAL_PACKAGE_NAME := BulbJNILOCAL_CERTIFICATE := platformLOCAL_SRC_FILES := $(call all-subdir-java-files)include $(BUILD_PACKAGE)################################################### Use the folloing include to make our test apk.include $(call all-makefiles-under,$(LOCAL_PATH))最后,在源码中使用mm进行部分编译即可生成apk
运行效果如下:
Flash OnFlash Off
源代码,请点击这里下载,稍后会传到github~
相关参考文档:
http://jingyan.baidu.com/article/5d6edee22d908799eadeec9f.html
http://blog.csdn.net/sdvch/article/details/17492861
http://blog.csdn.net/vincent_czz/article/details/7199567
http://jingyan.baidu.com/article/5d6edee22d908799eadeec9f.html
- 简单的手电筒程序(基于系统驱动节点)
- 简单的手电筒程序(基于Camera类实现)
- 基于设备树的GPIO驱动(通过系统节点控制)
- android 简单的手电筒制作
- 开启你的闪光灯:手电筒程序(Flash on)
- 基于Android平台开发的手电筒Light
- Android实现一个简单的手电筒
- 系统开关,wifi、手电筒等的开关
- Android第一个小程序(手电筒)
- Android学习之手电筒程序(兼容6.0系统)
- Android学习之手电筒程序(兼容6.0系统)二
- 基于LPC2210的RTL8019AS以太网驱动系统设计(二)
- 基于LPC2210的RTL8019AS以太网驱动系统设计(三)
- 基于LPC2210的RTL8019AS以太网驱动系统设计(四)
- 一键手电筒:光线超亮、简单好用的手电筒
- 基于tiny4412的ts驱动简单分析
- Linux基于事件驱动的程序框架
- 基于VxWorks系统的NVMe驱动
- 交叉编译Ruby for ARM
- hihoCoder挑战赛12 顺子 模拟
- 用户态以及内核态
- 特殊字符搜索
- MapServer 之 发布网络地图服务(WMS-Web Map Service)
- 简单的手电筒程序(基于系统驱动节点)
- 一种基于“哨兵”的分布式缓存设计
- solr系统query检索词特殊字符的处理
- Cannot find the declaration of element 'beans'
- 多线程就这么简单 python版
- 【互联网+】电子商务秘诀
- ubuntu有效的sourcelist配置
- win7 手把手教你将win7背景色修改为浅绿保护色【包括资源管理器的背景】
- 大话设计模式C++版——工厂模式在COM中的典型应用