Unity/Csharp/音/サイレントモードでも音を出す
ナビゲーションに移動
検索に移動
UntyのAndroid側のProjectSetting設定
- CustomMainManifestにチェックして、Assets/Plugins/Android/AndroidManifest.xml を作成
- CustomMainGradleTemplateにチェックして、Assets/Plugins/Android/mainTemplate.gradle を作成
- CustomGradlePropertiesTemplateにチェックして、Assets/Plugins/Android/gradleTemplate.properties を作成
- minimum api levelをandroid12以上に
Android実機設定
pixel3例
- Android実機で、サイレントモードを長押しして、サイレントモード設定を開く
- アラームとその他の割り込み/メディアサウンドをONにすると、消音モードでも、音がなるようになる。
注意
以下コードについて
ToggleMuteBypass(bool enable);
消音モードで、音をOFFにしたいときにfalseへ、消音モードで、音をONにしたいときはtrueへ。 起動時に、通常通り消音モードで、音をOFFにしたいときは、そのまま実行しないほうが安全。 alseで実行すると、端末によっては消音モードで音がONになる可能性がある。
実装
com.yourdomain.project1は、適宜、自分のpackage_nameに変更する。
Assets/Plugins/Android/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.VIBRATE" />
<application>
<!--Used when Application Entry is set to Activity, otherwise remove this activity block-->
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:theme="@style/UnityThemeSelector">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<!--Used when Application Entry is set to GameActivity, otherwise remove this activity block-->
<activity android:name="com.unity3d.player.UnityPlayerGameActivity"
android:theme="@style/BaseUnityGameActivityTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="android.app.lib_name" android:value="game" />
</activity>
</application>
</manifest>
Assets/Plugins/Android/AudioPlugin.java
package com.yourdomain.project1;
import android.content.Context;
import android.media.AudioManager;
import android.util.Log;
public class AudioPlugin {
private static final String TAG = "AudioPlugin";
public static void setMuteBypass(boolean enable, Context context) {
try {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
// STREAM_MUSICの音量で制御
int streamType = AudioManager.STREAM_MUSIC;
int maxVolume = audioManager.getStreamMaxVolume(streamType);
if (enable) {
// 消音モード無効(最大音量に設定)
audioManager.setStreamVolume(
streamType,
maxVolume,
AudioManager.FLAG_SHOW_UI
);
Log.d(TAG, "Mute bypass enabled - Volume set to max");
} else {
// 消音モード有効(音量0に設定)
audioManager.setStreamVolume(
streamType,
0,
AudioManager.FLAG_SHOW_UI
);
Log.d(TAG, "Mute bypass disabled - Volume muted");
}
} catch (Exception e) {
Log.e(TAG, "Error controlling audio: " + e.getMessage());
}
}
}
Assets/Plugins/Android/mainTemplate.gradle
apply plugin: 'com.android.library'
apply from: '../shared/keepUnitySymbols.gradle'
**APPLY_PLUGINS**
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
**DEPS**}
android {
namespace "com.unity3d.player"
ndkPath "**NDKPATH**"
ndkVersion "**NDKVERSION**"
compileSdk **APIVERSION**
buildToolsVersion = "**BUILDTOOLS**"
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
defaultConfig {
manifestPlaceholders = [unityPlayerActivity: "com.unity3d.player.UnityPlayerActivity"]
minSdk **MINSDK**
targetSdk **TARGETSDK**
ndk {
abiFilters **ABIFILTERS**
debugSymbolLevel **DEBUGSYMBOLLEVEL**
}
versionCode **VERSIONCODE**
versionName '**VERSIONNAME**'
consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
**DEFAULT_CONFIG_SETUP**
}
lint {
abortOnError false
}
androidResources {
noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
}**PACKAGING**
}
**IL_CPP_BUILD_SETUP**
**SOURCE_BUILD_SETUP**
**EXTERNAL_SOURCES**
Assets/Plugins/Android/gradle-wrapper.properties
org.gradle.jvmargs=-Xmx4096m android.useAndroidX=true android.enableJetifier=true
Assets/Plugins/Android/gradleTemplate.properties
org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M org.gradle.parallel=true unityStreamingAssets=**STREAMING_ASSETS** **ADDITIONAL_PROPERTIES**
Assets/Plugins/iOS/AudioPlugin.mm
#import <AVFoundation/AVFoundation.h>
extern "C" {
void ConfigureAudioSession(bool ignoreMute) {
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error = nil;
[session setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionMixWithOthers
error:&error];
if (ignoreMute) {
// 消音モードを無視する設定
[session setMode:AVAudioSessionModeDefault error:&error];
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];
NSLog(@"消音モード無視 ON");
} else {
// デフォルト設定に戻す
[session setMode:AVAudioSessionModeDefault error:&error];
NSLog(@"消音モード無視 OFF");
}
[session setActive:YES error:&error];
}
}
Assets/Scripts/AudioMannerManager.cs
using UnityEngine;
using System.Runtime.InteropServices;
public class AudioMannerManager : MonoBehaviour
{
public static AudioMannerManager Instance { get; private set; }
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
#if UNITY_IOS
[DllImport("__Internal")]
private static extern void ConfigureAudioSession(bool ignoreMute);
#endif
// 消音モードで、音をOFFにしたいときにfalseへ、消音モードで、音をONにしたいときはtrueへ
// 起動時に、通常通り消音モードで、音をOFFにしたいときは、そのまま実行しないほうが安全。
// falseで実行すると、端末によっては消音モードで音がONになる可能性がある。
public void ToggleMuteBypass(bool enable)
{
Debug.Log($"Attempting to {(enable ? "enable" : "disable")} mute bypass");
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidToggleMuteBypass(enable);
#elif UNITY_IOS && !UNITY_EDITOR
iOSToggleMuteBypass(enable);
#else
Debug.LogWarning("Mute bypass not supported on this platform");
#endif
}
#if UNITY_ANDROID
private void AndroidToggleMuteBypass(bool enable)
{
try
{
AndroidJavaClass pluginClass = new AndroidJavaClass("com.yourdomain.project1.AudioPlugin");
AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer")
.GetStatic<AndroidJavaObject>("currentActivity");
pluginClass.CallStatic("setAudioMode", enable, activity);
Debug.Log($"Android mute bypass set to: {enable}");
}
catch (System.Exception e)
{
Debug.LogError($"Android audio mode change failed: {e.Message}");
}
}
#endif
#if UNITY_IOS
private void iOSToggleMuteBypass(bool enable)
{
try
{
ConfigureAudioSession(enable);
Debug.Log($"iOS mute bypass set to: {enable}");
}
catch (System.Exception e)
{
Debug.LogError($"iOS audio session config failed: {e.Message}");
}
}
#endif
}
AudioPlayTest.cs
using UnityEngine;
using UnityEngine.UI;
public class AudioPlayTest : MonoBehaviour
{
[SerializeField] Button playButton;
// テスト用のメソッド
void Start()
{
playButton.onClick.AddListener(OnClickButton);
}
void OnClickButton()
{
GetComponent<AudioSource>().Play();
Handheld.Vibrate(); // バイブレーションテスト
}
}
Assets/Scripts/ToggleButtonController.cs
using UnityEngine;
using UnityEngine.UI;
public class ToggleButtonController : MonoBehaviour
{
[SerializeField] private Toggle toggle;
[SerializeField] private Text statusText;
private void Start()
{
toggle.onValueChanged.AddListener(OnToggleChanged);
UpdateStatusText(false); // 初期状態表示
}
private void OnToggleChanged(bool isOn)
{
AudioMannerManager.Instance.ToggleMuteBypass(isOn);
UpdateStatusText(isOn);
Handheld.Vibrate(); // バイブレーション
}
private void UpdateStatusText(bool isOn)
{
statusText.text = $"Mute Bypass: {(isOn ? "ON" : "OFF")}";
}
}
適宜コンポーネントを作って、ScriptsをAddComponentして、SerializeFieldの部分にコンポーネントをドラッグする。
Androidで、Dexエラーが出たら、Libraryを消してUnity再起動したら直った。
Xcodeでも、ビルド途中で止まるエラーが出たら、Libraryを消してUnity再起動したら直った。