转载自 http://blog.youkuaiyun.com/zyw123/article/details/6891063
最近在做基于一款芯片的FM Radio.有了底层驱动,需要我做上层java代码,已经自己写jni调用驱动,实现FM Radio 的功能。
android NDK开发就不介绍了,这样的可以有很多参考。我只是把我写的部分代码拿出来与大家分享。有做FM Radio 的请参考,也可以提出意见。
首先要有功能代码:做了一个类
package com.mycompanyname.fm;
import android.util.Log;
public class FMFunction {
private static final String TAG = "FMFunction";
public FMFunction() {
Log.i(TAG,"FMFunction created......");
}
public void openFm () {
nativeOpenFM();
}
public void closeFm () {
nativeCloseFM();
}
public int[] scanChannel() {
return nativeScanChannel();
}
public void playChannel(int freq) {
nativePlayChannel(freq);
}
public int getAudioVolume() {
return nativeGetAudioVolume();
}
public void audioUp() {
nativeAudioUp();
}
public void audioDown() {
nativeAudioDown();
}
public void setMute() {
nativeSetMute();
}
public int getRssiLevel() {
return nativeGetRssiLevel();
}
//native function
private native void nativeOpenFM();
private native void nativeCloseFM();
private native int [] nativeScanChannel();
private native void nativePlayChannel(int freq);
private native void nativeAudioUp();
private native void nativeAudioDown();
private native int nativeGetAudioVolume();
private native void nativeSetMute();
private native int nativeGetRssiLevel();
static {
Log.i(TAG,"loadLibrary carry out..............");
System.loadLibrary("fmfunction-jni");
}
}
这个类介绍了要用到的radio 功能。
openFm ():打开radio
closeFm ():关闭radio
scanChannel():扫描所有频道
playChannel(int freq):播放指定频率的频道
getAudioVolume():取得当前音量值
audioUp():提高音量
audioDown():降低音量
setMute():静音
getRssiLevel():取得信号强度
只是简单的写了这些功能,这些功能对播放应该就可以了。
下面还要就这些上层功能做jni实现,jni调用驱动实现上述功能。
jni 代码如下:
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <android/log.h>
#define VIDIOC_S_HW_FREQ_SEEK 0x40305652
struct v4l2_hw_freq_seek {
__u32 tuner;
enum v4l2_tuner_type type;
__u32 seek_upward;
__u32 wrap_around;
__u32 reserved[8];
};
/* parameters for driver use */
static int fd;
int ret;
struct v4l2_capability cap;
struct v4l2_tuner tuner;
struct v4l2_audio a;
struct v4l2_frequency f;
struct v4l2_queryctrl q;
struct v4l2_control c;
struct v4l2_hw_freq_seek seek;
unsigned int i;
unsigned int mute=0;
unsigned int volume = 0;
unsigned int freq = 87500000;
void Java_com_innofidei_fm_FMFunction_nativeOpenFM(JNIEnv* env,jobject thiz) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeOpenFM init............");
fd = open("/dev/radio0",O_RDONLY);
if (fd < 0) {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeOpenFM init failed : %d ",fd);
} else {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeOpenFM init success");
}
}
void Java_com_innofidei_fm_FMFunction_nativeCloseFM(JNIEnv* env,jobject thiz) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeCloseFM .............");
close(fd);
return;
}
jintArray Java_com_innofidei_fm_FMFunction_nativeScanChannel(JNIEnv* env,jobject thiz) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeScanChannel..... .......");
jintArray result;
result = (*env)->NewIntArray(env, 20);
if (result == NULL) {
return NULL;
}
/*init original array for recording frequency info */
jint num[20];
jint i = 0;
for (;i<20;i++) {
num[i] = 0;
}
/* set lowest frequency */
f.frequency = freq *2 /125;
f.type = V4L2_TUNER_RADIO;
f.tuner = 0;
ret = ioctl(fd,VIDIOC_S_FREQUENCY,&f);
if (ret < 0) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","search frequency failed");
} else {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","search frequency success");
}
/*search channel,obtain frequency to enter array */
jint j = 0;
for (;j<20;j++) {
seek.wrap_around = 1;
seek.seek_upward = 0;
seek.tuner = 0;
ret = ioctl(fd,VIDIOC_S_HW_FREQ_SEEK,&seek);
if (ret == 0) {
f.tuner = 0;
ret = ioctl(fd,VIDIOC_G_FREQUENCY,&f);
if (ret < 0) {
__android_log_print(ANDROID_LOG_INFO,"JNIGetFrequency","get frequency failed");
break;
} else {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","get freq is %d",f.frequency);
num[j] = f.frequency;
}
} else {
break;
}
}
(*env)->SetIntArrayRegion(env,result, 0, 20, num);
return result;
}
void Java_com_innofidei_fm_FMFunction_nativePlayChannel(JNIEnv* env,jobject thiz,jint freq){
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativePlayChannel init......,freq is: %d",freq);
f.frequency = freq;
f.type = V4L2_TUNER_RADIO;
f.tuner = 0;
ret = ioctl(fd,VIDIOC_S_FREQUENCY,&f);
if (ret < 0) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativePlay set frequency failed");
} else {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativePlay carry out success");
}
/*unmute */
mute = 0;
c.id = V4L2_CID_AUDIO_MUTE;
c.value = mute;
ret = ioctl(fd,VIDIOC_S_CTRL,&c);
if (ret < 0) {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativePlay can not unmute");
} else {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativePlay unmute success ");
}
/*obtain current volume*/
c.id = V4L2_CID_AUDIO_VOLUME;
ret = ioctl(fd,VIDIOC_G_CTRL,&c);
if (ret < 0) {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","get ctrl failed");
} else {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","current volume is : %d",c.value);
}
}
void Java_com_innofidei_fm_FMFunction_nativeAudioUp(JNIEnv* env,jobject thiz) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeAudioUp...............");
c.id = V4L2_CID_AUDIO_VOLUME;
ret = ioctl(fd,VIDIOC_G_CTRL,&c);
if (ret < 0) {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","get ctrl failed");
} else {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","current volume is : %d",c.value);
volume = c.value;
}
c.id = V4L2_CID_AUDIO_VOLUME;
if (volume < 15) {
c.value = ++volume;
}
volume %=0x0f;
ret = ioctl(fd,VIDIOC_S_CTRL,&c);
if (ret < 0) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","set volume ctrl failed");
}
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","after up, volume: %d",volume);
return;
}
void Java_com_innofidei_fm_FMFunction_nativeAudioDown(JNIEnv* env,jobject thiz) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","nativeAudioDown.............");
c.id = V4L2_CID_AUDIO_VOLUME;
ret = ioctl(fd,VIDIOC_G_CTRL,&c);
if (ret < 0) {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","get ctrl failed");
} else {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","current volume is : %d",c.value);
volume = c.value;
}
c.id = V4L2_CID_AUDIO_VOLUME;
if (volume > 0) {
c.value = --volume;
}
volume %=0x0f;
ret = ioctl(fd,VIDIOC_S_CTRL,&c);
if (ret < 0) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","set volume ctrl failed");
}
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","after down, volume: %d",volume);
return;
}
void Java_com_innofidei_fm_FMFunction_nativeSetMute(JNIEnv* env,jobject thiz) {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeSetMute init..................mute value is : %d",mute);
if (mute == 0) {
mute = 1;
} else {
mute = 0;
}
c.id = V4L2_CID_AUDIO_MUTE;
c.value = mute;
ret = ioctl(fd,VIDIOC_S_CTRL,&c);
if (ret < 0) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","set mute ctrl failed");
}
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","set mute ctrl success");
return;
}
jint Java_com_innofidei_fm_FMFunction_nativeGetAudioVolume(JNIEnv* env,jobject thiz) {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeGetAudioVolume............");
c.id = V4L2_CID_AUDIO_VOLUME;
ret = ioctl(fd,VIDIOC_G_CTRL,&c);
if (ret < 0) {
__android_log_write(ANDROID_LOG_INFO,"JNIMsg","get ctrl failed");
return ret;
}
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","volume is %d",c.value);
return c.value;
}
jint Java_com_innofidei_fm_FMFunction_nativeGetRssiLevel(JNIEnv* env,jobject thiz) {
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","nativeGetRssiLevel init................................");
tuner.index = 0;
ret = ioctl(fd,VIDIOC_G_TUNER,&tuner);
__android_log_print(ANDROID_LOG_INFO,"JNIMsg","rssi level is %d",tuner.signal);
return tuner.signal;
}
这个jni代码可以帮助你理解驱动,以及jni的写法,其中引人#include <android/log.h>头文件是为了用logcat查看代码流程用的。
因为网上的原创代码很少,所以将这些个人原创代码提供给android开发的朋友,为大家做参考。