web-dev-qa-db-ja.com

現在のアクティビティの画面ビデオ記録Android

同じアクティビティから現在実行中のアクティビティの画面ビデオを記録することは可能ですか?
現在のアクティビティのスクリーンショットを撮る方法は知っていますが、スクリーンのビデオ記録を撮る方法がわかりません。どうやって始めますか?開始方法がわかりません。

23
captaindroid

[〜#〜] edit [〜#〜]:この回答は、Danpeの回答 に置き換えられます。

アプリ内からプログラムでビデオを録画するには、rootアクセスが必要です。 Playストアでこれを実行できるアプリは、アプリの説明に「ルートが必要」と明記されていることに気付くでしょう。また、このアプローチが機能するための特定のハードウェア要件があるかもしれないことに気付くでしょう(「Galaxy NexusまたはTegra 2/3では動作しません...」 スクリーンキャストビデオレコーダーの説明から app。

このコードを自分で書いたことはありませんが、必要なアプローチの非常に高いレベルのアイデアをまとめました。これから post のように見えます。 "/ dev/graphics/fb0"を介してフレームバッファデータにアクセスする必要があります。フレームバッファのアクセスモードは660です。つまり、アクセスするにはルートアクセスが必要です。ルートアクセス権を取得したら、フレームバッファデータを使用してスクリーンショットを作成し(このタスクはこの project で動作する可能性があります)、これらのスクリーンショットからビデオを作成できます(他のSO方法に関する質問 画像シーケンスからビデオを作成 )。

Screencastアプリを使用しましたが、Samsung Noteでうまく機能します。これが彼らがとった基本的なアプローチだと思う。

15
mikejonesguy

Lollipop以降、Media Projection APIを使用できます! (API 21 +)

記録に使用する次のコードは次のとおりです。最初にそのためのユーザー権限を取得する必要があることに注意してください;)

private static final int CAST_PERMISSION_CODE = 22;
private DisplayMetrics mDisplayMetrics;
private MediaProjection mMediaProjection;
private VirtualDisplay mVirtualDisplay;
private MediaRecorder mMediaRecorder;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mMediaRecorder = new MediaRecorder();

    mProjectionManager = (MediaProjectionManager) getSystemService
            (Context.MEDIA_PROJECTION_SERVICE);

    getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);

    prepareRecording();
}

private void startRecording() {
    // If mMediaProjection is null that means we didn't get a context, lets ask the user
    if (mMediaProjection == null) {
        // This asks for user permissions to capture the screen
        startActivityForResult(mProjectionManager.createScreenCaptureIntent(), CAST_PERMISSION_CODE);
        return;
    }
    mVirtualDisplay = createVirtualDisplay();
    mMediaRecorder.start();
}

private void stopRecording() {
    if (mMediaRecorder != null) {
        mMediaRecorder.stop();
        mMediaRecorder.reset();
    }
    if (mVirtualDisplay != null) {
        mVirtualDisplay.release();
    }
    if (mMediaProjection != null) {
        mMediaProjection.stop();
    }
    prepareRecording();
}

public String getCurSysDate() {
    return new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date());
}

private void prepareRecording() {
    try {
        mMediaRecorder.prepare();
    } catch (Exception e) {
        e.printStackTrace();
        return;
    }

    final String directory = Environment.getExternalStorageDirectory() + File.separator + "Recordings";
    if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
        Toast.makeText(this, "Failed to get External Storage", Toast.LENGTH_SHORT).show();
        return;
    }
    final File folder = new File(directory);
    boolean success = true;
    if (!folder.exists()) {
        success = folder.mkdir();
    }
    String filePath;
    if (success) {
        String videoName = ("capture_" + getCurSysDate() + ".mp4");
        filePath = directory + File.separator + videoName;
    } else {
        Toast.makeText(this, "Failed to create Recordings directory", Toast.LENGTH_SHORT).show();
        return;
    }

    int width = mDisplayMetrics.widthPixels;
    int height = mDisplayMetrics.heightPixels;

    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    mMediaRecorder.setVideoEncodingBitRate(512 * 1000);
    mMediaRecorder.setVideoFrameRate(30);
    mMediaRecorder.setVideoSize(width, height);
    mMediaRecorder.setOutputFile(filePath);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode != CAST_PERMISSION_CODE) {
        // Where did we get this request from ? -_-
        Log.w(TAG, "Unknown request code: " + requestCode);
        return;
    }
    if (resultCode != RESULT_OK) {
        Toast.makeText(this, "Screen Cast Permission Denied :(", Toast.LENGTH_SHORT).show();
        return;
    }
    mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
    // TODO Register a callback that will listen onStop and release & prepare the recorder for next recording
    // mMediaProjection.registerCallback(callback, null);
    mVirtualDisplay = getVirtualDisplay();
    mMediaRecorder.start();
}

private VirtualDisplay getVirtualDisplay() {
    screenDensity = mDisplayMetrics.densityDpi;
    int width = mDisplayMetrics.widthPixels;
    int height = mDisplayMetrics.heightPixels;

    return mMediaProjection.createVirtualDisplay(this.getClass().getSimpleName(),
            width, height, screenDensity,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            mMediaRecorder.getSurface(), null /*Callbacks*/, null /*Handler*/);
}

これは最終的なコードではなく、開始するのに適したベースです:)

26
Danpe

通常Androidアプリはフレームバッファーをキャプチャする権限がありません(具体的には、AID_GRAPHICSグループのメンバーではありません)。これはセキュリティ上の理由によるものです。そのため、一般的に、権限の問題を回避する何らかの方法がないと、Androidアプリから画面をキャプチャできません。

ビュー階層の最上位のビューに移動し、View.draw(Canvas)を使用してビットマップに描画することにより、アプリケーションが現在使用している画面領域のスナップショットを多かれ少なかれキャプチャできますが、これは記録しませんステータスバー、ソフトキーボード、OpenGLサーフェスなど。

これよりもうまくしたい場合は、外部ツールを使用する必要があります。 ADBインターフェースを介して開始されたプロセスにはAID_GRAPHICS特権があるため、ツールにはルートまたはADBインターフェースを使用する必要があります。後者の方法を使用すると、非特権アプリは特権サーバーに接続して記録を行うことができます。

ツールは大まかに次のカテゴリに分類できます。

  • ルートのみのフレームバッファレコーダーアプリ(Screencastなど)。これらの記録は、/ dev/graphics/fb0デバイスから直接記録されますが、フレームバッファーが読み取り可能なデバイスでのみ機能します(たとえば、Tegra 2 Nexus 7では使用できません)。

  • ルート専用のスクリーンキャプチャレコーダーアプリ(SCR、Recなど)。これらは、SurfaceFlingerを介して画面をキャプチャし、はるかに幅広いデバイスで動作します。

  • 非ルートスクリーンキャプチャレコーダーアプリ(Recordable、Ascrecorderなど)。これらは、ユーザーがホストPC経由で接続しているときにUSBデバッグを有効にし、デーモンを起動することを必要とします。その後、デバイスが再起動されるまで、ホストPCは必要ありません。オーディオも録音できます。

  • ADBツール(例:Android 4.4)のビルトインスクリーンレコーダー。USB経由で接続する必要があり、音声をキャプチャできません。

数か月前、利用可能なアプリの比較を行いました。ここで利用できます:

http://recordable.mobi/compare

完全を期すために、USBを介して画面をストリーミングするUSB​​ツール(Mobizenなど)もあり(低USB帯域幅に制限され、オーディオを録音できません)、一部のデバイスはwifi経由で画面を送信し、別のデバイスでキャプチャできます。

11

これはかなり古い投稿ですが、これがAndroidデバイスの画面を記録する方法をまだ探している人に役立つことを願っています:

Android 5.0以降、画面の記録に使用できる新しいAPIがあります。 MediaProjection MediaProjectionは、画面コンテンツをキャプチャしますが、システムオーディオはキャプチャしません。また、安全な画面コンテンツをキャプチャしません。

Matt Sniderのページには、APIを使用して、画面をSDカード上のファイルに実際に記録する方法の良い例があります: [〜#〜] link [〜#〜]

4
Failster

adbが実行され、フレームバッファへのアクセス許可があるときに、DDMSを使用して画面をキャプチャできます。

詳細については、このリンクをたどってください。

http://thetechjournal.com/electronics/Android/how-to-capture-screenshots-and-record-video-on-Android-device.xhtml

また、このリンクをチェックして、必要なものについていくつかのアイデアを得ることができます。

http://answers.oreilly.com/topic/951-how-to-capture-video-of-the-screen-on-Android/

http://www.mightypocket.com/2010/09/installing-Android-screenshots-screen-capture-screen-cast-for-windows/

このプロジェクトを確認してください:

http://sourceforge.net/projects/ashot/

この助けを願っています。

2
Android Stack

これを処理する library を作成しました。カスタマイズ可能な通知の表示を含め、通知を表示したくない場合は無効にすることができます。

API 21が必要>


使用方法の簡単なデモを次に示します(詳細については、ライブラリのreadmeを参照してください)。

まず、Activityで宣言して初期化します。

public class MainActivity extends AppCompatActivity implements HBRecorderListener {
    //Declare HBRecorder
    HBRecorder hbRecorder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     

        //Init HBRecorder
        hbRecorder = new HBRecorder(this, this);        

}

その後、録音を開始したい場合は、次を呼び出すことができます。

private void startRecordingScreen() {
    MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    Intent permissionIntent = mediaProjectionManager != null ? mediaProjectionManager.createScreenCaptureIntent() : null;
    startActivityForResult(permissionIntent, SCREEN_RECORD_REQUEST_CODE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == SCREEN_RECORD_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            //It is important to call this before starting the recording
            hbRecorder.onActivityResult(resultCode, data, this);
            //Start screen recording
            hbRecorder.startScreenRecording(data);
        }
    }
}

次を呼び出して、記録を停止できます。

hbRecorder.stopScreenRecording();

onCompleteListenerは、ファイルがいつ作成されたかを知らせます。

@Override
public void HBRecorderOnComplete() {
    //This is called once the file was created
}

また、AudioBitrateAudioSamplingRateなどの変更など、設定可能なパラメーターの束を追加しました。

0
HB.