用JNI实现调节win7系统音量

前言

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

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

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

使用了异常处理机制

com.guwei,volume.VolumeControl.java文件

  1. package com.guwei.volume;
  2. /**
  3. * 该类设计为单例模式
  4. * 提供控制win7系统音量的方法
  5. * @author guwei
  6. *
  7. */
  8. public class VolumeControl {
  9.      static
  10.      {
  11.          System.out.println(System.getProperty("java.library.path"));
  12.      System.loadLibrary("VolumeControlDLL");
  13.      }
  14.         private static VolumeControl uniqueInstance = null;
  15.  
  16.         private VolumeControl() throws OperationFailedException
  17.         {            
  18.             init();
  19.         }            
  20.         /**
  21.          * 单例模式
  22.          * @return 唯一的VolumeControl 有可能为null
  23.          */
  24.         public static VolumeControl getInstance() {
  25.             if (uniqueInstance == null) {
  26.                 try {
  27.                     uniqueInstance = new VolumeControl();
  28.                 }catch (OperationFailedException e)
  29.                 {
  30.                     e.printStackTrace();
  31.                     return null;
  32.                 }
  33.             }
  34.             return uniqueInstance;
  35.         }             
  36.         /**
  37.          * cpp本地一些初始化
  38.          * @return
  39.          */
  40.         private native void init() throws OperationFailedException;
  41.         /**
  42.          * 设置音量大小0~100
  43.          * @param num
  44.          * @return 操作是否成功
  45.          */
  46.      public native void setMasterVolume(int num) throws OperationFailedException;
  47.      /**
  48.      *
  49.      * @return 当前音量大小1-100
  50.      */
  51.         public native int getMasterVolume() throws OperationFailedException;
  52.         /**
  53.          * 设置是否静音 true-是 false-否
  54.          * @param bMute
  55.          * @return
  56.          */
  57.         public native void setMute(boolean bMute) throws OperationFailedException;
  58.         /**
  59.          * 得到当前静音状态 true-是 false-否
  60.          * @return
  61.          */
  62.         public native boolean getMute() throws OperationFailedException;
  63.         /**
  64.          * cpp本地释放指针等操作
  65.          * @return
  66.          */
  67.         private native void finished();        
  68.         @Override
  69.         public void finalize()
  70.         {
  71.             finished();
  72.         }
  73. }

com.guwei,volume.OperationFailedException.java文件

  1. package com.guwei.volume;
  2. public class OperationFailedException extends Exception
  3. {
  4.     public OperationFailedException()
  5.     {}
  6.     public OperationFailedException(String message)
  7.     {
  8.         super(message);
  9.     }
  10. }

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

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

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

javah -jni com.guwei.volume.VolumeControl

也可以用-classpath指明类路径

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

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

生成的头文件内容如下:

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

#include <jni.h>

/* 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系统音量的方法

https://msdn.microsoft.com/zh-cn/library/windows/desktop/dd370839(v=vs.85).aspx

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

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

该工程运行效果如下:

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

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

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

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

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

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

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

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

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

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

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

#include
"Epvolume.h"

#include
"com_guwei_volume_VolumeControl.h"

GUID g_guidMyContext = GUID_NULL;

static
IAudioEndpointVolume *g_pEndptVol = NULL;

IMMDeviceEnumerator *pEnumerator = NULL;

IMMDevice *pDevice = NULL;

JNIEXPORT
void
JNICALL Java_com_guwei_volume_VolumeControl_init(JNIEnv *env,

jobject
obj)

{

jclass cls;

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

if (cls == NULL){

return;

}

HRESULT hr = 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");

}

}

JNIEXPORT
void
JNICALL Java_com_guwei_volume_VolumeControl_setMasterVolume(JNIEnv *env,

jobject
obj,

jint
nVolume)

{

jclass cls;

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

if (cls == NULL){

return;

}

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

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

if (FAILED(hr)) {

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

}

}

JNIEXPORT
jint
JNICALL Java_com_guwei_volume_VolumeControl_getMasterVolume(JNIEnv *env,

jobject
obj)

{

jclass cls;

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

if (cls == NULL){

return -1;

}

int ret;

float fVolume;

HRESULT hr = 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

return ret;

}

JNIEXPORT
void
JNICALL Java_com_guwei_volume_VolumeControl_setMute(JNIEnv *env,

jobject
obj,

jboolean
bMute)

{

jclass cls;

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

if (cls == NULL){

return;

}

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

if (FAILED(hr)) {

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

}

}

JNIEXPORT
jboolean
JNICALL Java_com_guwei_volume_VolumeControl_getMute(JNIEnv *env,

jobject
obj)

{

jclass cls;

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

if (cls == NULL){

return
false;

}

BOOL bMute;//是否静音

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

if (FAILED(hr)) {

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

}

return bMute;

}

JNIEXPORT
void
JNICALL Java_com_guwei_volume_VolumeControl_finished(JNIEnv *env,

jobject
obj)

{

//释放指针

SAFE_RELEASE(pEnumerator)

SAFE_RELEASE(pDevice)

SAFE_RELEASE(g_pEndptVol)

}

  1. 配置dll

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

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

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

    然后多了x64文件夹

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

    将该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 ;

    }

    }

    }

    }

    }

    }

时间: 2024-10-08 09:58:18

用JNI实现调节win7系统音量的相关文章

Win7系统中哪些服务可以关闭?

Win7系统中很多服务和进程其实大家在平时都用不上,这些服务和进程不仅占用了很大部分的资源,而且还会影响系统的运行速度和安全.我们可以关闭那些不常用的服务和进程来加快系统运行速度,但对于一般的用户来说可能不太清楚哪些是可关闭,哪些是不可关闭的,因此下面我们就来详解下Win7系统中可以关闭的服务. Win7系统查看服务的方法:点击开始--运行--输入services.msc--回车. 1.Application Management 该服务主要适用于大型企业环境下的集中管理,普通用户关了没什么影响

iOS编程修改系统音量

iOS的AVFoundation框架提供了基本的音视频播放工具,我们基本上可以靠其中提供的类完成绝大部分的音视频播放任务.但是在音频播放的输出音量的处理上,苹果的策略比较保守.尽管AVPlayer和AVPAudiolayerzhe这些类提供了音量调节功能,但这些音量控制属于App级别的控制.好处就是音量调节独立于系统音量,调节大小时不会影响系统音量.但有时候我们可能希望修改系统音量,以免在调节声音的时候,如果系统音量过小,App调节音量效果不明显.一般来说要调节系统音量会有以下方法: 请注意:修

xp/win7系统CMD命令大全

系统的CMD命令提示符,通过输入相应的命令来完成相应的操作,提高工作效率,下面是网络人为大家精心整理的xp/win7系统cmd命令大全. 注:有关cmd命令大全.cmd命令行.cmd命令提示符的详细信息,可进入CMD命令提示符尝试,运行CMD命令提示符的方式:在电脑"开始"菜单-->选择"运行"-->输入"CMD",点击确定或按下回车键,然后在CMD主面板输入HELP命令名回车即可. XP/WIN7.CMD命令大全: cleanmgr

QQ远程协助不能控制win7系统的解决方法

经常碰到一个人说,用QQ远程WIN7等操作系统电脑时,总是点了没有反应,不知道是怎么一回事?其实,这主要是WIN7操作系统在安全管理性方面提高了,要进行设置一下,才可以 当对方使用win7系统的时候,为什么有些时候QQ远程协助控制不了win7的电脑,经常遇到这样的情况,远程连接上了,有些项可以点,有些项点一下就卡死了,点不动了,必须我们经常要用到磁盘管理,当我们点到这个项目的时候对方的电脑画面就卡住了再点鼠标也没有任何反应,这是怎么回事? 经过一番研究,我们发现在控制面板用户帐户里面有一个项目需

浅谈换回Win7系统的 及安装方法

目前很多笔记本新出厂的时候自带的都是Win8系统,但是大多数用户在使用电脑过程中,总觉得很不习惯,毕竟一直都是在用Win7系统,现在一下子换了一个系统,自然不习惯了.Windows 8可以在大部分运行Windows 7的电脑上平稳运行.Windows 8支持个人电脑(X64构架,X86构架)及平板电脑(ARM架构 ).但很多朋友还是比较喜欢win7. 若您确定要将您笔记本预装的Windows 8系统改装为Windows 7系统,安全管家提示你需要注意重要事项: 1.由于您笔记本预装的Window

在预装win8的电脑上换win7系统讲解

现在买电脑,如果电脑预装的系统是win8系统,那么这个电脑的默认启动模式应该就是UEFI模式,现在UEFI模式正在逐渐取代传统模式.UEFI启动需要一个独立的分区,它将系统启动文件和操作系统本身隔离,可以更好的保护系统的启动,这个模式能加快开机速度等一些优点. 下面说说如何在预装win8系统的电脑上安装win7系统 之前有很多朋友遇到一个装系统的问题,就是明明系统装好了,为什么开机还是进入不了系统,提示说找不到系统文件. 有两个方法可以解决在预装win8换win7系统出现的这个问题. 方法一:将

创建应答文件之自定义部署Win7系统模版

在SCVMM和VDI中,可以通过创建Win7系统模版来批量部署,可以节省很多重复的操作.创建Windows系统模版,必须要经过Sysprep.exe这个工具来重新封装.我们新装一个Win7系统,使用Sysprep直接做成模版,那我们在这个Win7系统上所做的所有设置都会被还原,不能达到所有虚拟机保持同样个性化的设置.现在我们可以使用应答文件来保留模版机上所有设置,Sysprep之后仍然存在.本次实验我们使用Win7系统做示范,在这之前需要下载好适用于Win7的AIK工具和Win系统镜像. 下载链

U盘装win7系统

首先在互联网下载UltraISO光盘映像文件制作/编辑/格式转换工具,(当然还有其它如WinISO.WinImage.Daemon Tools等)然后在准备一个4GB容量以上(含4GB)的优盘或者移动硬盘,这里需要注意做启动盘的U盘或者移动硬盘必须是格式化后的,所以需要提前备份里面的数据,等制作好启动盘后再拷贝进去,也不影响日使用. 第一步,需要有Win7操作系统的ISO文件,可以在网上下载,然后再UltraISO中打开这个ISO文件. 制作可以安装Win7系统U盘步骤一 制作可以安装Win7系

Ubuntu安装教程--Win7系统中含100M保留分区

1.检查 Win7 保留分区 1)进入 Win7 打开库文件夹,在左侧栏找到"计算机",瞄准点右键选择"管理"菜单: 2)在出来的管理面板左边找到"磁盘管理",点击它,在右边出来各个分区: 注意:如果里面有一个100M的系统保留分区,则进行下面(3-6)的操作,否则请跳至第2步复制启动文件: 3)瞄准100M"系统保留"分区点右键,选择"更改驱动器号和路径"菜单: 4)在出来的面板中,点左下角的"