日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

android MediaRecorder實現(xiàn)錄屏時帶錄音功能

瀏覽:146日期:2022-09-25 08:05:40

下面說說android的事把

最近是不是也會遇到需求中需要用到錄屏錄音的功能,最近也是遇到的 現(xiàn)在整理完記錄一下

首先呢,錄音錄屏需要權(quán)限 先貼一個動態(tài)權(quán)限類

public class TalAllow { /** * RECORD_AUDIO 音頻權(quán)限 * WRITE_EXTERNAL_STORAGE 寫入權(quán)限 * CAMERA相機權(quán)限 */ 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); } }}

有需求需要判斷權(quán)限的呢 插入個鏈接 (上面那個類code碼為100)判斷是否有權(quán)限

下面重點來了

首先說明一下這個錄屏和錄音是在服務里面做的,所以呢貼一個服務類這個代碼絕對有質(zhì)量 做了很多處理,下面一行一行解讀把

//首先呢實現(xiàn)的是Handle.Callback接口 主要是做時間及計時時間回調(diào)的,會重新寫HandleMessage方法,其實我個覺得跟在括號{} 里面重寫沒啥區(qū)別就是簡潔頁面public class TalScreenRecordService extends Service implements Handler.Callback {//這個就不解釋了吧 log private static final String TAG = 'TalScreenRecordService'; //這個類是管理類拿到服務后會通過下面的類申請錄屏,點擊允許, //其中會回調(diào)兩個參數(shù),code碼 和 data,都在ActivityForResult中進行判斷code private MediaProjectionManager mProjectionManager; //這個會拿到申請的結(jié)果 private MediaProjection mMediaProjection; //這個類就是我們主要的錄屏錄音的類啦 private MediaRecorder mMediaRecorder; //這個就是我們要獲取錄制屏幕的大小,像素,等等一些數(shù)據(jù) //關于這類更詳細的介紹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 就是上面說的允許后回調(diào) private int mResultCode; private Intent mResultData; //錄屏文件的保存地址 private String mRecordFilePath; private Handler mHandler; //已經(jīng)錄制多少秒了 private int mRecordSeconds = 0; //handle發(fā)送消息時的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; //創(chuàng)建對象 在create方法里只執(zhí)行一次 mMediaRecorder = new MediaRecorder(); // 由于實現(xiàn)了CallBack接口,在這里注冊一下接口(個人覺得高大的寫法,簡潔) mHandler = new Handler(Looper.getMainLooper(), this); } @Override public void onDestroy() { super.onDestroy(); } //數(shù)據(jù)不為空 public boolean isReady() { return mMediaProjection != null && mResultData != null; } //清除的方法 避免內(nèi)存泄漏 相信都看得懂 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public void clearRecordElement() { clearAll(); if (mMediaRecorder != null) { mMediaRecorder.reset(); mMediaRecorder.release(); mMediaRecorder = null; } mResultData = null; //不執(zhí)行的時候false mIsRunning = false; } //這個就是給是否正在錄屏提供一個get方法 public boolean ismIsRunning() { return mIsRunning; } //這個就是設置數(shù)據(jù)的方法在ActivityForResult中設置數(shù)據(jù),說明是允許錄屏的 @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void setResultData(int resultCode, Intent resultData) { mResultCode = resultCode; mResultData = resultData; //拿到這個管理,看不懂跟上面注釋結(jié)合看 mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); //getMediaProjection(code,data)不知道這樣寫看不看的董 //說白了MediaProjectionManager是申請權(quán)限 MediaProjection是獲取申請結(jié)果,防止別人調(diào)取隱私 //再通過上面的setResultData方法獲取到ActivityForResult中的code,data if (mProjectionManager != null) { mMediaProjection = mProjectionManager.getMediaProjection(mResultCode, mResultData); } } //開始錄制了 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public boolean startRecord() { //代碼執(zhí)行順序(false,目前沒錄屏) if (mIsRunning) { return false; } //再次創(chuàng)建,防止異常 if (mMediaProjection == null) { mMediaProjection = mProjectionManager.getMediaProjection(mResultCode, mResultData); } //關于文件路徑還有錄屏的一些參數(shù)問題 setUpMediaRecorder(); //關于獲取錄制屏幕的大小,像素,等等一些數(shù)據(jù) createVirtualDisplay(); //開始錄制 mMediaRecorder.start(); //稍后貼類 監(jiān)聽錄制情況 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); //停止的監(jiān)聽 tip 是處理一些突發(fā)情況 比如內(nèi)存不足 TalScreenUtils.stopRecord(tip); Log.i(TAG, 'stopRecord: ' + mRecordFilePath); //錄制時間不到兩秒就刪除錄制文件 if (mRecordSeconds <= 2) { TalFileUtils.deleteSDFile(mRecordFilePath); } else { //錄制的視頻庫,將數(shù)據(jù)添加到媒體庫 //這個算是應用程序之間共享數(shù)據(jù),把自己應用的數(shù)據(jù)添加到手機的媒體庫ContentResolver //舉個例子,代碼添加手機聯(lián)系人到自己的聯(lián)系人列表,或者代碼添加圖片到自己的圖庫,還有不懂得,貼個鏈接 //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); } //這個主要是路徑,還有設置一些錄制視頻參數(shù)問題separator 為字節(jié),占位用 @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); //設置碼率 高清的話的要數(shù)越大 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; } } //這是實現(xiàn)了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;//這是內(nèi)存boolean enough = TalFileUtils.getSDFreeMemory() / (1024 * 1024) < 4;if (enough) { //空間不足,停止錄屏 str = '空間不足'; //停止錄屏時 通過接口回調(diào)一個信息,是因為什么停止錄屏的 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; } /** * 添加到媒體數(shù)據(jù)庫 * * @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的SIZElong nBlockSize = statfs.getBlockSize();// 獲取可供程序使用的Block的數(shù)量// long nAvailBlock = statfs.getAvailableBlocksLong();long nAvailBlock = statfs.getAvailableBlocks();// 計算SDCard剩余大小Bytelong 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);// 單位Bytereturn info.availMem / 1024 / 1024; } } return 0; }}

還有一個類 是為整個Service提供了便捷訪問的類 ,將一些監(jiān)聽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,錄制結(jié)束的提示語正在顯示 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){ //存在錄屏授權(quán)的Activity activity.startActivityForResult(intent,requestCode); }else { Toast.makeText(activity, '不能錄音', Toast.LENGTH_SHORT).show(); } }} else { s_ScreenRecordService.startRecord();} } } } /** * 獲取用戶允許錄屏后,設置必要的數(shù)據(jù) * @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,錄制結(jié)束的提示語正在顯示 * @return */ public static boolean isRecodingTipShow(){ return s_IsRecordingTipShowing; } public static void setRecordingStatus(boolean isShow){ s_IsRecordingTipShowing = isShow; } /** * 系統(tǒng)正在錄屏,app 錄屏會有沖突,清理掉一些數(shù)據(jù) */ 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(); }}

到了最后了,是一些調(diào)用時的內(nèi)容

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需要創(chuàng)建連接 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,意圖跳轉(zhuǎn)到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(); //兩個按鈕 一個開始 一個結(jié)束 xml不貼了 mBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {if (TalFileUtils.getFreeMem(MainActivity.this) < 100) { Toast.makeText(MainActivity.this, '手機內(nèi)存不足,請清理后再進行錄屏', 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() { //權(quán)限申請 TalAllow.requestPermissions(this, REQUEST_ALLOW); //獲取屏幕大小 在onCreate里面初始化就可以獲取 TalScreenParams.init(this); startService(); } @Override protected void onStop() { super.onStop(); //在對用戶可見不可交互的時候防止異常 TalScreenUtils.clear(); } //打印權(quán)限獲取情況日志 @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 { //設置數(shù)據(jù),在用戶允許后 調(diào)用了開始錄屏的方法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); }}

至此,一個還算比較完整的錄屏錄音功能就可以實現(xiàn),不足之處請批評指正

總結(jié)

到此這篇關于android MediaRecorder錄屏時帶錄音功能實現(xiàn)的文章就介紹到這了,更多相關android MediaRecorder錄屏帶錄音內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持好吧啦網(wǎng)!

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久在线视频免费观看| 一区免费视频| 亚洲美女91| 综合一区二区三区| 国产婷婷精品| 综合激情婷婷| 国产日韩亚洲欧美精品| 乱一区二区av| 91精品一区国产高清在线gif| 亚洲二区视频| 美国欧美日韩国产在线播放| 日韩高清不卡在线| 国产精品久av福利在线观看| 精品高清久久| 在线一区免费| 午夜久久av| 国产精品宾馆| 黄色在线观看www| 欧美精品一区二区三区精品| 欧美一级精品| 亚洲影院天堂中文av色| 国产免费av国片精品草莓男男| 开心激情综合| 日韩精品欧美| 三级亚洲高清视频| 久久国产人妖系列| 国产一区丝袜| 国产精品人人爽人人做我的可爱| 亚洲人成网77777色在线播放| 91嫩草精品| 一区二区精品伦理...| 伊人久久亚洲美女图片| 日韩国产在线不卡视频| 成人国产精品一区二区网站| 91精品国产福利在线观看麻豆| 在线观看亚洲精品福利片| 麻豆精品少妇| 一区免费视频| 久久免费视频66| 亚洲欧美日韩精品一区二区 | 日韩欧美在线中字| 亚洲激情不卡| 精品99在线| 中文字幕av一区二区三区人 | 中文一区一区三区免费在线观| 精品资源在线| 国产毛片久久| 国产精品黑丝在线播放| 日韩中文字幕不卡| 日韩精品永久网址| 欧美亚洲三级| 亚洲黄页一区| 日韩免费福利视频| 国产麻豆精品| 欧美资源在线| 97人人精品| 欧美久久久网站| 国产综合精品| 国产不卡精品在线| 日韩av在线免费观看不卡| 99久久精品费精品国产| 欧美激情日韩| 日本中文字幕一区二区视频 | 91看片一区| 国产精品嫩模av在线| 国产精品日本| 婷婷成人综合| 黄色精品视频| 国产欧美亚洲一区| 丝瓜av网站精品一区二区| 精精国产xxxx视频在线野外| 日韩福利视频网| 亚洲精品2区| 97国产精品| 欧美国产另类| 国产精品视频首页| 日韩精品免费视频一区二区三区| 91高清一区| 国产v日韩v欧美v| 国产极品模特精品一二| 中文一区一区三区免费在线观 | 丝袜美腿一区| 成人午夜网址| 国产精品丝袜在线播放| 日韩高清在线不卡| 久久亚洲精品伦理| 欧美a级片一区| 欧美日韩在线观看视频小说| 97精品中文字幕| 久久精品国产99国产精品| 国产日韩在线观看视频| 日韩激情中文字幕| 中文字幕日韩亚洲| 亚洲一区二区免费在线观看| 久久国产精品久久久久久电车| 狠狠色狠狠色综合日日tαg| 亚洲精品一二三区区别| 婷婷亚洲综合| 欧美日韩少妇| 红桃视频欧美| 久久不射中文字幕| 蜜臀av国产精品久久久久| 亚洲一区激情| 中文字幕av亚洲精品一部二部| 亚洲精品在线a| 91成人精品在线| 国产精品99久久免费| 国产精品三p一区二区| 乱一区二区av| 日本欧美不卡| 欧美日韩免费观看一区=区三区| 国产精品毛片在线看| 蜜臀av亚洲一区中文字幕| 日韩中文字幕视频网| 国产精品丝袜在线播放| аⅴ资源天堂资源库在线| 久久国产亚洲精品| 欧美在线影院| 亚洲精品日本| 麻豆91在线播放| 日本韩国欧美超级黄在线观看| 蜜桃成人av| 天堂成人国产精品一区| 日本久久二区| 国产一区一一区高清不卡| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 六月天综合网| 亚洲免费专区| 欧美成人精品一级| 久久视频国产| 日本中文字幕不卡| 国产成人久久精品一区二区三区| 波多野结衣久久精品| 亚洲精品91| 国产精品自在| 九九久久电影| 国产日韩一区二区三区在线| 捆绑调教日本一区二区三区| 黑丝一区二区三区| 国产精品三级| 99热免费精品| 久久精品国产999大香线蕉| 好吊一区二区三区| 久久av网站| 性欧美长视频| 国产在视频一区二区三区吞精| 国产一区白浆| 精品一区二区三区免费看| 婷婷色综合网| 久久免费精品| 爽好久久久欧美精品| 国产一区二区三区亚洲| 国产精品色网| 女生影院久久| 国产亚洲一区二区三区啪| 欧美日韩中文一区二区| 国产剧情一区二区在线观看| 国产精品美女| 成人日韩在线| 欧美日韩精品一区二区三区视频 | 免费人成网站在线观看欧美高清| 国产精品xxx在线观看| 黄色国产精品| 国产精品久久久久久久免费观看| 蜜臀va亚洲va欧美va天堂| 国产欧美一区二区三区精品酒店| 色综合视频一区二区三区日韩 | 丝瓜av网站精品一区二区| 岛国av免费在线观看| 日韩福利视频网| 亚洲欧美久久久| 日本国产精品| 丰满少妇一区| 国产伦理一区| 亚洲精品在线二区| 米奇777超碰欧美日韩亚洲| 精品三区视频| 日本精品久久| 亚洲综合国产| 日韩一区二区在线免费| 国产乱码精品一区二区亚洲| 国产农村妇女精品一区二区| 欧美男人天堂| 久久精品人人| 国产调教一区二区三区| 视频在线观看国产精品| 91精品精品| 国产成人精品亚洲日本在线观看| 国产精品亚洲产品| 婷婷精品在线| 免费在线欧美视频| 91久久视频| 午夜国产精品视频| 999国产精品视频| 四虎成人av| 国产一区丝袜| 成人一二三区| 欧美激情另类| 亚洲永久av| 日本美女一区|