点按并按住即可像 Vine 一样录制视频

2024-04-01

我想做一个录制视频的应用程序,它看起来像藤蔓,按住录制,松开停止,按住录制并保持到最后。

我使用过 MediaRecorder,但它每次只录制一次,如果我再次开始录制,应用程序就会崩溃。

请告诉我有什么办法可以做到这一点吗? 我编辑了我的代码:

public class VideoRecordingActivity extends AppCompatActivity implements View.OnTouchListener, View.OnLongClickListener {
private Context myContext;
private boolean hasCamera;
private boolean onRecording;

private Camera mCamera;
private CameraPreview mPreview;
private MediaRecorder mediaRecorder;
private boolean cameraFront = false;
private int cameraId;

private int videoNumer;
private boolean isActionDown = false;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_video_introduction_recording);
    initUI();
    initialize();
}
private LinearLayout lnCameraPreview;
private ImageButton btn_recording;

private void initUI() {
    lnCameraPreview = (LinearLayout) findViewById(R.id.ln_body_recording);
    btn_recording = (ImageButton) findViewById(R.id.btn_recording);

}

public void initialize() {
    myContext = this;
    mPreview = new CameraPreview(this, cameraId, mCamera);
    lnCameraPreview.addView(mPreview);
    btn_recording.setOnLongClickListener(this);
    btn_recording.setOnTouchListener(this);
    videoNumer = 0;
}
public boolean onLongClick(View v) {
    isActionDown = true;
    try {
        boolean isPrepared = false;
        if (isActionDown)
            isPrepared = prepareMediaRecorder();
        if (isPrepared && isActionDown) {
            // work on UiThread for better performance
            runOnUiThread(new Runnable() {
                public void run() {
                    mediaRecorder.start();
                    onRecording = true;
                }
            });

        }
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("onLongPress Error ", e.toString());
    }

    return true;
}


@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
            isActionDown = false;

            try {
                if (onRecording) {

                    if (mediaRecorder != null) {
                        mediaRecorder.stop();
                    }
                    onRecording = false;
                    videoNumer++;
                }
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            break;
    }
    return false;
}



public void onResume() {
    super.onResume();
    if (!hasCamera(myContext)) {
        Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG).show();
        return;
    }
    initCamera();
}

@Override
protected void onPause() {
    super.onPause();
    // when on Pause, release camera in order to be used from other
    // applications
    releaseCamera();
}


private final int cMaxRecordDurationInMs = 30000;
private final long cMaxFileSizeInBytes = 5000000;
private final int cFrameRate = 20;
private File prRecordedFile;

@SuppressLint("SdCardPath")
private boolean prepareMediaRecorder() {
    mediaRecorder = new MediaRecorder();

    try {
        mCamera.unlock();
    } catch (Exception ex) {
        return false;
    }

        // adjust the camera the way you need
        mediaRecorder.setCamera(mCamera);
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);

        //
        CamcorderProfile cpHigh = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
        mediaRecorder.setProfile(cpHigh);
        mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());

    mediaRecorder.setOutputFile("/sdcard/" + videoNumer + "videocapture_example.mp4");

    //set max size
    mediaRecorder.setMaxDuration(600000); // Set max duration 60 sec.
    mediaRecorder.setMaxFileSize(50000000); // Set max file size 50M

    try {
        mediaRecorder.prepare();
    } catch (Exception e) {
        releaseMediaRecorder();
        e.printStackTrace();
    }
    return true;
}

private void releaseMediaRecorder() {
    if (mediaRecorder != null) {
        mediaRecorder.reset(); // clear recorder configuration
        mediaRecorder.release(); // release the recorder object
        mediaRecorder = null;
        if (mCamera != null) {
            mCamera.lock(); // lock camera for later use
        }
    }
}

/**
 * Camera
 */

private void initCamera() {
    if (mCamera == null) {
        // if the front facing camera does not exist
        if (findFrontFacingCamera() < 0) {
            Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show();
        }
        mCamera = Camera.open(findBackFacingCamera());
        mPreview.refreshCamera(mCamera);
    }
    onRecording = false;
}

private boolean hasCamera(Context context) {
    // check if the device has camera
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        hasCamera = true;
    } else {
        hasCamera = false;
    }
    return hasCamera;
}

private int findFrontFacingCamera() {
    int cameraId = -1;
    // Search for the front facing camera
    int numberOfCameras = Camera.getNumberOfCameras();
    for (int i = 0; i < numberOfCameras; i++) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            cameraId = i;
            cameraFront = true;
            break;
        }
    }
    this.cameraId = cameraId;
    return cameraId;
}

private int findBackFacingCamera() {
    int cameraId = -1;
    // Search for the back facing camera
    // get the number of cameras
    int numberOfCameras = Camera.getNumberOfCameras();
    // for every camera check
    for (int i = 0; i < numberOfCameras; i++) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            cameraId = i;
            cameraFront = false;
            break;
        }
    }
    this.cameraId = cameraId;
    return cameraId;
}

public void switchCamera() {
    // if the camera preview is the front
    if (cameraFront) {
        int cameraId = findBackFacingCamera();
        if (cameraId >= 0) {
            // open the backFacingCamera
            mCamera = Camera.open(cameraId);
            // refresh the preview
            mPreview.refreshCamera(mCamera);
        }
    } else {
        int cameraId = findFrontFacingCamera();
        if (cameraId >= 0) {
            // open the backFacingCamera
            mCamera = Camera.open(cameraId);
            // refresh the preview
            mPreview.refreshCamera(mCamera);
        }
    }
}

private void releaseCamera() {
    // stop and release camera
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}

}


您可以通过在录制按钮上设置 OnLongClickListener() 和 OnTouchListener() 来实现此功能。像这样:

recordBtn.setOnLongClickListener(recordBtnLCListener);
recordBtn.setOnTouchListener(recordBtnTouchListener);

then :

@Override
public boolean onLongClick(View v) {
    ivCancel.setVisibility(View.GONE);
    ivDone.setVisibility(View.GONE);
    isActionDown = true;
    try {
        if (isActionDown) {
            initRecorder();
            if (isActionDown)
                prepareRecorder();
        }
        if (isPrepared && isActionDown) {
            mMediaRecorder.start();
            isRecording = true;
        }
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("onLongPress Error ", e.toString());
    }

    return true;
}

and :

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
            isActionDown = false;

            try {
                if (isRecording) {

                    if (mMediaRecorder != null) {
                        mMediaRecorder.stop();
                    }
                    isRecording = false;
                }
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            break;
    }
    return false;
}

因此,通过这种方式,您可以录制视频的各个部分。意味着每次长按录制按钮时,录制就会开始。当您松开按钮时,录制就会停止,此时您必须将这部分视频保存在任何临时文件夹中。 一旦您完成了所需数量的视频的所有部分,那么您必须将视频的所有部分组合起来制作一个视频。

这里是合并临时文件夹中保存的所有视频部分的代码:

public void mergeVideos() {
    try {
        List<Movie> inMovies = new ArrayList<>();
        for (int i = 0; i < videosPathList.size(); i++) {
            String filePath = videosPathList.get(i);
            try {
                Movie movie = MovieCreator.build(filePath);
                if (movie != null)
                    inMovies.add(movie);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        List<Track> videoTracks = new LinkedList<Track>();
        List<Track> audioTracks = new LinkedList<Track>();
        for (Movie m : inMovies) {
            for (Track t : m.getTracks()) {
                try {
                    if (t.getHandler().equals("soun")) {
                        audioTracks.add(t);
                    }
                    if (t.getHandler().equals("vide")) {
                        videoTracks.add(t);
                    }
                } catch (Exception e) {

                }
            }
        }
        Movie result = new Movie();
        if (audioTracks.size() > 0) {
            result.addTrack(new AppendTrack(audioTracks
                    .toArray(new Track[audioTracks.size()])));
        }
        if (videoTracks.size() > 0) {
            result.addTrack(new AppendTrack(videoTracks
                    .toArray(new Track[videoTracks.size()])));
        }
        BasicContainer out = (BasicContainer) new DefaultMp4Builder().build(result);
        File f = null;
        String finalVideoPath;
        try {
            f = setUpVideoFile(Environment
        .getExternalStorageDirectory()+"/MyApp/videos/");
            finalVideoPath = f.getAbsolutePath();

        } catch (IOException e) {
            e.printStackTrace();
            f = null;
            finalVideoPath = null;
        }
        WritableByteChannel fc = new RandomAccessFile(finalVideoPath, "rw").getChannel();
        out.writeContainer(fc);
        fc.close();
        deleteFilesDir(); //In this method you have to delete all parts of video stored in temporary folder.


    } catch (Exception e) {
        e.printStackTrace();
       progressDialog.dismiss();
        finish();
    }
}

File setUpVideoFile(String directory) throws IOException {
    File videoFile = null;
    if (Environment.MEDIA_MOUNTED.equals(Environment
            .getExternalStorageState())) {
        File storageDir = new File(directory);
        if (storageDir != null) {
            if (!storageDir.mkdirs()) {
                if (!storageDir.exists()) {
                    Log.d("CameraSample", "failed to create directory");
                    return null;
                }
            }
        }
        videoFile = File.createTempFile("video_"
                        + System.currentTimeMillis() + "_",
                .mp4, storageDir);
    }
    return videoFile;
}

您可以在停止 mediaRecorder 后调用 mergeVideos() 方法。

希望这段代码对您有帮助。 :)

要合并视频,您必须使用 isoparser 库。因此,您必须在 gradle 文件中添加以下依赖项:

compile 'com.googlecode.mp4parser:isoparser:1.0.5.4'
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

点按并按住即可像 Vine 一样录制视频 的相关文章

  • 在 Android Studio 中,为什么我必须在模拟器中单击“运行应用程序”两次才能启动应用程序?

    在 Android Studio 中 当我按播放按钮在 Android 模拟器上安装并运行应用程序时 大约 5 10 秒后 我在屏幕底部收到一条消息 显示 安装成功 但应用程序实际上并未运行在模拟器上 我必须再次按下播放按钮 这是非常令人沮
  • SearchView过滤ListView

    我已经实现了搜索视图来过滤我的列表视图项目 当我输入任何文本时 它会过滤列表 但当我退出搜索视图时 它不会返回原始列表项 public class PlacesListAdapter extends ArrayAdapter
  • Android 后退按钮无法与 Flutter 选项卡内的导航器配合使用

    我需要在每个选项卡内有一个导航器 因此当我推送新的小部件时 选项卡栏会保留在屏幕上 代码运行得很好 但是 android 后退按钮正在关闭应用程序而不是运行 Navigator pop import package flutter mate
  • 谷歌坐标认证

    当我尝试连接到 Google 坐标时 总是出现异常GoogleAuthException 我拥有 Google 地图协调中心许可证 我确实使用我的包应用程序名称和 SHA1 在 google 控制台中创建了我的客户端 ID 我将权限添加到清
  • Adobe 是否为其 PDF 阅读器提供 Android SDK 或 API? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我希望能够在我们的应用程序内的视图中显示本地 PDF 文件 在 Android 4 03 下的平板电脑上运行 目前 我们将 Adob eR
  • 是否必须删除 Intent extra?

    这可能是一个愚蠢的问题 但是是否有一条规则规定消费活动必须显式删除 Intent 额外内容 或者只有在回收 Intent 对象时才如此 换句话说 如果我总是通过执行以下操作来链接到下一个活动 Intent i new Intent MyCu
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • 无法访问 com.google.android.gms.internal.zzbfm 的 zzbfm 类文件未找到

    我正在将我的 Android 应用程序项目从GCM to FCM 为此 我使用 Android Studio 中的 Firebase 助手工具 并遵循 Google 开发人员指南中的说明 一切都很顺利 并将我的应用程序代码更改为FCM根据助
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • 尝试将相机切换回前面但出现异常

    尝试将相机切换回前面 但出现异常 找不到 问题请检查并帮助 error 01 27 11 49 00 376 E AndroidRuntime 30767 java lang RuntimeException Unable to start
  • 发布android后更改应用内购买项目的价格

    在 Google Play 上发布后 是否可以更改应用内购买商品的价格 我假设该应用程序也已发布 完整的在线文档位于http developer android com http developer android com也http sup
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • 在activity_main.xml中注释

    我是安卓新手 据我所知 XML 中的注释与 HTML 中的注释相同 使用 形式 我想在 Android 项目的 Activity main xml 配置文件中写一些注释 但它给了我错误 值得注意的是 我使用的是 Eclipse 但目前 我直
  • 一次显示两条Toast消息?

    我希望在一个位置显示一条 Toast 消息 并在另一位置同时显示另一条 Toast 消息 多个 Toast 消息似乎总是按顺序排队和显示 是否可以同时显示两条消息 是否有一种解决方法至少可以提供这种外观并且不涉及扰乱活动布局 Edit 看来
  • 实现滚动选择 ListView 中的项目

    我想使用 ListView 您可以在其中滚动列表来选择一个项目 它应该像一个 Seekbar 但拇指应该是固定的 并且您必须使用该栏来调整它 我面临的一个问题是 我不知道这种小部件是如何调用的 这使得我很难搜索 所以我制作了下面这张图片 以
  • android sdk 的位置尚未在 Windows 操作系统的首选项中设置

    在 Eclipse 上 我转到 windows gt Android SDK 和 AVD Manager 然后弹出此消息 Android sdk 的位置尚未在首选项中设置 进入首选项 在侧边栏找到 Android 然后会出现一个 SDK 位
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两
  • 强制 Listview 不重复使用视图(复选框)

    我做了一个定制Listview 没有覆盖getView 方法 Listview 中的每个项目都具有以下布局 联系布局 xml

随机推荐