26

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

4

6 に答える 6

31

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*/);
}

これは最終的なコードではありませんが、開始のための良いベースです:)

于 2015-06-23T14:11:26.857 に答える
17

編集:この答えは、ダンペからの以下の答えに取って代わられます。

アプリ内からプログラムでビデオを録画するには、rootアクセスが必要です。Playストアでこれを行うために利用できるアプリは、アプリの説明に「REQUIRESROOT」を目立つようにリストしていることに気付くでしょう。また、このアプローチが機能するための特定のハードウェア要件がある場合もあります(「GalaxyNexusまたはTegra2/3では機能しません...」- ScreencastVideoRecorderアプリの説明から。

私はこのコードを自分で書いたことがありませんが、必要なアプローチの非常に高いレベルのアイデアをまとめました。この投稿から、「/ dev / graphics/fb0」を介してフレームバッファデータにアクセスする必要があるようです。フレームバッファのアクセスモードは660です。これは、フレームバッファにアクセスするにはrootアクセスが必要であることを意味します。ルートアクセスを取得したら、フレームバッファデータを使用してスクリーンショットを作成し(このプロジェクトはこのタスクで機能する可能性があります)、これらのスクリーンショットからビデオを作成できます(画像シーケンスからビデオを作成する方法については、この他のSOの質問を参照してください)。

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

于 2013-02-02T19:05:49.023 に答える
11

通常の Android アプリには、フレーム バッファーをキャプチャする権限がありません (具体的には、AID_GRAPHICS グループのメンバーではありません)。これはセキュリティ上の理由によるものです。そうしないと、ソフト キーボードからパスワードなどを盗み見られる可能性があります。したがって、一般に、特権の問題を回避する方法がなければ、Android アプリから画面をキャプチャすることはできません。

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

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

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

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

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

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

  • ADB ツール (例: Android 4.4 の組み込みスクリーンレコーダー)。USB経由で接続する必要があり、オーディオをキャプチャできません。

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

于 2014-04-10T09:57:28.907 に答える
2

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/

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

于 2013-02-01T17:53:46.460 に答える