不需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"><TextViewandroid: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" /><LinearLayoutandroid:layout_width="match_parent"android:layout_margin="20dp"android:layout_height="wrap_content"><TextViewandroid:id="@+id/tv_start"android:text="开始录制"android:textSize="21dp"android:clickable="true"android:layout_width="wrap_content"android:layout_height="wrap_content" /><TextViewandroid: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;@Overrideprotected 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() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {ScreenRecordService.RecordBinder recordBinder = (ScreenRecordService.RecordBinder) service;ScreenRecordService screenRecordService = recordBinder.getRecordService();ScreenUtil.setScreenService(screenRecordService);}@Overridepublic void onServiceDisconnected(ComponentName name) {}};Intent intent = new Intent(this, ScreenRecordService.class);bindService(intent, mServiceConnection, BIND_AUTO_CREATE);ScreenUtil.addRecordListener(recordListener);}@Overridepublic 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() {@Overridepublic void onClick(DialogInterface dialog, int which) {ToastUtil.show(ScreenRecordActivity.this, "取消");}}).setPositiveButton("设置", new DialogInterface.OnClickListener() {@Overridepublic 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() {@Overridepublic void onStartRecord() {}@Overridepublic void onPauseRecord() {}@Overridepublic void onResumeRecord() {}@Overridepublic void onStopRecord(String stopTip) {ToastUtil.show(ScreenRecordActivity.this,stopTip);}@Overridepublic void onRecording(String timeTip) {mTvTime.setText(timeTip);}};@Overrideprotected 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,"拒绝录屏");}}@Overridepublic 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){//存在录屏授权的Activityactivity.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() {@Overridepublic 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的SIZElong nBlockSize = statfs.getBlockSize();// 获取可供程序使用的Block的数量// long nAvailBlock = statfs.getAvailableBlocksLong();long nAvailBlock = statfs.getAvailableBlocks();// 计算SDCard剩余大小Bytelong 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;@Overridepublic IBinder onBind(Intent intent) {return new RecordBinder();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return START_STICKY;}@Overridepublic void onCreate() {super.onCreate();mIsRunning = false;mMediaRecorder = new MediaRecorder();mHandler = new Handler(Looper.getMainLooper(),this);}@Overridepublic 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)@Overridepublic 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;}}}

好了,这就是全部代码了,菜鸟一枚,希望大家多多关注!

有问题,可以在下面评论,看到就会回的

Android 录屏+录音,原生代码,无需root权限,好用更好懂相关推荐

  1. C++版Android实时投屏软件系统源码,安卓手机投屏软件源码,无需root权限

    QtScrcpy QtScrcpy 可以通过 USB / 网络连接Android设备,并进行显示和控制.无需root权限. 同时支持 GNU/Linux ,Windows 和 MacOS 三大主流桌面 ...

  2. android 手机录屏功能,Android录屏功能的实现

    最近做一个Android开发的项目用到了录屏的功能,开始查阅了一些资料和博客,基本上都是在讨论ROOT的.直到后来在github上看到一个比较新的代码,才恍然发现,Android 5.0时候开放了一个 ...

  3. 如何调用android录屏功能吗,Android录屏功能的实现

    最近做一个Android开发的项目用到了录屏的功能,开始查阅了一些资料和博客,基本上都是在讨论ROOT的.直到后来在github上看到一个比较新的代码,才恍然发现,Android 5.0时候开放了一个 ...

  4. Android录屏应用开发研究

    1截屏接口 在Android5.0之前如果希望截图屏幕,是需要获取系统root权限的.但在Android5.0之后Android开放了新的接口android.media.projection,开发者使 ...

  5. Android录屏分析(Android12源码)

    Android录屏分析 目录 Android录屏分析 prepare方法(准备录制) MediaProjection.MediaRecorder.VirtualDisplay的介绍 开始与结束 缩略图 ...

  6. 无需Root权限新型Android木马SpyNote在多个论坛泄露

    [发现厂家: Paloaltonetworks] 由于其可以免费获得,虽然目前还未发现实际的感染案例,但是可以预见到其可能在近期内传播开来. 木马名称: SpyNote 类似木马: OmniRat和D ...

  7. android 录屏自动运行,自动化录屏方案简介 for Android

    原标题:自动化录屏方案简介 for Android 前言 针对移动端项目的评测,为了记录并评估产品表现,时常需要对设备进行录屏以作后续分析. 那么,应该如何在Python脚本中可靠.可控地实现安卓设备 ...

  8. android 录屏 github,GitHub - mabeijianxi/ScreenRecordPushStream: Android 录屏推流demo

    ScreenRecordPushStream 这是一个基于 rtmp 协议的 Android 录屏推流demo (Demo APK 下载) 使用方法 一. 服务器搭建 mkdir nms cd nms ...

  9. Qt+FFmpeg录屏录音

    源码:Qt+FFmpeg录屏录音 NanaRecorder 之前的录屏项目ScreenCapture存在音视频同步问题,所以重写了第二个版本:NanaRecorder. 录制桌面和系统声音(扬声器). ...

  10. android录屏软件

    android录屏软件 系统类型:Android手机(平板) 软件大小:1KB 软件简介:通过USB链接android.用鼠标键盘控制你的android 安装步骤: 1.安装的Android SDK( ...

最新文章

  1. 城市地图, 军事地图, 矿山地图, 电力地理, 电子地图, 制图, 编辑, OCX控件, VC++源代码组件库...
  2. POJ 3009 Curling 2.0(简单DFS)
  3. iphone查看删除的短信_手机资讯:iPhone手机可以批量删除短信吗如何操作
  4. [Swift]LeetCode916.单词子集 | Word Subsets
  5. 下拉选择_在管理Excel中实现联动下拉选择
  6. 通用职责分配软件原则之5-控制器原则
  7. Wireshark 检索命令
  8. CSND怎样获得积分
  9. 111、锐捷交换机如何配置?一步步详解,交换机配置再也不难了
  10. 傅里叶变换(二维离散傅里叶变换)
  11. C语言:数组排序(冒泡法排序)
  12. Linux 查询系统日志
  13. 数据库SQL Server 2017下载及安装
  14. 数据库完整性--断言和触发器
  15. java从邮箱获取邮件_javaMail正确读取邮箱内容的方式
  16. python 网络编程基础
  17. 判断输入的年份是不是闰年
  18. 事务的基本特性是什么
  19. Python学习(九)Python缩进规则
  20. 【WebRTC】回声抵消(aec、aecm)算法简介

热门文章

  1. mac上qlv格式转mp4方法
  2. 操作——UE常用快捷键
  3. NB-IoT技术发展史漫谈(NB-IoT专栏—拓展篇1)
  4. 2021全国大学生信息安全竞赛初赛部分Write up
  5. wps插入公式与文字不平行问题解决办法
  6. 推荐一款待办事项和日程管理的微信小程序——腾讯待办
  7. android音视频焦点切换
  8. 2D武侠游戏《剑侠世界》网游单机 搭建教程说明
  9. android手机陀螺仪传感器,10.12 传感器专题(3)——加速度/陀螺仪传感器
  10. 陀螺仪传感器与方向传感器的区别