不需root权限,也不依赖架包,完美实现了录屏+录音,项目里面,大家都会很讨厌导入架包,又安装什么插件才能运行起来的功能,这对于一些普通群众,他们根本不会给你再下下插件,再给你搞搞root,希望能帮到大家
(马上都把csdn给忘了,谢谢大家的关注,我只分享我用在项目里面很好用的Demo,也为了给关注我的人带来更多的帮助,我会持续为大家更新)
为了避免您在项目里粘贴报红,先把一些细节贴出来
<string name="record_video_tip">停止录制</string>
<string name="can_not_record_tip">暂时无法录制</string>
<string name="record_space_tip">存储空间不足</string>
<string name="record_time_end_tip">录制已到限定时长</string>
下面是权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
这个是主activity的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_record_time"
android:text="0:00"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_margin="20dp"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_start"
android:text="开始录制"
android:textSize="21dp"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_end"
android:text="结束录制"
android:textSize="21dp"
android:clickable="true"
android:layout_marginLeft="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
下面是主运行代码,上面布局是下面activity的布局:
import android.app.Activity;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.hani.coolcode.service.ScreenRecordService;
import com.hani.coolcode.service.ScreenUtil;
import com.hani.coolcode.utils.CommonUtil;
import com.hani.coolcode.utils.PermissionUtils;
import com.hani.coolcode.utils.ToastUtil;
import static android.support.v4.content.PermissionChecker.PERMISSION_DENIED;
public class ScreenRecordActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTvStart;
private TextView mTvEnd;
private TextView mTvTime;
private int REQUEST_CODE = 1;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.screen_record_activity);
CommonUtil.init(this);
PermissionUtils.checkPermission(this);
mTvStart = findViewById(R.id.tv_start);
mTvStart.setOnClickListener(this);
mTvTime = findViewById(R.id.tv_record_time);
mTvEnd = findViewById(R.id.tv_end);
mTvEnd.setOnClickListener(this);
startScreenRecordService();
}
private ServiceConnection mServiceConnection;
/**
* 开启录制 Service
*/
private void startScreenRecordService(){
mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
ScreenRecordService.RecordBinder recordBinder = (ScreenRecordService.RecordBinder) service;
ScreenRecordService screenRecordService = recordBinder.getRecordService();
ScreenUtil.setScreenService(screenRecordService);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Intent intent = new Intent(this, ScreenRecordService.class);
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
ScreenUtil.addRecordListener(recordListener);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
for (int temp : grantResults) {
if (temp == PERMISSION_DENIED) {
AlertDialog dialog = new AlertDialog.Builder(this).setTitle("申请权限").setMessage("这些权限很重要").setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ToastUtil.show(ScreenRecordActivity.this, "取消");
}
}).setPositiveButton("设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + ScreenRecordActivity.this.getPackageName()));
ScreenRecordActivity.this.startActivity(intent);
}
}).create();
dialog.show();
break;
}
}
}
private ScreenUtil.RecordListener recordListener = new ScreenUtil.RecordListener() {
@Override
public void onStartRecord() {
}
@Override
public void onPauseRecord() {
}
@Override
public void onResumeRecord() {
}
@Override
public void onStopRecord(String stopTip) {
ToastUtil.show(ScreenRecordActivity.this,stopTip);
}
@Override
public void onRecording(String timeTip) {
mTvTime.setText(timeTip);
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK){
try {
ScreenUtil.setUpData(resultCode,data);
} catch (Exception e) {
e.printStackTrace();
}
} else {
ToastUtil.show(this,"拒绝录屏");
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.tv_start:{
ScreenUtil.startScreenRecord(this,REQUEST_CODE);
break;
}
case R.id.tv_end:{
ScreenUtil.stopScreenRecord(this);
break;
}
}
}
}
下面是录屏,录音需要的权限工具类:
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
/**
* 动态申请权限
* 可以在activity中增加如果权限被拒绝后的弹窗,在onRequestPermissionsResult中判断状态
*
* @author lixiao
* @since 2017-10-25 00:00
*/
public class PermissionUtils {
/**
* 获取打开摄像机的权限,录音,文件读写
*
* @param activity
*/
public static void checkPermission(AppCompatActivity activity) {
if (Build.VERSION.SDK_INT >= 23) {
int checkPermission =
ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO)
+ ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_STATE)
+ ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
if (checkPermission != PackageManager.PERMISSION_GRANTED) {
//动态申请
ActivityCompat.requestPermissions(activity, new String[]{
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);
return;
} else {
return;
}
}
return;
}
}
ScreenUtil 录屏工具类,展示的是录屏过程的一个相关状态
package android_robot.com.example.luping.service;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import android_robot.com.example.luping.R;
/**
* Created by admin on 2018/3/28.
*/
public class ScreenUtil {
private static ScreenRecordService 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(ScreenRecordService 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, R.string.can_not_record_tip,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 = context.getString(R.string.record_video_tip);
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();
}
}
}
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();
}
}
下面是对录音,录屏文件的管理类
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
import android.provider.MediaStore;
import android.text.TextUtils;
import java.io.File;
public class FileUtil {
/**
* 删除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;
}
}
CommonUtil
public class CommonUtil {
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;
}
}
下面是service的辅助类和service通知刷新的后台操作方法:
import android.annotation.TargetApi;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Binder;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.RequiresApi;
import com.RZ.TeacherAC.R;
import com.RZ.TeacherAC.recording.utils.CommonUtil;
import com.RZ.TeacherAC.recording.utils.FileUtil;
import java.io.File;
import java.io.IOException;
/**
* Created by admin on 2018/3/28.
*/
public class ScreenRecordService extends Service implements Handler.Callback{
private MediaProjectionManager mProjectionManager;
private MediaProjection mMediaProjection;
private MediaRecorder mMediaRecorder;
private VirtualDisplay mVirtualDisplay;
private boolean mIsRunning;
private int mRecordWidth = CommonUtil.getScreenWidth();
private int mRecordHeight = CommonUtil.getScreenHeight();
private int mScreenDpi = CommonUtil.getScreenDpi();
private int mResultCode;
private Intent mResultData;
//录屏文件的保存地址
private String mRecordFilePath;
private Handler mHandler;
//已经录制多少秒了
private int mRecordSeconds = 0;
private static final int MSG_TYPE_COUNT_DOWN = 110;
@Override
public IBinder onBind(Intent intent) {
return new RecordBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
mIsRunning = false;
mMediaRecorder = new MediaRecorder();
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;
mIsRunning =false;
}
public boolean ismIsRunning() {
return mIsRunning;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void setResultData(int resultCode, Intent resultData){
mResultCode = resultCode;
mResultData = resultData;
mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (mProjectionManager != null){
mMediaProjection = mProjectionManager.getMediaProjection(mResultCode,mResultData);
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public boolean startRecord() {
if ( mIsRunning) {
return false;
}
if (mMediaProjection == null){
mMediaProjection = mProjectionManager.getMediaProjection(mResultCode,mResultData);
}
setUpMediaRecorder();
createVirtualDisplay();
mMediaRecorder.start();
ScreenUtil.startRecord();
//最多录制三分钟
mHandler.sendEmptyMessageDelayed(MSG_TYPE_COUNT_DOWN,1000);
mIsRunning = true;
// Log.w("lala","startRecord ");
return true;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public boolean stopRecord(String tip) {
// Log.w("lala","stopRecord: first ");
if (!mIsRunning) {
return false;
}
mIsRunning = false;
// Log.w("lala","stopRecord middle");
try {
mMediaRecorder.stop();
mMediaRecorder.reset();
mMediaRecorder = null;
mVirtualDisplay.release();
mMediaProjection.stop();
// Log.w("lala","stopRecord ");
}catch (Exception e){
e.printStackTrace();
mMediaRecorder.release();
mMediaRecorder = null;
// Log.w("lala","stopRecord exception");
}
mMediaProjection = null;
mHandler.removeMessages(MSG_TYPE_COUNT_DOWN);
ScreenUtil.stopRecord(tip);
if (mRecordSeconds <= 2 ){
FileUtil.deleteSDFile(mRecordFilePath);
}else {
//通知系统图库更新
FileUtil.fileScanVideo(this,mRecordFilePath,mRecordWidth,mRecordHeight,mRecordSeconds);
}
// mRecordFilePath = null;
mRecordSeconds = 0;
return true;
}
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();
}
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void createVirtualDisplay() {
mVirtualDisplay = mMediaProjection.createVirtualDisplay("MainScreen", mRecordWidth, mRecordHeight, mScreenDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder.getSurface(), null, null);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setUpMediaRecorder() {
mRecordFilePath = getSaveDirectory() + File.separator+ System.currentTimeMillis() + ".mp4";
if (mMediaRecorder == null){
mMediaRecorder = new MediaRecorder();
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setOutputFile( mRecordFilePath );
mMediaRecorder.setVideoSize(mRecordWidth, mRecordHeight);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncodingBitRate((int) (mRecordWidth * mRecordHeight * 3.6));
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;
}
public String getSaveDirectory() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return Environment.getExternalStorageDirectory().getAbsolutePath();
} else {
return null;
}
}
@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 = FileUtil.getSDFreeMemory() / (1024* 1024) < 4;
if (enough){
//空间不足,停止录屏
str = getString(R.string.record_space_tip);
stopRecord(str);
mRecordSeconds = 0;
break;
}
mRecordSeconds++;
int minute = 0, second = 0;
if (mRecordSeconds >= 60 ){
minute = mRecordSeconds / 60;
second = mRecordSeconds % 60;
} else {
second = mRecordSeconds;
}
ScreenUtil.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 = getString(R.string.record_time_end_tip);
stopRecord(str);
mRecordSeconds = 0;
}
break;
}
}
return true;
}
public class RecordBinder extends Binder {
public ScreenRecordService getRecordService() {
return ScreenRecordService.this;
}
}
}
好了,这就是全部代码了,菜鸟一枚,希望大家多多关注!
有问题,可以在下面评论,看到就会回的