java 控制系统音量_用JNI实现调节win7系统音量

本文介绍如何使用Java结合JNI技术,通过C++编写的DLL动态库来控制Windows7系统的音量。包括设置音量、获取音量、开关静音等操作,并提供了详细的代码实现和步骤。
摘要由CSDN通过智能技术生成

前言

这是我大三时写的,现在把它传到博客园给大家分享.

github地址:https://github.com/silicon621600/SiliconJNIProject/tree/master/JavaControlVolumeOfWin7

一编写包含native方法的Java类文件:

使用了异常处理机制

com.guwei,volume.VolumeControl.java文件

package com.guwei.volume;

/**

* 该类设计为单例模式

* 提供控制win7系统音量的方法

* @author guwei

*

*/

public class VolumeControl {

static

{

System.out.println(System.getProperty("java.library.path"));

System.loadLibrary("VolumeControlDLL");

}

private static VolumeControl uniqueInstance = null;

private VolumeControl() throws OperationFailedException

{

init();

}

/**

* 单例模式

* @return 唯一的VolumeControl 有可能为null

*/

public static VolumeControl getInstance() {

if (uniqueInstance == null) {

try {

uniqueInstance = new VolumeControl();

}catch (OperationFailedException e)

{

e.printStackTrace();

return null;

}

}

return uniqueInstance;

}

/**

* cpp本地一些初始化

* @return

*/

private native void init() throws OperationFailedException;

/**

* 设置音量大小0~100

* @param num

* @return 操作是否成功

*/

public native void setMasterVolume(int num) throws OperationFailedException;

/**

*

* @return 当前音量大小1-100

*/

public native int getMasterVolume() throws OperationFailedException;

/**

* 设置是否静音 true-是 false-否

* @param bMute

* @return

*/

public native void setMute(boolean bMute) throws OperationFailedException;

/**

* 得到当前静音状态 true-是 false-否

* @return

*/

public native boolean getMute() throws OperationFailedException;

/**

* cpp本地释放指针等操作

* @return

*/

private native void finished();

@Override

public void finalize()

{

finished();

}

}

com.guwei,volume.OperationFailedException.java文件

package com.guwei.volume;

public class OperationFailedException extends Exception

{

public OperationFailedException()

{}

public OperationFailedException(String message)

{

super(message);

}

}

一.编译,然后用javah命令生成相应cpp头文件

编译可用命令行javac或eclipse自动编译(javac 注意用-encoding utf8参数)

在完整.class文件位置(不是class文件的存放目录,考虑包名)使用javah命令

javah -jni com.guwei.volume.VolumeControl

也可以用-classpath指明类路径

注意要输入完整的类名,更多参数输入javah查看

命令运行完成后,会出现一个com_guwei_volume_VolumeControl.h文件

4093da2903f7aa8d6be3caf8a6fd1b68.png

8efff0e8a0595c3e8f7d03a3d13efdbd.png

生成的头文件内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class com_guwei_volume_VolumeControl */

#ifndef _Included_com_guwei_volume_VolumeControl

#define _Included_com_guwei_volume_VolumeControl

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: com_guwei_volume_VolumeControl

* Method: init

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_com_guwei_volume_VolumeControl_init

(JNIEnv *, jobject);

/*

* Class: com_guwei_volume_VolumeControl

* Method: setMasterVolume

* Signature: (I)V

*/

JNIEXPORT void JNICALL Java_com_guwei_volume_VolumeControl_setMasterVolume

(JNIEnv *, jobject, jint);

/*

* Class: com_guwei_volume_VolumeControl

* Method: getMasterVolume

* Signature: ()I

*/

JNIEXPORT jint JNICALL Java_com_guwei_volume_VolumeControl_getMasterVolume

(JNIEnv *, jobject);

/*

* Class: com_guwei_volume_VolumeControl

* Method: setMute

* Signature: (Z)V

*/

JNIEXPORT void JNICALL Java_com_guwei_volume_VolumeControl_setMute

(JNIEnv *, jobject, jboolean);

/*

* Class: com_guwei_volume_VolumeControl

* Method: getMute

* Signature: ()Z

*/

JNIEXPORT jboolean JNICALL Java_com_guwei_volume_VolumeControl_getMute

(JNIEnv *, jobject);

/*

* Class: com_guwei_volume_VolumeControl

* Method: finished

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_com_guwei_volume_VolumeControl_finished

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

二.查询MSDN中调节wen7系统音量的方法

该网址提供一个样例VC++的win32工程显示调节系统音量,

将网页文档读懂即可编写自己的dll,其中用到了COM组件相关知识

67bae5d26735eb5396cdd0379794a126.png

该工程运行效果如下:

180d64097e59c4170834af9b5c297beb.png

三.编写dll文件(用到了COM相关)

使用VS2010建立名为VolumeControlDLL的win32控制台工程

4248789fc3700fb47030c1d0208ec511.png

cea71f1cee908fd33e0cc96c49dba776.png

点下一步后 选择dll 和空项目

8fac658eea3f9decf540f9a8a88656a8.png

将jni.h和之前生成的com_guwei_volume_VolumeControl.h加入工程

jni.h在jdk目录的include目录下:

可以在VS的环境变量中加入该目录

此处我用的是直接把文件拷到当前工程,所以相应com_guwei_volume_VolumeControl.h文件中的 include 改为 include "jni.h"

注意头文件中的extern C 是必要的,否则会报找不到的错,这是因为CPP支持函数重载,会将函数名XX映射

另外,jdk1.7只需jni.h文件,jdk1.8还需要jni_md.h文件(include/win32目录下)根据编译信息来即可

b3fb53c03a2a2d0b23e8e550492f83f1.png

Epvolume.cpp文件实现com_guwei_volume_VolumeControl.h的方法(根据MSDN工程中的改写)

// Epvolume.cpp -- WinMain and dialog box functions

#include"Epvolume.h"

#include"com_guwei_volume_VolumeControl.h"

GUIDg_guidMyContext = GUID_NULL;

staticIAudioEndpointVolume*g_pEndptVol = NULL;

IMMDeviceEnumerator*pEnumerator = NULL;

IMMDevice*pDevice = NULL;

JNIEXPORTvoidJNICALLJava_com_guwei_volume_VolumeControl_init(JNIEnv*env,

jobjectobj)

{

jclasscls;

cls = env->FindClass("com/guwei/volume/OperationFailedException");

if(cls == NULL){

return;

}

HRESULThr = S_OK;

//CAudioEndpointVolumeCallback EPVolEvents;

//得到g_guidMyContext hr只是结果

hr = CoCreateGuid(&g_guidMyContext);

if(FAILED(hr)) {

env->ThrowNew(cls, "CoCreateGuid error");

}

// Get enumerator for audio endpoint devices. pEnumerator中

hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),

NULL, CLSCTX_INPROC_SERVER,

__uuidof(IMMDeviceEnumerator),

(void**)&pEnumerator);

if(FAILED(hr)) {

env->ThrowNew(cls, "CoCreateInstance error");

}

// Get default audio-rendering device. pDevice中

hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);

if(FAILED(hr)) {

env->ThrowNew(cls, "pEnumerator->GetDefaultAudioEndpoint error");

}

hr = pDevice->Activate(__uuidof(IAudioEndpointVolume),

CLSCTX_ALL, NULL, (void**)&g_pEndptVol);

if(FAILED(hr)) {

env->ThrowNew(cls, "pDevice->Activate error");

}

}

JNIEXPORTvoidJNICALLJava_com_guwei_volume_VolumeControl_setMasterVolume(JNIEnv*env,

jobjectobj,

jintnVolume)

{

jclasscls;

cls = env->FindClass("com/guwei/volume/OperationFailedException");

if(cls == NULL){

return;

}

floatfVolume = (float)nVolume/ MAX_VOL;//设置音量

HRESULThr = g_pEndptVol->SetMasterVolumeLevelScalar(fVolume, &g_guidMyContext);

if(FAILED(hr)) {

env->ThrowNew(cls, "setMasterVolume error");

}

}

JNIEXPORTjintJNICALLJava_com_guwei_volume_VolumeControl_getMasterVolume(JNIEnv*env,

jobjectobj)

{

jclasscls;

cls = env->FindClass("com/guwei/volume/OperationFailedException");

if(cls == NULL){

return-1;

}

intret;

floatfVolume;

HRESULThr = g_pEndptVol->GetMasterVolumeLevelScalar(&fVolume);//得到主音量的大小浮点数(0.0~1.0)

if(FAILED(hr)) {

env->ThrowNew(cls, "getMasterVolume error");

}

ret = (int)(MAX_VOL*fVolume + 0.5);//将音量转化为整数(0到100) MAX_VOL为100

returnret;

}

JNIEXPORTvoidJNICALLJava_com_guwei_volume_VolumeControl_setMute(JNIEnv*env,

jobjectobj,

jbooleanbMute)

{

jclasscls;

cls = env->FindClass("com/guwei/volume/OperationFailedException");

if(cls == NULL){

return;

}

HRESULThr = g_pEndptVol->SetMute(bMute, &g_guidMyContext);//设置静音

if(FAILED(hr)) {

env->ThrowNew(cls, "setMute error");

}

}

JNIEXPORTjbooleanJNICALLJava_com_guwei_volume_VolumeControl_getMute(JNIEnv*env,

jobjectobj)

{

jclasscls;

cls = env->FindClass("com/guwei/volume/OperationFailedException");

if(cls == NULL){

returnfalse;

}

BOOLbMute;//是否静音

HRESULThr = g_pEndptVol->GetMute(&bMute);//得到静音状态

if(FAILED(hr)) {

env->ThrowNew(cls, "getMute error");

}

returnbMute;

}

JNIEXPORTvoidJNICALLJava_com_guwei_volume_VolumeControl_finished(JNIEnv*env,

jobjectobj)

{

//释放指针

SAFE_RELEASE(pEnumerator)

SAFE_RELEASE(pDevice)

SAFE_RELEASE(g_pEndptVol)

}

配置dll

注意32位和64位系统问题,

错误:Can't load IA 32-bit .dll on a AMD 64-bit platform

由于VS生成32位的,但系统使用64位

ba6fc6c0a0ad845a86b6c2b959b90dca.png

然后多了x64文件夹

7b9320c63b4854684470316cafe6e24f.png

VC项目生成的dll在工程目录的debug(32位) 或 x64/debug(64位)目录里

6aefe9889149d231952843170bb445d1.png

将该dll加入java工程的类路径(System.getProperty("java.library.path");只要在这里面都行)即可(可以设定参数-Djava.library.path=)

编写测试类Test.java

import com.guwei.volume.*;

import java.lang.Integer;

public class Test{

public static void main(String[] args)

{

VolumeControl vc = null;

try{

vc = VolumeControl.getInstance();

int val = vc.getMasterVolume();

boolean mute = vc.getMute();

System.out.println("current volume is"+val+". Is Muted?:"+mute);

}catch (OperationFailedException e)

{

System.out.println("can not read volume info: Exception:"+e);

return ;

}

if (args.length>1)

{

String s1=args[0];

String s2=args[1];

if (s1.equals("setmute"))

{

if (s2.equals("on"))

{

try{

vc.setMute(true);

System.out.println("Operation succeed!!!");

}catch (OperationFailedException e)

{

System.out.println("operation failed: Exception:"+e);

return ;

}

}

else if (s2.equals("off"))

{

try{

vc.setMute(false);

System.out.println("Operation succeed!!!");

}catch (OperationFailedException e)

{

System.out.println("operation failed: Exception:"+e);

return ;

}

}

}else if (s1.equals("setvolume"))

{

int value = -1;

try {

value = Integer.parseInt(s2);

}catch(NumberFormatException e)

{

System.out.println("operation failed: Exception:"+e);

return ;

}

if (value>=0 && value<=100)

{

try{

vc.setMasterVolume(value);

System.out.println("Operation succeed!!!");

}catch (OperationFailedException e)

{

System.out.println("operation failed: Exception:"+e);

return ;

}

}

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值