UI Automatorで自動試験を実施するとき、画面を録画したいことがあるかと思います(多分お客様へのエビデンスとしてなど)。
Android 4.4(Kitkat)から標準で搭載されている"screenrecord"をUI Automatorで実行させるときの注意点について記載します。

試した条件は以下のようになります。
Android 7.1.2
Nexus 6P

UI Automatorにコマンドを実行するためのAPIとしてUiDevice.executeShellCommand(publicメソッドですが、よくよく見たらhideされていて一般公開されていませんでした)が用意されていますが、このメソッドをそのまま使用すると以下のような問題が発生しました。

実装概要発生する問題点
1 テストスレッドでそのままコール
device.executeShellCommand("screenrecord [動画の保存先パス]")
メソッドが最大180秒間ブロックされる。
結局撮りたい動画が撮れない
2 テストスレッドでバックグラウンド実行としてコール
device.executeShellCommand("screenrecord [動画の保存先パス] &")
コールしても実際にはscreenrecordが動作しなかった
3 ワークスレッドでそのままコール
device.executeShellCommand("screenrecord [動画の保存先パス]")
180秒経過する前の任意のタイミングで画面録画を停止することができない

結論としては上記の3の方式+αで対応してみました。(苦肉の策・・・)
やっていることは、以下のようになります。
  1. ワークスレッドでscreenrecordを実行。保存するファイルパスは一時ファイル名称として保存
  2. screenrecordが終わった段階でUiDevice.executeShellCommandから戻ってくるので、そのタイミングで一時ファイル名称を正式なファイル名称に変更
  3. 途中で中断するときは、一時ファイルを正式なファイル名称にコピー。screenrecordのプロセスはそのままにしておいた上で、一時ファイルを削除
    ※ screenrecordプロセスを権限の関係で、killできないので、そのままにしておくしかできなかったです。とは言え、最大でも180秒でプロセスは終了するので、それほど大きな影響はないかと。

画面録画開始:
new Thread(new Runnable(){
    public void run(){
        try{
            device.executeShellCommand("screenrecord [一時的な動画の保存先パス]");
        }catch(Exception e){
        }finally{
            try{
                device.executeShellCommand("mv [一時的な動画の保存先パス] [正式な動画の保存先パス]");
            }catch(Exception e){
            }
        }
    }
}).start();

任意のタイミングでの画面録画終了:
        try{
            // リネームするとリネーム先のファイルにscreenrecordが出力し続けたので、別ファイル化と削除に分割しています
            device.executeShellCommand("cp [一時的な動画の保存先パス] [正式な動画の保存先パス]");
            device.executeShellCommand("rm [一時的な動画の保存先パス]");
        }catch(Exception e){
        }

UiDevice.executeShellCommandは実行時の権限確認に縛られないようなので、便利でした。

コメントの投稿