当前位置: 首页 > news >正文

使用Java调用Windows通知并显示自定义图标

使用Java调用Windows通知并显示自定义图标

一 实现原理,java调用shell脚本,实现弹出通知,其实是有两种shell脚本的方式,任何编程语言都可以调用shell的,底部附源码

在现代应用程序中,通知系统是一个非常重要的功能,它可以帮助用户及时了解应用程序的状态或重要信息。本文将详细介绍如何使用Java调用Windows通知,并在通知中显示自定义图标。我们将通过一个完整的代码示例来展示这一功能的实现。

代码功能概述

本文的代码实现了一个Java方法
showWindowsNotificationWithIconA,它可以在Windows系统上显示一个带有自定义图标的通知。通知的标题和内容可以通过参数传递,图标则从项目的资源文件中加载。如果图标无法直接从资源文件中加载,代码还会尝试将图标提取到临时文件中,并使用该临时文件的路径来显示图标。

此外,代码还包含一个辅助方法 executeShellScriptEx,用于执行PowerShell脚本。该方法会将脚本保存到临时文件中,然后通过 ProcessBuilder 启动PowerShell进程来执行脚本,并捕获脚本的输出。

代码实现逻辑

    1. 加载图标资源

首先,代码尝试从项目的资源文件中加载图标。图标文件位于 resources/static/A.ico 路径下。通过
GlobalKeyListener.class.getResource(“/static/A.ico”) 方法获取图标的URL。

URL iconUrl = GlobalKeyListener.class.getResource("/static/A.ico");
if (iconUrl == null) {
    System.err.println("无法加载图标资源!");
    return;
}

如果图标资源无法加载,代码会输出错误信息并返回。

    1. 处理图标路径
      获取到图标的URL后,代码将其转换为适合PowerShell脚本使用的字符串形式,并进行必要的转义。如果URL不包含 file 协议(即图标不是从文件系统中加载的),代码会调用 extractIconToTemp 方法将图标提取到临时文件中。
String file = iconUrl.toString().replace("\\", "/");
if(!file.contains("file")){
    try {
        file = extractIconToTemp();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
    1. 构建PowerShell脚本

接下来,代码构建一个PowerShell脚本来显示通知。脚本使用了Windows的Toast通知系统,并指定了带图标的模板
ToastImageAndText02。通知的标题、内容和图标路径通过格式化字符串插入到脚本中。

String script = String.format("""
    $ErrorActionPreference = 'Stop';
    Add-Type -AssemblyName System.Runtime.WindowsRuntime;
    [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null;
    $template = [Windows.UI.Notifications.ToastTemplateType]::ToastImageAndText02;  # 使用带图标的模板
    $toastContent = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent($template);
    $toastXml = [xml] $toastContent.GetXml();
    $toastXml.SelectSingleNode('//text[1]').InnerText = '%s';  # 标题
    $toastXml.SelectSingleNode('//text[2]').InnerText = '%s';  # 内容
    $toastXml.SelectSingleNode('//image').Attributes['src'].Value = '%s';  # 图标路径
    $toastNode = [Windows.Data.Xml.Dom.XmlDocument]::new();
    $toastNode.LoadXml($toastXml.OuterXml);
    $toast = [Windows.UI.Notifications.ToastNotification]::new($toastNode);
    $notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('柚柚通知');  # 应用名称
    $notifier.Show($toast);
    """,
    title.replace("'", "''"), message.replace("'", "''"), file);
    1. 执行PowerShell脚本

最后,代码通过 WindowsSystemUtil.executeShellScriptEx
方法执行构建好的PowerShell脚本,从而在Windows系统上显示通知。

WindowsSystemUtil.executeShellScriptEx(script);
5. 提取图标到临时文件
如果图标无法直接从资源文件中加载,代码会调用 extractIconToTemp 方法将图标提取到临时文件中。该方法首先通过 ClassLoader 加载图标资源,然后将其写入一个临时文件,并返回该临时文件的绝对路径。

public static String extractIconToTemp() throws IOException {
    InputStream inputStream = GlobalKeyListener.class.getClassLoader().getResourceAsStream("static/A.ico");
    if (inputStream == null) {
        throw new FileNotFoundException("图标文件未找到!");
    }

    try {
        File tempFile = File.createTempFile("appicon", ".ico");
        tempFile.deleteOnExit(); // 程序正常退出时删除临时文件

        try (OutputStream outputStream = new FileOutputStream(tempFile)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }

        return tempFile.getAbsolutePath();
    } finally {
        inputStream.close();
    }
}

完整代码

public static void showWindowsNotificationWithIconA(String title, String message)  {
    // 获取图标文件的URL。这里假设图标位于项目的resources/static/A.ico。
    URL iconUrl = GlobalKeyListener.class.getResource("/static/A.ico");
    if (iconUrl == null) {
        System.err.println("无法加载图标资源!");
        return;
    }

    // 将URL转换为适合PowerShell脚本使用的字符串形式,并进行必要的转义
    String file = iconUrl.toString().replace("\\", "/");
    if(!file.contains("file")){
        try {
            file = extractIconToTemp();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 构建PowerShell脚本
    String script = String.format("""
        $ErrorActionPreference = 'Stop';
        Add-Type -AssemblyName System.Runtime.WindowsRuntime;
        [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null;
        $template = [Windows.UI.Notifications.ToastTemplateType]::ToastImageAndText02;  # 使用带图标的模板
        $toastContent = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent($template);
        $toastXml = [xml] $toastContent.GetXml();
        $toastXml.SelectSingleNode('//text[1]').InnerText = '%s';  # 标题
        $toastXml.SelectSingleNode('//text[2]').InnerText = '%s';  # 内容
        $toastXml.SelectSingleNode('//image').Attributes['src'].Value = '%s';  # 图标路径
        $toastNode = [Windows.Data.Xml.Dom.XmlDocument]::new();
        $toastNode.LoadXml($toastXml.OuterXml);
        $toast = [Windows.UI.Notifications.ToastNotification]::new($toastNode);
        $notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('柚柚通知');  # 应用名称
        $notifier.Show($toast);
        """,
        title.replace("'", "''"), message.replace("'", "''"), file);

    // 打印构建好的脚本(可选)
    System.out.println(script);

    // 执行构建好的脚本
    WindowsSystemUtil.executeShellScriptEx(script);
}

public static String extractIconToTemp() throws IOException {
    // 使用ClassLoader加载资源
    InputStream inputStream = GlobalKeyListener.class.getClassLoader().getResourceAsStream("static/A.ico");

    if (inputStream == null) {
        throw new FileNotFoundException("图标文件未找到!");
    }

    try {
        // 创建临时文件
        File tempFile = File.createTempFile("appicon", ".ico");
        tempFile.deleteOnExit(); // 程序正常退出时删除临时文件

        // 将输入流的数据写入临时文件
        try (OutputStream outputStream = new FileOutputStream(tempFile)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }

        // 返回临时文件的绝对路径
        return tempFile.getAbsolutePath();
    } finally {
        inputStream.close();
    }
}

总结

通过本文的代码示例,我们展示了如何使用Java调用Windows通知并显示自定义图标。代码通过加载资源文件、处理图标路径、构建PowerShell脚本以及执行脚本等步骤,实现了这一功能。希望本文能帮助你更好地理解如何在Java应用程序中集成Windows通知功能。

相关文章:

  • 使用memmove优化插入排序
  • 【专项测试】限流测试
  • maven的安装配置
  • 【数据结构】线性表简介
  • 重要!!! 什么是梯度方差 ; AdaLoRA中的Fisher信息矩阵:核心作用与通俗举例
  • RUOYI框架在实际项目中的应用二:Ruoyi前后端分离版本
  • 【MySQL】(5) 数据行的增删改查操作
  • Hexo主题配置and常用指令
  • mysql-8.0.25-winx64安装步骤
  • 中考英语之02高频词汇
  • React 常用 Hooks 详细解析
  • 责任链模式
  • 【leetcode hot 100 230】二叉搜索树中第K小的元素
  • Web前端开发——CSS入门
  • 前端web worker提升性能实战案例
  • zk-SNARKs 最简单的应用示例:密码验证
  • RAG的Rerank:从期待到现实的转变
  • Mysql第二次练习
  • Swift 中 associatedtype 的用法详解
  • IntelliJ IDEA 2023.3.1安装指南从下载到配置的完整教程(附资源下载)
  • 做模具的都有什么网站/百度2022第三季度财报
  • 网站空间2G一年多少钱/网站域名服务器查询
  • 做网站很挣多少钱/广告代理商
  • 网站开发php制作/正规网络公司关键词排名优化
  • 机场建设管理投资有限责任公司网站/微信管理工具
  • 章贡区综合网站建设商家/免费网络推广渠道