GVKun编程网logo

android – MediaRecorder“开始失败-12”(android mediasession)

52

如果您想了解android–MediaRecorder“开始失败-12”和androidmediasession的知识,那么本篇文章将是您的不二之选。我们将深入剖析android–MediaRecor

如果您想了解android – MediaRecorder“开始失败-12”android mediasession的知识,那么本篇文章将是您的不二之选。我们将深入剖析android – MediaRecorder“开始失败-12”的各个方面,并为您解答android mediasession的疑在这篇文章中,我们将为您介绍android – MediaRecorder“开始失败-12”的相关知识,同时也会详细的解释android mediasession的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

android – MediaRecorder“开始失败-12”(android mediasession)

android – MediaRecorder“开始失败-12”(android mediasession)

所以我一直在为更大的应用程序开发录音模块.
它在大多数设备上都功能齐全,但有一批手机只是拒绝录制.

每当我使用MediaRecorder开始录制时,LogCat都会慷慨地告诉我MediaRecorder无法启动,导致错误代码-12.
我一整天都在搜索互联网,寻找这些错误代码的解释.到目前为止,我一直不走运.因此,我转向开发者社区的其他人.

MediaRecorder start Failed -12

关于这些错误代码已经提出了不止一个问题,更具体地说是16,19,22和一个可笑的大数字2147483648,但是这个信息在我的案例中证明是无用的.

有谁知道我在哪里可以找到可靠的MediaRecorder错误代码列表,包括这些错误代码的含义?或者甚至更好,向我解释一下全能的Android oracle试图向我发出信号?

提前致谢

解决方法

我之前的回答并不完整.
经过更多的修改后,我发现很多设备对大多数设备默认的设置都非常敏感,但实际上有很多设备没有按照你期望的方式运行,它们会崩溃,给你带来许多不同的错误您无法在互联网上找到的代码.这些错误代码的范围从-12,-19,-21到-100等,并且大多数错误代码可以通过使用以下提示来解决.我将在下面列出一些简短的发现:

运行API 10的HTC ChaCha不使用H264编码器进行记录.我使用MP4和/或H263工作,但视频仍然完全失真.解决方法是将相机预览大小设置为640 * 480,而不是使用谷歌自己的“最佳预览”方法,该方法返回576 * 432.通过为此模型设置例外,我能够完美地记录它.

运行API 10的galaxy Y在尝试使用H264进行录制时崩溃.这个使用MP4编码器是个例外.固定它.

运行API 10的galaxy Ace在尝试使用MP4返回错误代码-12进行记录时崩溃.使用H264编码器为此设备模型添加例外可解决此问题.

运行API 10的Desire Z在尝试使用MP4编码器进行录制时崩溃.给我一个错误-100(媒体服务器死了).使用H264修复了这个问题.

if(API >=11){
        if(CamcorderProfile.hasProfile(mCamId,CamcorderProfile.QUALITY_480P)) {
            Log.d(TAG,"API 11+ 480P");
            mMediaRecorder.setProfile(CamcorderProfile.get(mCamId,CamcorderProfile.QUALITY_480P));
            mMediaRecorder.setVideoSize(640,480);
            mMediaRecorder.setVideoEncodingBitRate(2000000);
        } else {
            Log.d(TAG,"API 11+ LOW");
            mMediaRecorder.setProfile(CamcorderProfile.get(mCamId,CamcorderProfile.QUALITY_LOW));
        }
    } else if (API < 11 && !MODEL.equals("GT-S5830") && !MODEL.equals("vision")){
        mMediaRecorder.setoutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        Log.d(TAG,"API 9 device,defaulting");
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mMediaRecorder.setVideoSize(640,480);
        mMediaRecorder.setVideoEncodingBitRate(2000000);
    } else if ((API < 11) && MODEL.equals("GT-S5830") || MODEL.equals("vision")) {
        //galaxy Ace and Desire Z
        mMediaRecorder.setoutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mMediaRecorder.setVideoSize(640,480);
        mMediaRecorder.setVideoEncodingBitRate(2000000);
    }

我打赌我会遇到更多的模型,这是一个隐喻性的痛苦,当我这样做时,我会将它们添加到列表中.
总结一下;如果您遇到这些烦人的,几乎无法解释的错误代码,请查看MediaRecorder参数.我建议不要将CamcorderProfile类用于任何低于11的API,因为许多这些模型在使用高质量的实例时会崩溃.
如果您的录像机视频文件显示奇怪的绿色,在屏幕上运行的半对角线等,请尝试将预览大小设置为与录像机视频大小相匹配.

Camera.Parameters param = mCamera.getParameters();
param.setPreviewSize(width,height);
mCamera.setParameters( param );

Android AudioRecord和MediaRecorder

Android AudioRecord和MediaRecorder

我正在开发一个音频处理应用程序,我需要录制音频,然后处理它以获得该录制的功能.但是,我希望使用MediaPlayer播放可播放格式的音频.

我已经看到录制音频来处理它最好使用AudioRecord,因为我可以从那里获得原始音频.但是后来我无法以可播放的格式将数据写入文件(在android中是否有任何库可以执行此操作?).

我使用此方法记录原始数据,然后将其写入文件:
http://andrewbrobinson.com/2011/11/27/capturing-raw-audio-data-in-android/
但是当我尝试在设备上播放此文件时,它无法播放.

然后,如果我使用MediaRecorder,我不知道如何解码数据来提取功能.我一直在寻找MediaExtractor,但它接触MediaExtractor不解码帧.

那么..最好的方法是什么?我想这在任何音频处理应用程序中都很常见,但我无法找到管理它的方法.

感谢您的回复.

解决方法

如果您需要进行任何类型的处理,使用AudioRecord是正确的方法.要播放它,你有几个选择.如果您只是在应用程序中播放它,则可以使用AudioTrack而不是MediaPlayer播放原始PCM流.

如果您希望它可以与其他应用程序一起播放,您需要先将其转换为其他应用程序. WAV通常是最简单的,因为您只需添加header.您还可以找到用于转换为其他格式的库,例如JOGbis for OGG或JLayer for MP3等.

android MediaRecorder 视频录制

android MediaRecorder 视频录制

package com.example.camera;

import java.io.IOException;

import android.app.Activity;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainActivity extends Activity implements SurfaceHolder.Callback {

	private SurfaceView mSurfaceview = null; // SurfaceView对象:(视图组件)视频显示
	private SurfaceHolder mSurfaceHolder = null; // SurfaceHolder对象:(抽象接口)SurfaceView支持类
	private MediaRecorder mediarecorder;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mSurfaceview = (SurfaceView) findViewById(R.id.surfaceview);
		mSurfaceHolder = mSurfaceview.getHolder(); // 绑定SurfaceView,取得SurfaceHolder对象
		mSurfaceHolder.addCallback(this); // SurfaceHolder加入回调接口
		mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 設置顯示器類型,setType必须设置

	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
	}

	@Override
	protected void onPause() {
		super.onPause();
		mediarecorder.stop();
		mediarecorder.release();
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		mediarecorder = new MediaRecorder();// 创建mediarecorder对象
		// 设置录制视频源为Camera(相机)
		mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
		// 设置录制完成后视频的封装格式THREE_GPP为3gp.MPEG_4为mp4
		mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
		// 设置录制的视频编码h263 h264
		mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
		// 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错
		// mediarecorder.setVideoSize(176, 144);
		// 设置录制的视频帧率。必须放在设置编码和格式的后面,否则报错
		mediarecorder.setVideoFrameRate(20);
		mediarecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
		// 设置视频文件输出的路径
		mediarecorder.setOutputFile("/sdcard/love.3gp");
		try {
			mediarecorder.prepare();
			mediarecorder.start();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {

	}

}
参考:http://blog.sina.com.cn/s/blog_972577b3010108p1.html

Android mediarecorder只录制可怕质量的视频

Android mediarecorder只录制可怕质量的视频

所以我有以下代码来进行录制,质量非常糟糕.我想我必须设置错误,但我已经尝试过两种方式.以“CamcorderProfile”方式然后以“手动”方式,可以看到摄像机代码被注释掉了.两者都给出了完全相同的结果.

Camera _camera = Camera.Open (1);
    _camera.Unlock ();

    recorder = new MediaRecorder ();

    recorder.SetCamera (_camera);

    recorder.SetAudioSource (AudioSource.Mic);    
    recorder.SetVideoSource (VideoSource.Camera); 

    recorder.SetoutputFormat (OutputFormat.Default);

    recorder.SetAudioEncoder (AudioEncoder.Default);
    recorder.SetVideoEncoder (VideoEncoder.Default);

    //CamcorderProfile p = CamcorderProfile.Get(0,CamcorderQuality.High);
    //recorder.SetProfile(p);

    recorder.SetoutputFile (path);       

    recorder.SetPreviewdisplay(video.Holder.Surface);

    recorder.Prepare ();
    recorder.Start ();

这很好用,但问题就在这里. This是录制时预览窗口的图片,this是播放时的视频图片.你实际上不能说,因为截图是如此可怕,但没有一种颜色是正确的(它几乎没有颜色)我认为颜色通道必定存在某种问题.例如,这是与genymotion“虚拟相机”的另一个比较.这是correct版本.这是weird播放版.

解决方法

此属性有助于提高视频质量:

mediaRecorder.setVideoEncodingBitRate(3000000);  //you may try varying the argument value

并且在准备(:)之前调用此方法

android MediaRecorder实现录屏时带录音功能

android MediaRecorder实现录屏时带录音功能

下面说说android的事把

最近是不是也会遇到需求中需要用到录屏录音的功能,最近也是遇到的 现在整理完记录一下

首先呢,录音录屏需要权限 先贴一个动态权限类

public class TalAllow {
  /**
   * RECORD_AUDIO     音频权限
   * WRITE_EXTERNAL_STORAGE 写入权限
   * CAMERA        相机权限
   */
  public static void requestPermissions(Context context,int allowCode) {
    ArrayList<String> ps = new ArrayList<>();
    int per = ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO);
    if (per != PackageManager.PERMISSION_GRANTED) {
      ps.add(Manifest.permission.RECORD_AUDIO);
    }
    per = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    if (per != PackageManager.PERMISSION_GRANTED) {
      ps.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }
    per = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA);
    if (per != PackageManager.PERMISSION_GRANTED) {
      ps.add(Manifest.permission.CAMERA);
    }
    per = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE);
    if (per != PackageManager.PERMISSION_GRANTED) {
      ps.add(Manifest.permission.READ_PHONE_STATE);
    }
    Log.d(TAG, "requestPermissions:ps=" + ps.size());
    if (!ps.isEmpty()) {
      String[] ps3 = new String[ps.size()];
      ps.toArray(ps3);
      ActivityCompat.requestPermissions((Activity) context, ps3, allowCode);
    }
  }
}

有需求需要判断权限的呢 插入个链接 (上面那个类code码为100)
判断是否有权限

下面重点来了

首先说明一下这个录屏和录音是在服务里面做的,所以呢贴一个服务类
这个代码绝对有质量 做了很多处理,下面一行一行解读把

//首先呢实现的是Handle.Callback接口 主要是做时间及计时时间回调的,会重新写HandleMessage方法,其实我个觉得跟在括号{} 里面重写没啥区别就是简洁页面
public class TalScreenRecordService extends Service implements Handler.Callback {
//这个就不解释了吧 log
  private static final String TAG = "TalScreenRecordService";
  //这个类是管理类拿到服务后会通过下面的类申请录屏,点击允许,
  //其中会回调两个参数,code码 和 data,都在ActivityForResult中进行判断code
  private MediaProjectionManager mProjectionManager;
 //这个会拿到申请的结果
  private MediaProjection mMediaProjection;
  //这个类就是我们主要的录屏录音的类啦
  private MediaRecorder mMediaRecorder;
  //这个就是我们要获取录制屏幕的大小,像素,等等一些数据
  //关于这类更详细的介绍https://blog.csdn.net/qq_16628781/article/details/62038163
  private VirtualDisplay mVirtualDisplay;
 //是否正在录制 false 没有录制
  private boolean mIsRunning;
  //获取屏幕的宽高和像素密度 稍后贴类
  private int mRecordWidth = TalScreenParams.getScreenWidth();
  private int mRecordHeight = TalScreenParams.getScreenWidth();
  private int mScreenDpi = TalScreenParams.getScreenDpi();
 //code data 就是上面说的允许后回调
  private int mResultCode;
  private Intent mResultData;
  //录屏文件的保存地址
  private String mRecordFilePath;
  private Handler mHandler;
  //已经录制多少秒了
  private int mRecordSeconds = 0;
  //handle发送消息时的what
  private static final int MSG_TYPE_COUNT_DOWN = 110;
 //这个是继承Service 必须重写的方法 这是使用的BindService(生命周期的长短跟activity一致)
  @Override
  public IBinder onBind(Intent intent) {
    return new RecordBinder();
  }
 //说一说这个返回值的问题吧
 // START_STICKY 粘性返回 ,一次失败,多次启动,不保留Intent对象
 //关于返回值问题https://blog.csdn.net/github_37663523/article/details/78811539
 @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    return START_STICKY;
  }
  @Override
  public void onCreate() {
    super.onCreate();
    //没有录制
    mIsRunning = false;
    //创建对象 在create方法里只执行一次
    mMediaRecorder = new MediaRecorder();
    // 由于实现了CallBack接口,在这里注册一下接口(个人觉得高大的写法,简洁)
    mHandler = new Handler(Looper.getMainLooper(), this);
  }
  @Override
  public void onDestroy() {
    super.onDestroy();
  }
 //数据不为空
  public boolean isReady() {
    return mMediaProjection != null && mResultData != null;
  }
 //清除的方法 避免内存泄漏 相信都看得懂
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  public void clearRecordElement() {
    clearAll();
    if (mMediaRecorder != null) {
      mMediaRecorder.reset();
      mMediaRecorder.release();
      mMediaRecorder = null;
    }
    mResultData = null;
    //不执行的时候false
    mIsRunning = false;
  }
 //这个就是给是否正在录屏提供一个get方法
  public boolean ismIsRunning() {
    return mIsRunning;
  }
 //这个就是设置数据的方法在ActivityForResult中设置数据,说明是允许录屏的
  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  public void setResultData(int resultCode, Intent resultData) {
    mResultCode = resultCode;
    mResultData = resultData;
 //拿到这个管理,看不懂跟上面注释结合看
    mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    //getMediaProjection(code,data)不知道这样写看不看的董 
    //说白了MediaProjectionManager是申请权限 MediaProjection是获取申请结果,防止别人调取隐私
    //再通过上面的setResultData方法获取到ActivityForResult中的code,data
    if (mProjectionManager != null) {
      mMediaProjection = mProjectionManager.getMediaProjection(mResultCode, mResultData);
    }
  }
 //开始录制了
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  public boolean startRecord() {
  //代码执行顺序(false,目前没录屏)
    if (mIsRunning) {
      return false;
    }
    //再次创建,防止异常
    if (mMediaProjection == null) {
      mMediaProjection = mProjectionManager.getMediaProjection(mResultCode, mResultData);
    }
 //关于文件路径还有录屏的一些参数问题
    setUpMediaRecorder();
    //关于获取录制屏幕的大小,像素,等等一些数据
    createVirtualDisplay();
    //开始录制
    mMediaRecorder.start();
 //稍后贴类 监听录制情况
    TalScreenUtils.startRecord();
    //最多录制三分钟
    mHandler.sendEmptyMessageDelayed(MSG_TYPE_COUNT_DOWN, 1000);
    //录制时为true
    mIsRunning = true;
    Log.d(TAG, "startRecord ");
    return true;
  }
 //停止的方法
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  public boolean stopRecord(String tip) {
    Log.d(TAG, "stopRecord: first ");
    //mIsRunning 默认值为false !mIsRunning 就是true。。
    if (!mIsRunning) {
      return false;
    }
    mIsRunning = false;
    Log.w(TAG, "stopRecord middle");
    try {
    //停止抓取异常,该置空的为空
      mMediaRecorder.stop();
      mMediaRecorder.reset();
      mMediaRecorder = null;
      mVirtualDisplay.release();
      mMediaProjection.stop();
      Log.w(TAG, "stopRecord ");
    } catch (Exception e) {
      e.printStackTrace();
      mMediaRecorder.release();
      mMediaRecorder = null;
      Log.w(TAG, "stopRecord exception");
    }
    mMediaProjection = null;
 //停止时移出这条消息what 
    mHandler.removeMessages(MSG_TYPE_COUNT_DOWN);
    //停止的监听 tip 是处理一些突发情况 比如内存不足
    TalScreenUtils.stopRecord(tip);
    Log.i(TAG, "stopRecord: " + mRecordFilePath);
    //录制时间不到两秒就删除录制文件
    if (mRecordSeconds <= 2) {
      TalFileUtils.deleteSDFile(mRecordFilePath);
    } else {
    //录制的视频库,将数据添加到媒体库
    //这个算是应用程序之间共享数据,把自己应用的数据添加到手机的媒体库ContentResolver
    //举个例子,代码添加手机联系人到自己的联系人列表,或者代码添加图片到自己的图库,还有不懂得,贴个链接
    //https://blog.csdn.net/bzlj2912009596/article/details/80248272
      TalFileUtils.fileScanVideo(this, mRecordFilePath, 1280, 720, mRecordSeconds);
    }
//    mRecordFilePath = null;
    mRecordSeconds = 0;
    return true;
  }
 //下面是关于处理在一些activity or fragment中生命周期的做法
  public void pauseRecord() {
    if (mMediaRecorder != null) {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        mMediaRecorder.pause();
      }
    }
  }
  public void resumeRecord() {
    if (mMediaRecorder != null) {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        mMediaRecorder.resume();
      }
    }
  }
 //这个就是刚才讲过的 绘制窗口大小,dpi问题 VirtualDisplay
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  private void createVirtualDisplay() {
    mVirtualDisplay = mMediaProjection.createVirtualDisplay("MainScreen", 1280, 720, mScreenDpi,
        DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder.getSurface(), null, null);
  }
 //这个主要是路径,还有设置一些录制视频参数问题separator 为字节,占位用
  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  private void setUpMediaRecorder() {
    mRecordFilePath = getSaveDirectory() + File.separator + System.currentTimeMillis() + ".mp4";
    Log.i(TAG, "setUpMediaRecorder: " + mRecordFilePath);
    if (mMediaRecorder == null) {
      mMediaRecorder = new MediaRecorder();
    }
    //设置音频源
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
 //设置视频源    
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
 //设置输出的编码格式 
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    if (mRecordFilePath != null) {
      mMediaRecorder.setOutputFile(mRecordFilePath);
    } else if (mRecordFilePath == null) {
      mMediaRecorder.setOutputFile(mRecordFilePath);
    }
    //设置录屏时屏幕大小,这个可跟mVirtualDisplay 一起控制屏幕大小
    //mVirtualDisplay 是将屏幕设置成多大多小,setVideoSize是输出文件时屏幕多大多小
    mMediaRecorder.setVideoSize(1280, 720);
     //图像编码 H264较好还有其他选择
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
  //音频编码    
    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    //设置码率 高清的话的要数越大
    mMediaRecorder.setVideoEncodingBitRate((int) (1280 * 720 * 2.6));
    //设置帧率,该帧率必须是硬件支持的,可以通过Camera.CameraParameter.getSupportedPreviewFpsRange()方法获取相机支持的帧率
    mMediaRecorder.setVideoFrameRate(20);
    try {
    //准备
      mMediaRecorder.prepare();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  public void clearAll() {
    if (mMediaProjection != null) {
      mMediaProjection.stop();
      mMediaProjection = null;
    }
  }
 //路径
  public String getRecordFilePath() {
    return mRecordFilePath;
  }
 //sd下绝对路径,先判断sd卡是否挂载
  public String getSaveDirectory() {
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
      return Environment.getExternalStorageDirectory().getAbsolutePath();
    } else {
      return null;
    }
  }
  //这是实现了Handle.CallBack中重写方法 handleMessage
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  @Override
  public boolean handleMessage(Message msg) {
    switch (msg.what) {
      case MSG_TYPE_COUNT_DOWN: {
        String str = null;
        //这是内存
        boolean enough = TalFileUtils.getSDFreeMemory() / (1024 * 1024) < 4;
        if (enough) {
          //空间不足,停止录屏
          str = "空间不足";
          //停止录屏时 通过接口回调一个信息,是因为什么停止录屏的
          stopRecord(str);
          mRecordSeconds = 0;
          break;
        }
        mRecordSeconds++;
        int minute = 0, second = 0;
        if (mRecordSeconds >= 60) {
          minute = mRecordSeconds / 60;
          second = mRecordSeconds % 60;
        } else {
          second = mRecordSeconds;
        }
        TalScreenUtils.onRecording("0" + minute + ":" + (second < 10 ? "0" + second : second + ""));
        if (mRecordSeconds < 5 * 60) {
          mHandler.sendEmptyMessageDelayed(MSG_TYPE_COUNT_DOWN, 1000);
        } else if (mRecordSeconds == 5 * 60) {
          str = "录制已到限定时长";
          stopRecord(str);
          mRecordSeconds = 0;
        }
        break;
      }
    }
    return true;
  }
  public class RecordBinder extends Binder {
    public TalScreenRecordService getRecordService() {
      return TalScreenRecordService.this;
    }
  }
}

下面贴关于手机像素还有dpi的类

public class TalScreenParams {
  private static int mScreenWidth;
  private static int mScreenHeight;
  private static int mScreenDpi;

  public static void init(Activity activity){
    Display display = activity.getWindowManager().getDefaultDisplay();
    DisplayMetrics metrics = new DisplayMetrics();
    display.getMetrics(metrics);
    mScreenWidth = metrics.widthPixels;
    mScreenHeight = metrics.heightPixels;
    mScreenDpi = metrics.densityDpi;
  }

  public static int getScreenWidth(){
    return mScreenWidth;
  }

  public static int getScreenHeight(){
    return mScreenHeight;
  }

  public static int getScreenDpi(){
    return mScreenDpi;
  }

下面贴关于删除文件,添加到媒体库的类 这里就使用到了ContentResolver

public class TalFileUtils {
  /**
   * 删除SD卡中的文件或目录
   *
   * @param path
   * @return
   */
  public static boolean deleteSDFile(String path) {
    return deleteSDFile(path, false);
  }

  /**
   * 删除SD卡中的文件或目录
   *
   * @param path
   * @param deleteParent true为删除父目录
   * @return
   */
  public static boolean deleteSDFile(String path, boolean deleteParent) {
    if (TextUtils.isEmpty(path)) {
      return false;
    }

    File file = new File(path);
    if (!file.exists()) {
      //不存在
      return true;
    }
    return deleteFile(file, deleteParent);
  }

  /**
   * @param file
   * @param deleteParent true为删除父目录
   * @return
   */
  public static boolean deleteFile(File file, boolean deleteParent) {
    boolean flag = false;
    if (file == null) {
      return flag;
    }
    if (file.isDirectory()) {
      //是文件夹
      File[] files = file.listFiles();
      if (files.length > 0) {
        for (int i = 0; i < files.length; i++) {
          flag = deleteFile(files[i], true);
          if (!flag) {
            return flag;
          }
        }
      }
      if (deleteParent) {
        flag = file.delete();
      }
    } else {
      flag = file.delete();
    }
    file = null;
    return flag;
  }

  /**
   * 添加到媒体数据库
   *
   * @param context 上下文
   */
  public static Uri fileScanVideo(Context context, String videoPath, int videoWidth, int videoHeight,
                  int videoTime) {
    File file = new File(videoPath);
    if (file.exists()) {
      Uri uri = null;
      long size = file.length();
      String fileName = file.getName();
      long dateTaken = System.currentTimeMillis();
      ContentValues values = new ContentValues(11);
      values.put(MediaStore.Video.Media.DATA, videoPath); // 路径;
      values.put(MediaStore.Video.Media.TITLE, fileName); // 标题;
      values.put(MediaStore.Video.Media.DURATION, videoTime * 1000); // 时长
      values.put(MediaStore.Video.Media.WIDTH, videoWidth); // 视频宽
      values.put(MediaStore.Video.Media.HEIGHT, videoHeight); // 视频高
      values.put(MediaStore.Video.Media.SIZE, size); // 视频大小;
      values.put(MediaStore.Video.Media.DATE_TAKEN, dateTaken); // 插入时间;
      values.put(MediaStore.Video.Media.DISPLAY_NAME, fileName);// 文件名;
      values.put(MediaStore.Video.Media.DATE_MODIFIED, dateTaken / 1000);// 修改时间;
      values.put(MediaStore.Video.Media.DATE_ADDED, dateTaken / 1000); // 添加时间;
      values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");

      ContentResolver resolver = context.getContentResolver();

      if (resolver != null) {
        try {
          uri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
        } catch (Exception e) {
          e.printStackTrace();
          uri = null;
        }
      }

      if (uri == null) {
        MediaScannerConnection.scanFile(context, new String[]{videoPath}, new String[]{"video/*"}, new MediaScannerConnection.OnScanCompletedListener() {
          @Override
          public void onScanCompleted(String path, Uri uri) {

          }
        });
      }

      return uri;
    }

    return null;
  }

  /**
   * SD卡存在并可以使用
   */
  public static boolean isSDExists() {
    return Environment.getExternalStorageState().equals(
        Environment.MEDIA_MOUNTED);
  }

  /**
   * 获取SD卡的剩余容量,单位是Byte
   *
   * @return
   */
  public static long getSDFreeMemory() {
    try {
      if (isSDExists()) {
        File pathFile = Environment.getExternalStorageDirectory();
        // Retrieve overall information about the space on a filesystem.
        // This is a Wrapper for Unix statfs().
        StatFs statfs = new StatFs(pathFile.getPath());
        // 获取SDCard上每一个block的SIZE
        long nBlockSize = statfs.getBlockSize();
        // 获取可供程序使用的Block的数量
        // long nAvailBlock = statfs.getAvailableBlocksLong();
        long nAvailBlock = statfs.getAvailableBlocks();
        // 计算SDCard剩余大小Byte
        long nSDFreeSize = nAvailBlock * nBlockSize;
        return nSDFreeSize;
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    return 0;
  }
  public static long getFreeMem(Context context) {
    ActivityManager manager = (ActivityManager) context.getApplicationContext().getSystemService(Activity.ACTIVITY_SERVICE);
    if (manager != null) {
      ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
      if (info != null) {
        manager.getMemoryInfo(info);
        // 单位Byte
        return info.availMem / 1024 / 1024;
      }
    }
    return 0;
  }
}

还有一个类 是为整个Service提供了便捷访问的类 ,将一些监听service中的变化放到集合里来做

public class TalScreenUtils {
  private static TalScreenRecordService s_ScreenRecordService;
  private static List<RecordListener> s_RecordListener = new ArrayList<>();
  private static List<OnPageRecordListener> s_PageRecordListener = new ArrayList<>();
  //true,录制结束的提示语正在显示
  public static boolean s_IsRecordingTipShowing = false;
  /**
   * 录屏功能 5.0+ 的手机才能使用
   * @return
   */
  public static boolean isScreenRecordEnable(){
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ;
  }
  public static void setScreenService(TalScreenRecordService screenService){
    s_ScreenRecordService = screenService;
  }
  public static void clear(){
    if ( isScreenRecordEnable() && s_ScreenRecordService != null){
      s_ScreenRecordService.clearAll();
      s_ScreenRecordService = null;
    }
    if (s_RecordListener != null && s_RecordListener.size() > 0){
      s_RecordListener.clear();
    }
    if (s_PageRecordListener != null && s_PageRecordListener.size() > 0 ){
      s_PageRecordListener.clear();
    }
  }
  /**
   * 开始录制
   */
  public static void startScreenRecord(Activity activity, int requestCode) {
    if (isScreenRecordEnable()){
      if (s_ScreenRecordService != null && !s_ScreenRecordService.ismIsRunning()){
        if (!s_ScreenRecordService.isReady()){
          MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) activity.
              getSystemService(Context.MEDIA_PROJECTION_SERVICE);
          if (mediaProjectionManager != null){
            Intent intent = mediaProjectionManager.createScreenCaptureIntent();
            PackageManager packageManager = activity.getPackageManager();
            if (packageManager.resolveActivity(intent,PackageManager.MATCH_DEFAULT_ONLY) != null){
              //存在录屏授权的Activity
              activity.startActivityForResult(intent,requestCode);
            }else {
              Toast.makeText(activity, "不能录音", Toast.LENGTH_SHORT).show();
            }
          }
        } else {
          s_ScreenRecordService.startRecord();
        }
      }
    }
  }
  /**
   * 获取用户允许录屏后,设置必要的数据
   * @param resultCode
   * @param resultData
   */
  public static void setUpData(int resultCode,Intent resultData) throws Exception{
    if (isScreenRecordEnable()){
      if (s_ScreenRecordService != null && !s_ScreenRecordService.ismIsRunning()){
        s_ScreenRecordService.setResultData(resultCode,resultData);
        s_ScreenRecordService.startRecord();
      }
    }
  }
  /**
   * 停止录制
   */
  public static void stopScreenRecord(Context context){
    if (isScreenRecordEnable()){
      if (s_ScreenRecordService != null && s_ScreenRecordService.ismIsRunning()){
        String str = "停止录制";
        s_ScreenRecordService.stopRecord(str);
      }
    }
  }
  /**
   * 获取录制后的文件地址
   * @return
   */
  public static String getScreenRecordFilePath(){
    if (isScreenRecordEnable() && s_ScreenRecordService!= null) {
      return s_ScreenRecordService.getRecordFilePath();
    }
    return null;
  }
  /**
   * 判断当前是否在录制
   * @return
   */
  public static boolean isCurrentRecording(){
    if (isScreenRecordEnable() && s_ScreenRecordService!= null) {
      return s_ScreenRecordService.ismIsRunning();
    }
    return false;
  }
  /**
   * true,录制结束的提示语正在显示
   * @return
   */
  public static boolean isRecodingTipShow(){
    return s_IsRecordingTipShowing;
  }
  public static void setRecordingStatus(boolean isShow){
    s_IsRecordingTipShowing = isShow;
  }
  /**
   * 系统正在录屏,app 录屏会有冲突,清理掉一些数据
   */
  public static void clearRecordElement(){
    if (isScreenRecordEnable()){
      if (s_ScreenRecordService != null ){
        s_ScreenRecordService.clearRecordElement();
      }
    }
  }
  public static void addRecordListener(RecordListener listener){
    if (listener != null && !s_RecordListener.contains(listener)){
      s_RecordListener.add(listener);
    }
  }
  public static void removeRecordListener(RecordListener listener){
    if (listener != null && s_RecordListener.contains(listener)){
      s_RecordListener.remove(listener);
    }
  }
  public static void addPageRecordListener( OnPageRecordListener listener){
    if (listener != null && !s_PageRecordListener.contains(listener)){
      s_PageRecordListener.add(listener);
    }
  }
  public static void removePageRecordListener( OnPageRecordListener listener){
    if (listener != null && s_PageRecordListener.contains(listener)){
      s_PageRecordListener.remove(listener);
    }
  }
  public static void onPageRecordStart(){
    if (s_PageRecordListener!= null && s_PageRecordListener.size() > 0 ){
      for (OnPageRecordListener listener : s_PageRecordListener){
        listener.onStartRecord();
      }
    }
  }
  public static void onPageRecordStop(){
    if (s_PageRecordListener!= null && s_PageRecordListener.size() > 0 ){
      for (OnPageRecordListener listener : s_PageRecordListener){
        listener.onStopRecord();
      }
    }
  }
  public static void onPageBeforeShowAnim(){
    if (s_PageRecordListener!= null && s_PageRecordListener.size() > 0 ){
      for (OnPageRecordListener listener : s_PageRecordListener){
        listener.onBeforeShowAnim();
      }
    }
  }
  public static void onPageAfterHideAnim(){
    if (s_PageRecordListener!= null && s_PageRecordListener.size() > 0 ){
      for (OnPageRecordListener listener : s_PageRecordListener){
        listener.onAfterHideAnim();
      }
    }
  }
  public static void startRecord(){
    if (s_RecordListener.size() > 0 ){
      for (RecordListener listener : s_RecordListener){
        listener.onStartRecord();
        Log.i("xxx", "startRecord: ");
      }
    }
  }
  public static void pauseRecord(){
    if (s_RecordListener.size() > 0 ){
      for (RecordListener listener : s_RecordListener){
        listener.onPauseRecord();
      }
    }
  }
  public static void resumeRecord(){
    if (s_RecordListener.size() > 0 ){
      for (RecordListener listener : s_RecordListener){
        listener.onResumeRecord();
      }
    }
  }
  public static void onRecording(String timeTip){
    if (s_RecordListener.size() > 0 ){
      for (RecordListener listener : s_RecordListener){
        listener.onRecording(timeTip);
      }
    }
  }
  public static void stopRecord(String stopTip){
    if (s_RecordListener.size() > 0 ){
      for (RecordListener listener : s_RecordListener){
        listener.onStopRecord( stopTip);
      }
    }
  }
  public interface RecordListener{
    void onStartRecord();
    void onPauseRecord();
    void onResumeRecord();
    void onStopRecord(String stopTip);
    void onRecording(String timeTip);
  }
  public interface OnPageRecordListener {
    void onStartRecord();
    void onStopRecord();
    void onBeforeShowAnim();
    void onAfterHideAnim();
  }
}

到了最后了,是一些调用时的内容

public class MainActivity extends AppCompatActivity {
  private static final String TAG = MainActivity.class.getSimpleName();
  private Button mBtn;
  private final int REQUEST_ALLOW = 100;
  private Button mButton;
  //bindService需要创建连接
  private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
      //启动service
      TalScreenRecordService.RecordBinder recordBinder = (TalScreenRecordService.RecordBinder) service;
      TalScreenRecordService recordService = recordBinder.getRecordService();
      //这个其实是传值在使用的activity中拿到Service
      TalScreenUtils.setScreenService(recordService);
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
    }
  };
 //开启service,意图跳转到service,别忘了AndroidManifest里面需要注册这个service哦
  private void startService() {
    Intent intent = new Intent(MainActivity.this, TalScreenRecordService.class);
    bindService(intent, mConnection, BIND_AUTO_CREATE);
  }
  @Override
  protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mBtn = findViewById(R.id.btn);
    mButton = findViewById(R.id.button2);
    initView();
    //两个按钮 一个开始 一个结束 xml不贴了
    mBtn.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        if (TalFileUtils.getFreeMem(MainActivity.this) < 100) {
          Toast.makeText(MainActivity.this, "手机内存不足,请清理后再进行录屏", Toast.LENGTH_SHORT).show();
          return;
        }
        //开始录屏录音
        TalScreenUtils.startScreenRecord(MainActivity.this, REQUEST_ALLOW);
      }
    });
    mButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        stop();
        Log.i(TAG, "onClick: " + stop());
      }
  //停止录屏录音返回路径
      private String stop() {
        TalScreenUtils.stopScreenRecord(MainActivity.this);//停止
        return TalScreenUtils.getScreenRecordFilePath();
      }
    });
  }
  @Override
  protected void onStart() {
    super.onStart();

  }

  private void initView() {
    //权限申请
    TalAllow.requestPermissions(this, REQUEST_ALLOW);
    //获取屏幕大小 在onCreate里面初始化就可以获取
    TalScreenParams.init(this);
    startService();
  }

  @Override
  protected void onStop() {
    super.onStop();
    //在对用户可见不可交互的时候防止异常
    TalScreenUtils.clear();
  }
 //打印权限获取情况日志
  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    Toast.makeText(this, permissions[0] + "\n" + grantResults[0], Toast.LENGTH_SHORT).show();
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }
 //在用户允许录屏后拿到确定的code 跟data
  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_ALLOW && data != null) {
      try {
      //设置数据,在用户允许后 调用了开始录屏的方法
        TalScreenUtils.setUpData(resultCode, data);
        //拿到路径
        String screenRecordFilePath = TalScreenUtils.getScreenRecordFilePath();
        if (screenRecordFilePath == null) {
          Toast.makeText(this, "空的", Toast.LENGTH_SHORT).show();
        }
        Toast.makeText(MainActivity.this, "" + screenRecordFilePath, Toast.LENGTH_SHORT).show();
        Log.i("zlq", "onClick: " + screenRecordFilePath);
      } catch (Exception e) {
        e.printStackTrace();
      }
    } else {
      Toast.makeText(this, "禁止录屏", Toast.LENGTH_SHORT).show();
    }
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    unbindService(mConnection);
  }
}

至此,一个还算比较完整的录屏录音功能就可以实现,不足之处请批评指正

总结

到此这篇关于android MediaRecorder录屏时带录音功能实现的文章就介绍到这了,更多相关android MediaRecorder录屏带录音内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

您可能感兴趣的文章:
  • Android编程录音工具类RecorderUtil定义与用法示例
  • Android实现录音功能实现实例(MediaRecorder)
  • Android使用AudioRecord实现暂停录音功能实例代码
  • Android录音--AudioRecord、MediaRecorder的使用
  • android 通过MediaRecorder实现简单的录音示例
  • Android使用MediaRecorder实现录音及播放
  • Android App调用MediaRecorder实现录音功能的实例
  • Android音频录制MediaRecorder之简易的录音软件实现代码
  • Android简单的利用MediaRecorder进行录音的实例代码
  • Android使用AudioRecord实现录音功能

关于android – MediaRecorder“开始失败-12”android mediasession的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Android AudioRecord和MediaRecorder、android MediaRecorder 视频录制、Android mediarecorder只录制可怕质量的视频、android MediaRecorder实现录屏时带录音功能等相关知识的信息别忘了在本站进行查找喔。

本文标签: