Screen Recorder in Android Studio
Today I'll teach you how to make a screen recording app in android studio.
Screen Recording feature is available only for API level above or equal 21(LOLLIPOP).
Before Lollipop app must require root permission to record screen.
You can also the whole project
Download Project
You can also the whole project
Download Project
Follow the below instructions :-
1) Add the Storage permission and audio permission in your Android Manifest file.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
Your android manifest will look like below:-<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.sanjay.ezyscreenrecorder"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>
2) Here I am using only one activity activity_main.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rootLayout"
android:background="#FFFFFF"
android:orientation="vertical"
android:gravity="center">
<Button
android:id="@+id/btn_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/start_recording" />
</LinearLayout>
3) Then is our MainActivity.java. Here is our magic works....package com.sanjay.ezyscreenrecorder; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; 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.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.support.annotation.NonNull; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseIntArray; import android.view.Surface; import android.view.View; import android.widget.Button; import android.widget.Toast; import java.util.Timer; import java.util.TimerTask; import java.io.File; import java.text.SimpleDateFormat; import java.io.IOException; import java.util.Calendar; public class MainActivity extends AppCompatActivity { private Timer timer = new Timer(); private TimerTask timerTask; private static final String TAG = "MainActivity"; private String videofile= ""; private AlertDialog.Builder dialog; private static final int REQUEST_CODE = 1000; private int mScreenDensity; Button btn_action; private MediaProjectionManager mProjectionManager; private static final int DISPLAY_WIDTH = 720; private static final int DISPLAY_HEIGHT = 1280; private MediaProjection mMediaProjection; private VirtualDisplay mVirtualDisplay; private MediaProjectionCallback mMediaProjectionCallback; private MediaRecorder mMediaRecorder; private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); private static final int REQUEST_PERMISSION_KEY = 1; boolean isRecording = false; private Calendar calendar = Calendar.getInstance(); static { ORIENTATIONS.append(Surface.ROTATION_0, 90); ORIENTATIONS.append(Surface.ROTATION_90, 0); ORIENTATIONS.append(Surface.ROTATION_180, 270); ORIENTATIONS.append(Surface.ROTATION_270, 180); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dialog = new AlertDialog.Builder(this); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); mScreenDensity = metrics.densityDpi; mMediaRecorder = new MediaRecorder(); mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); btn_action = (Button) findViewById(R.id.btn_action); btn_action.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onToggleScreenShare(); } }); } public void actionBtnReload() { if (isRecording) { btn_action.setText(getString(R.string.stop_recording)); } else { btn_action.setText(getString(R.string.start_recording)); } } public void onToggleScreenShare() { if (!isRecording) { String[] PERMISSIONS = { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO }; if (!Function.hasPermissions(this, PERMISSIONS)) { ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_KEY); }else { initRecorder(); shareScreen(); } } else { mMediaRecorder.stop(); mMediaRecorder.reset(); stopScreenSharing(); } } private void shareScreen() { if (mMediaProjection == null) { startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE); return; } mVirtualDisplay = createVirtualDisplay(); mMediaRecorder.start(); isRecording = true; actionBtnReload(); } private VirtualDisplay createVirtualDisplay() { return mMediaProjection.createVirtualDisplay("MainActivity", DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder.getSurface(), null, null); } private void initRecorder() { try { File file = new File("/storage/emulated/0/Ezy/"); if(!file.exists()) { file.mkdirs(); } calendar=Calendar.getInstance(); videofile= "/storage/emulated/0/Ezy/Video".concat(new SimpleDateFormat("dd_MM_yyyy_hh_mm_ss_a").format(calendar.getTime()).concat(".mp4")); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //THREE_GPP mMediaRecorder.setOutputFile(videofile); mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mMediaRecorder.setVideoEncodingBitRate(512 * 1000); mMediaRecorder.setVideoFrameRate(30); // 30 mMediaRecorder.setVideoEncodingBitRate(3000000); int rotation = getWindowManager().getDefaultDisplay().getRotation(); int orientation = ORIENTATIONS.get(rotation + 90); mMediaRecorder.setOrientationHint(orientation); mMediaRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); } } private void stopScreenSharing() { if (mVirtualDisplay == null) { return; } mVirtualDisplay.release(); destroyMediaProjection(); isRecording = false; actionBtnReload(); dialog.setTitle("Video is saved..."); dialog.setMessage("Saved in /storage/emulated/0/Ezy/"); dialog.setPositiveButton("View Video", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(videofile)); intent.setDataAndType(Uri.parse(videofile), "video/*"); startActivity(intent); } }); dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); dialog.create().show(); } private void destroyMediaProjection() { if (mMediaProjection != null) { mMediaProjection.unregisterCallback(mMediaProjectionCallback); mMediaProjection.stop(); mMediaProjection = null; } Log.i(TAG, "MediaProjection Stopped"); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode != REQUEST_CODE) { Log.e(TAG, "Unknown request code: " + requestCode); return; } if (resultCode != RESULT_OK) { Toast.makeText(this, "Screen Cast Permission Denied", Toast.LENGTH_SHORT).show(); isRecording = false; actionBtnReload(); return; } mMediaProjectionCallback = new MediaProjectionCallback(); mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); btn_action.setEnabled(false); moveTaskToBack(true); timerTask = new TimerTask() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "Screen Recording is started", Toast.LENGTH_SHORT).show(); timerTask = new TimerTask() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { btn_action.setEnabled(true); mMediaProjection.registerCallback(mMediaProjectionCallback, null); mVirtualDisplay = createVirtualDisplay(); isRecording = true; actionBtnReload(); mMediaRecorder.start(); } }); } }; timer.schedule(timerTask, (int)(500)); } }); } }; timer.schedule(timerTask,(int)(500)); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_PERMISSION_KEY: { if ((grantResults.length > 0) && (grantResults[0] + grantResults[1]) == PackageManager.PERMISSION_GRANTED) { onToggleScreenShare(); } else { isRecording = false; actionBtnReload(); Snackbar.make(findViewById(android.R.id.content), "Please enable Microphone and Storage permissions.", Snackbar.LENGTH_INDEFINITE).setAction("ENABLE", new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setData(Uri.parse("package:" + getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); startActivity(intent); } }).show(); } return; } } } private class MediaProjectionCallback extends MediaProjection.Callback { @Override public void onStop() { if (isRecording) { isRecording = false; actionBtnReload(); mMediaRecorder.stop(); mMediaRecorder.reset(); } mMediaProjection = null; stopScreenSharing(); } } @Override public void onDestroy() { super.onDestroy(); destroyMediaProjection(); } @Override public void onBackPressed() { if (isRecording) { Snackbar.make(findViewById(android.R.id.content), "Wanna Stop recording and exit?", Snackbar.LENGTH_INDEFINITE).setAction("Stop", new View.OnClickListener() { @Override public void onClick(View v) { mMediaRecorder.stop(); mMediaRecorder.reset(); Log.v(TAG, "Stopping Recording"); stopScreenSharing(); finish(); } }).show(); } else { finish(); } } }
Here I am using Ezy folder to save Videos...
4)Then I am using another java class to request permission.
package com.sanjay.ezyscreenrecorder; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; import android.support.v4.app.ActivityCompat; public class Function { public static boolean hasPermissions(Context context, String... permissions) { if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) { for (String permission : permissions) { if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { return false; } } } return true; } }5) Here is my string.xml file:-
<resources> <string name="app_name">Ezy Screen Recorder</string> <string name="stop_recording">Stop Recording</string> <string name="start_recording">Start Recording</string> </resources>
Now Build and Sync project and make an apk file, then test it on your device...
Thank you...
Nice
ReplyDelete