Skip to main content

xue_hua_navite_volume_controller 1.0.0 copy "xue_hua_navite_volume_controller: ^1.0.0" to clipboard
xue_hua_navite_volume_controller: ^1.0.0 copied to clipboard

Cross-platform Flutter volume plugin for Android, iOS, macOS, Windows, Linux, and Web, with multi-stream control, mute, ringer mode, hardware keys, and device routing.

xue_hua_navite_volume_controller #

English | 简体中文

A production-grade, 6-platform system and application audio volume controller plugin for Flutter (Android, iOS, macOS, Windows, Linux, and Web).

Features #

  • Unified Normalized Volume Control (0.0–1.0): Read (getVolume), write (setVolume), adjust by relative delta (adjustVolume), or step up/down (stepVolume, volumeUp, volumeDown) with rich state snapshots (VolumeState).
  • Android 8-Stream Audio Mixer: Independently read and control media, ring, alarm, notification, voiceCall, system, accessibility, and dtmf streams via AudioManager.
  • Mute & Unmute with Smart Fallback: Hardware mute control (isMuted, setMute, toggleMute) with automatic software zero-volume fallback and pre-mute level restoration on iOS or external HDMI/DisplayPort monitors that lack a hardware mute register.
  • Real-Time OS Volume & Route Event Stream: Subscribe to onVolumeChanged or bind directly to stateNotifier (ValueNotifier<VolumeState>) to react immediately to physical volume buttons, Control Center sliders, Bluetooth headset buttons, or audio device hot-plugging.
  • Native System Volume HUD Control: Show or suppress the OS volume overlay (setShowSystemUI) on Android (AudioManager.FLAG_SHOW_UI) and iOS (MPVolumeView).
  • Physical Hardware Volume Button Interception: Capture physical Volume Up, Volume Down, and Volume Mute key presses on Android (setInterceptHardwareButtons, onHardwareButton) without modifying the system volume—ideal for camera shutters, page turners, or custom in-app media players.
  • Ringer Mode & Do Not Disturb (DND) Management: Query and switch Android ringer modes (RingerMode.normal, vibrate, silent) with built-in Notification Policy permission checking (hasDoNotDisturbAccess) and settings navigation (requestDoNotDisturbAccess).
  • Audio Output Device Enumeration & Switching: List connected audio output endpoints (getOutputDevices, getCurrentOutputDevice) and switch the default system output device (setOutputDevice) on macOS (CoreAudio), Windows (IPolicyConfig), Linux (pactl), Android 12+ (setCommunicationDevice), and Web (setSinkId).
  • Per-Application Volume & WebAudio Gain Boost: Control process-local volume on Windows (ISimpleAudioVolume) and Web (getAppVolume, setAppVolume), plus amplify quiet HTML5 <audio>/<video> elements up to 400% (setWebGainBoost(0.0..4.0)) via the Web Audio API GainNode.
  • Bundled AI Agent Skill: Ships with a standardized Dart package skill (skills/xue_hua_navite_volume_controller-usage/SKILL.md) following Ship skills with packages.

Platform Architecture & Differences #

Capability Android (API 24+) iOS (15.0+) macOS (12.0+) Windows (10/11) Linux (GTK3) Web (WASM / JS)
Native Audio Backend AudioManager + Window.Callback AVAudioSession + MPVolumeView CoreAudio (AudioObjectProperty) MMDeviceAPI + IAudioEndpointVolume PulseAudio (pactl) / PipeWire (wpctl) / ALSA (amixer) HTMLMediaElement + WebAudio GainNode
System Master Volume Yes Yes (physical device) Yes Yes (+ dB reading) Yes Sandboxed (controls DOM <audio>/<video>)
Multi-Stream Support 8 independent streams Unified output Unified output Unified output Unified output Unified DOM media
Mute Control ADJUST_MUTE / ADJUST_UNMUTE Software 0.0 + restore kAudioDevicePropertyMute + fallback IAudioEndpointVolume::SetMute Sink mute (pactl/wpctl/amixer) .muted property + restore
System Volume HUD Toggle Yes (FLAG_SHOW_UI) Yes (offscreen MPVolumeView) Managed by macOS Managed by Windows Managed by DE N/A
Hardware Key Interception Yes (KEYCODE_VOLUME_*) No (restricted by iOS) No No No No
Ringer Mode & DND normal, vibrate, silent Maps to mute state Maps to mute state Maps to mute state Maps to mute state Maps to mute state
Audio Device Listing getDevices(GET_DEVICES_OUTPUTS) currentRoute.outputs kAudioHardwarePropertyDevices EnumAudioEndpoints Default sink query mediaDevices.enumerateDevices()
Output Device Switching Android 12+ comm device System route picker only kAudioHardwarePropertyDefaultOutputDevice IPolicyConfig::SetDefaultEndpoint pactl set-default-sink HTMLMediaElement.setSinkId
Per-App Volume / Gain Media stream Media stream Master stream ISimpleAudioVolume (per-process) Master sink DOM volume + GainNode (0.0–4.0)

Installation & Native Setup #

Add xue_hua_navite_volume_controller to your pubspec.yaml:

dependencies:
  xue_hua_navite_volume_controller: ^1.0.0

Android Setup #

The plugin automatically merges the following permissions in its AndroidManifest.xml:

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
  • MODIFY_AUDIO_SETTINGS is a normal permission granted automatically at install time.
  • ACCESS_NOTIFICATION_POLICY is required only if your app switches the device into or out of RingerMode.silent (Do Not Disturb) on Android 6.0+. Always check await controller.hasDoNotDisturbAccess() and call await controller.requestDoNotDisturbAccess() before setting RingerMode.silent.

iOS Setup #

  • Requires iOS 15.0 or later.
  • Programmatic volume changes use MPVolumeView's internal UISlider. Important: Apple's iOS Simulator does not emulate hardware MPVolumeView slider changes—always test programmatic volume changes and HUD hiding on a physical iPhone or iPad.

macOS Setup #

  • Requires macOS 12.0 or later.
  • Works out of the box inside or outside the macOS App Sandbox using CoreAudio and AudioToolbox.

Windows Setup #

  • Uses standard Windows CoreAudio COM interfaces (mmdeviceapi.h, endpointvolume.h, audiopolicy.h). No extra DLLs or runtime installers are required.

Linux Setup #

  • Compiles with standard flutter_linux and gtk+-3.0 headers without requiring extra -dev audio packages at build time.
  • At runtime, automatically detects and uses pactl (PulseAudio / PipeWire-Pulse), wpctl (PipeWire WirePlumber), or amixer (ALSA).

Quick Start & Usage #

1. Initialize and Bind Reactive UI #

import 'package:flutter/material.dart';
import 'package:xue_hua_navite_volume_controller/xue_hua_navite_volume_controller.dart';

final controller = XueHuaNaviteVolumeController.instance;

Future<void> setupVolumeController() async {
  final initialState = await controller.initialize(
    const VolumeControllerConfig(
      defaultStream: VolumeStreamType.media,
      showSystemUI: false,
      interceptHardwareButtons: false,
      listenToVolumeChanges: true,
    ),
  );
  debugPrint('Initial volume: ${initialState.percentage}% (muted: ${initialState.isMuted})');
}

Use ValueListenableBuilder<VolumeState> with controller.stateNotifier for zero-boilerplate reactive UI updates:

ValueListenableBuilder<VolumeState>(
  valueListenable: XueHuaNaviteVolumeController.instance.stateNotifier,
  builder: (context, state, _) {
    return Row(
      children: [
        IconButton(
          icon: Icon(state.isMuted ? Icons.volume_off : Icons.volume_up),
          onPressed: () => XueHuaNaviteVolumeController.instance.toggleMute(),
        ),
        Expanded(
          child: Slider(
            value: state.volume,
            onChanged: (val) => XueHuaNaviteVolumeController.instance.setVolume(val),
          ),
        ),
        Text('${state.percentage}%'),
      ],
    );
  },
)

2. Listen to Volume Change & Hardware Key Streams #

final volumeSub = controller.onVolumeChanged.listen((VolumeChangeEvent event) {
  debugPrint(
    'Stream ${event.streamType.wireName} changed to ${event.state.percentage}% '
    '(reason: ${event.reason}, device: ${event.state.outputDeviceName})',
  );
});

// Enable physical hardware volume button interception on Android:
await controller.setInterceptHardwareButtons(true);
final buttonSub = controller.onHardwareButton.listen((VolumeButtonEvent button) {
  if (button.action == VolumeKeyAction.keyDown) {
    debugPrint('Intercepted hardware key: ${button.direction.wireName}');
  }
});

3. Control Android Multi-Stream Volumes & Ringer Mode #

// Set individual Android stream volumes:
await controller.setVolume(0.8, stream: VolumeStreamType.media, showSystemUI: false);
await controller.setVolume(1.0, stream: VolumeStreamType.alarm, showSystemUI: false);
await controller.setVolume(0.4, stream: VolumeStreamType.notification, showSystemUI: false);

// Read all stream volumes at once:
final Map<VolumeStreamType, double> allVolumes = await controller.getAllStreamVolumes();

// Safely switch ringer mode:
if (await controller.hasDoNotDisturbAccess()) {
  await controller.setRingerMode(RingerMode.silent);
} else {
  await controller.requestDoNotDisturbAccess();
}

4. Enumerate & Switch Audio Output Devices #

final devices = await controller.getOutputDevices();
for (final dev in devices) {
  debugPrint('${dev.name} [${dev.route.wireName}] (default: ${dev.isDefault})');
}

// Switch to a specific output device on macOS, Windows, Linux, Android 12+, or Web:
if (devices.length > 1) {
  await controller.setOutputDevice(devices.last.id);
}

5. Per-Application Volume (Windows/Web) & WebAudio Gain Boost #

// Set process-local application volume on Windows (ISimpleAudioVolume) or Web:
await controller.setAppVolume(0.75);

// Apply 200% Web Audio API GainNode boost to HTML5 <audio>/<video> elements on Web:
await controller.setWebGainBoost(2.0);

Important Caveats & Best Practices #

  1. iOS Simulator vs Physical Device: iOS Simulator does not attach a hardware audio output slider to MPVolumeView. Always verify programmatic volume setting and HUD suppression on a real iOS device.
  2. External HDMI / DisplayPort Monitors on macOS: Many external HDMI/DisplayPort displays do not expose a writable hardware volume or mute register over CEC (AudioObjectIsPropertySettable returns false). The plugin automatically falls back to software zero-volume mute so setMute(true) still silences output reliably.
  3. Android Do Not Disturb (SecurityException): Android 6.0+ throws a SecurityException if an app attempts to enter or exit RingerMode.silent without Notification Policy access. The plugin surfaces this as a typed VolumeControllerException(code: 'DND_PERMISSION_REQUIRED') and provides hasDoNotDisturbAccess() / requestDoNotDisturbAccess().
  4. Cleaning Up Interception: If you enable setInterceptHardwareButtons(true) on a specific screen (such as a camera or reader page), call setInterceptHardwareButtons(false) in dispose() so normal system volume button behavior is restored when the user leaves that screen.

AI Agent Skills Support #

This package ships with an official AI Agent Skill under skills/xue_hua_navite_volume_controller-usage/SKILL.md in compliance with the Dart Package Skills specification. Consumers can install it into their project with:

dart run skills@ get
0
likes
160
points
--
downloads

Documentation

Documentation
API reference

Publisher

verified publisherjsontodart.cn

Cross-platform Flutter volume plugin for Android, iOS, macOS, Windows, Linux, and Web, with multi-stream control, mute, ringer mode, hardware keys, and device routing.

Repository (GitHub)
View/report issues

Topics

#volume #audio #sound #media #hardware-buttons

License

Apache-2.0 (license)

Dependencies

flutter, flutter_web_plugins, plugin_platform_interface, web

More

Packages that depend on xue_hua_navite_volume_controller

Packages that implement xue_hua_navite_volume_controller