アヒルのある日

株式会社AHIRUの社員ブログです。毎週更新!社員が自由に思いついたことを書きます。

Unityで端末音量を操作するPluginを作成してみる!

こんにちは。
ちゃらいアヒルです。

現在作成しているプロジェクトの要件で以下2点の対応が必要になりました。

・端末の音量を取得する
・端末の音量を操作する

ムムム・・・とうとうPlugin作成に手を出す時がきたか!!
と言うことで、AndroidとiOSでそれぞれ以下のように対応しました!

Android

Androidはとてもシンプルです。

// ミュート音量かどうか調べる
public bool IsMuteVolume()
{
#if UNITY_ANDROID
    AndroidJavaClass    unityPlayer     = new AndroidJavaClass( "com.unity3d.player.UnityPlayer" );
    AndroidJavaObject   context         = unityPlayer.GetStatic<AndroidJavaObject>( "currentActivity" );
    AndroidJavaObject   audioManager    = context.Call<AndroidJavaObject>( "getSystemService", "audio" );
    return 0 >= audioManager.Call<int>( "getStreamVolume", 3 );
#endif
}

// 音量設定
public void SetVolume()
{
#if UNITY_ANDROID
    AndroidJavaClass    unityPlayer     = new AndroidJavaClass( "com.unity3d.player.UnityPlayer" );
    AndroidJavaObject   context         = unityPlayer.GetStatic<AndroidJavaObject>( "currentActivity" );
    AndroidJavaObject   audioManager    = context.Call<AndroidJavaObject>( "getSystemService", "audio" );

    // 今回は最大ボリュームの半分に設定する仕様
    int maxVolume = audioManager.Call<int>( "getStreamMaxVolume", 3 );
    audioManager.Call( "setStreamVolume", 3, maxVolume / 2, 0 );
#endif
}

iOS

iOSの場合は工程が多いです...

1. プロジェクトフォルダの「Assets/Plugins/iOS」フォルダ以下に「PluginDeviceAudio.mm」を作成する

 ※ファイル名は自由で構いません。
 ※今回はObjective-Cでコーディングを行いました。

 Androidで実装した「ミュート音量かどうか調べる/音量設定」関数を定義します。

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#import <AVFoundation/AVFoundation.h>

extern "C"
{
    BOOL _PluginDeviceAudio_IsMuteVolume();
    void _PluginDeviceAudio_SetVolume();
}

BOOL _PluginDeviceAudio_IsMuteVolume()
{
    float volume = AVAudioSession.sharedInstance.outputVolume;
    if( volume > 0.0 )
    {
        return NO;
    }

    return YES;
}

void _PluginDeviceAudio_SetVolume()
{
    MPVolumeView *volumeView = [[MPVolumeView alloc] init];
    UISlider *volumeSlider = nil;

    for( UIView *view in [volumeView subviews] )
    {
        if( [NSStringFromClass(view.class) isEqualToString:@"MPVolumeSlider"] )
        {
            volumeSlider = (UISlider *)view;
            break;
        }
    }

    dispatch_after( dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        volumeSlider.value = 0.5f;
    });
}

2. UnityからiOSビルドで出力されたXcodeプロジェクトに「MediaPlayer.framework」を追加するため「PostProcessBuild」ファイルを作成する

public static class PostProcessBuild
{
    [PostProcessBuild(99)]
    public static void OnPostProcessBuild( BuildTarget target, string path )
    {
#if UNITY_IOS
        if( target == BuildTarget.iOS )
        {
            _postProcessBuildIOS( path );
        }
#endif
    }

#if UNITY_IOS
    private static void _postProcessBuildIOS( string path )
    {
        string      projectPath = PBXProject.GetPBXProjectPath( path );
        PBXProject  pbxProject  = new PBXProject();

        pbxProject.ReadFromString( File.ReadAllText(projectPath) );
        string target = pbxProject.TargetGuidByName( "Unity-iPhone" );

        // framework追加
        pbxProject.AddFrameworkToProject( target, "MediaPlayer.framework", true );

        // 出力
        File.WriteAllText( projectPath, pbxProject.WriteToString() );
    }
#endif
}

3. 「PluginDeviceAudio.mm」ファイルに定義された関数を呼び出す

#if UNITY_IOS
    [DllImport("__Internal")]
    private static extern bool _PluginDeviceAudio_IsMuteVolume();
    [DllImport("__Internal")]
    private static extern void _PluginDeviceAudio_SetVolume();
#endif

// ミュート音量かどうか調べる
public bool IsMuteVolume()
{
#if UNITY_IOS
    return _PluginDeviceAudio_IsMuteVolume();
#endif
}

// 音量設定
public void SetVolume()
{
#if UNITY_IOS
    _PluginDeviceAudio_SetVolume();
#endif
}

まとめると上記のようになります。

あとは、アプリ側で
・IsMuteVolume
・SetVolume
を任意のタイミングで呼び出す流れとなります。

もう、Objective-C触りたくない・・・

また次回!