20210112のUnityに関する記事は2件です。

【Unity】Android アプリでスクショや画面録画などを禁止する

背景

アプリによっては、セキュリティやコンテンツ的にスクショや画面録画を禁止したいときがあると思います。
そのとき Android の機能である WindowManager.LayoutParams.FLAG_SECURE を Activity の OnCreate() で呼ぶ必要があります。

しかし、Unity だとどうするのか分からなかったので調べてまとめた記事になります。

FLAG_SECURE を設定するとどうなるか

  • スクショを無効化
  • 画面録画(スクリーンレコーディング)をすると、録画した画面が真っ黒になる
  • タスク画面・タスク一覧で、アプリ画面を真っ白にできる

動作確認環境

  • Unity 2018.4.22f1

※ Unity2018.2以前のバージョンを使っている場合は、以下の手順とは異なるかと思いますので、ご注意ください。

手順

Unity + Android で実現するためには、

  1. UnityPlayerActivity を拡張して新しい Activity を定義する
  2. 新しい Activity が使用されるように AndroidManifest.xml を修正する
  3. 新しい Activity の OnCreate()FLAG_SECURE を設定する

という手順が必要です。

1. UnityPlayerActivity を拡張する

自分が作業中の Unityプロジェクトの Assets/Plugins/Android 配下に新しい Activity を作成します。
例として、 OverrideExample クラスを作成します。

ちなみに、 package name 以外のファイル内容は、Unity公式からそのままコピペしています。
UnityPlayerActivity Java コードの拡張 - Unity マニュアル
package name は、自分が設定した名前に置き換えてください。

OverrideExample.java
package com.DefaultCompany.ExtendUnityPlayerActivity;
import com.unity3d.player.UnityPlayerActivity;
import android.os.Bundle;
import android.util.Log;

public class OverrideExample extends UnityPlayerActivity {

  protected void onCreate(Bundle savedInstanceState) {

    // UnityPlayerActivity.onCreate() を呼び出す
    super.onCreate(savedInstanceState);

    // logcat にデバッグメッセージをプリントする
    Log.d("OverrideActivity", "onCreate called!");
  }

  public void onBackPressed()
  {
    // UnityPlayerActivity.onBackPressed() を呼び出す代わりに、Back ボタンイベントを無視する
    // super.onBackPressed();
  }
}

2. AndroidManifest.xml を修正する

Activity と同様に Assets/Plugins/AndroidAndroidManifest.xml を配置します。
android:name の部分は、1. で作成したクラス名に合わせてください。

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.company.product">
  <application android:icon="@drawable/app_icon" android:label="@string/app_name">
    <activity android:name=".OverrideExample"
             android:label="@string/app_name"
             android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
  </application>
</manifest>

この状態で、Androidビルドして問題なくアプリが使用できるか確認してください。
特に、 package name を間違えるとアプリがクラッシュしたりするので、注意してください。

3. FLAG_SECURE を設定する

onCreate()FLAG_SECURE を設定します。

OverrideExample.java
package com.DefaultCompany.ExtendUnityPlayerActivity;
import com.unity3d.player.UnityPlayerActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;

public class OverrideExample extends UnityPlayerActivity {

  protected void onCreate(Bundle savedInstanceState) {

    // UnityPlayerActivity.onCreate() を呼び出す
    super.onCreate(savedInstanceState);

    // logcat にデバッグメッセージをプリントする
    Log.d("OverrideActivity", "onCreate called!");

    //FLAG_SECUREの設定
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
  }

  public void onBackPressed()
  {
    // UnityPlayerActivity.onBackPressed() を呼び出す代わりに、Back ボタンイベントを無視する
    // super.onBackPressed();
  }
}

これで作業は完了です。
Androidビルドして、問題なければスクショや画面録画ができなくなっていると思います。

参考文献

UnityPlayerActivity Java コードの拡張 - Unity マニュアル
Androidアプリでキャプチャーをされたくないときにする方法

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityで対話型音声認識アプリを作れるフレームワークをつくった

macOS, Windows両方で動く、Unityで対話型の音声認識アプリがすぐに作れるフレームワークを作りました。

リポジトリへのリンク:https://github.com/HassoPlattnerInstituteHCI/SpeechIOForUnity
Unity Package: https://github.com/HassoPlattnerInstituteHCI/SpeechIOForUnity/releases/tag/v1.0

つかいかた

SpeechOut/SpeechInを宣言し、以下のように書くだけ。

SpeechOut speechOut = new SpeechOut();
SpeechIn  speechIn  = new SpeechIn(OnRecognized);

void Start(){
    Dialog();
}

async void Dialog(){
    await speechOut.Speak("Hello!");
    await speechIn.Listen(new string[] { "Hello", "Hi", "Hey" });
    await speechOut.Speak("How are you doing?");
    await speechIn.Listen(new string[] { "I'm fine", "Nah", "I'm Sick" });
    //...
}

なぜつくったか

macOS, Windowsを使う学生のために、Unityを扱う授業で音声認識を使った対話型アプリを作るためのフレームワークがあればいいなと思ったので作りました。
主に非同期処理のasync/awaitベースで、逐次処理をわかりやすく書けるように、また速度や”間”などのチューニングも簡単にできるようにしました。

授業ではmac, Windowsそれぞれを使う学生を同様に対応しないといけないのですが、Unityそのものは双方で動作する一方、ネイティブOSの機能を使おうとすると相互にコードを共有できない=他のチームやグループが作ったアプリを動作させられないことになるので、このようなコードを作りました。

授業のためとはいえ、一般的に使いやすいツールだと思います。

OSネイティブの音声認識・音声合成

macOS側

macOSネイティブのオフライン音声認識ツールとしては、NSSpeechRecognizerが、音声合成ツールとしては、コマンドラインツールとしてsayがあります。このうち、sayに関してはUnity上のSystem.Diagnostics.Processから呼び出すことで実行できます(この点、Argsをいじるだけで声質とか速度を変えられるのでサイコー)

一方のNSSpeechRecognizerはOSネイティブAPIとして提供されている機能なので、実行するためにはObjective-CもしくはSwiftで記述されたコードから実行する必要があります。

今回のフレームワークでは別途NSSpeechForUnityとして、NSSpeechRecognizerを呼び出すObjective-Cコードを書き、外部ライブラリとして.bundleファイルを書き出し、それをUnityのPluginとすることで実行しています。

Windows側

逆にWindows側ではUnityEngine.Windows.Speechなるモジュールがあり、音声認識に関してはUnityから直接実行できる一方、音声合成に関しては別途WindowsのネイティブAPI=SAPIを叩く必要がありました。コード内で別途WindowsVoiceProjectとして、Visual Studioから.dllをビルドできるプロジェクトを作り、その.dllをUnityのPluginにします。


以上2つのOSに関して独自にライブラリを書き出すことによって実現しましたが、Unity上で非同期の動作を実現させるため、それぞれの処理がきちんと終わったかどうかを常に監視するためのコードを書く必要があります。たとえばこのように、内部のStateを逐一変えて、Unity側から監視することで、UnityのAsync/Awaitが進行するように若干HardCodedな感じではありますが、リアルタイムアプリケーションのための非同期処理を実現しています。


応用

対話型アプリケーションのためとは言いましたが、VRアプリケーションなどのための目と手が離せない際のデバッグ(イベントが起こったときにどのフラグが立ったか喋って教えてくれる)や、視覚障害者向けアプリなど、様々な用途が考えられます。「デバッグのときになにか喋ってくれたら便利だな」とか、「アクセシビリティ機能の充実したアプリを作りたいな」などというときにはぜひ使ってみてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む