Reputation: 63
I copied the program from this site http://www.truiton.com/2015/05/capture-record-android-screen-using-mediaprojection-apis/ in order to create a screen recorder app. When I stop the app and try to view the video the writing of the video is not yet completed. I see that because in my file manager app the size of the file is growing at a very slow rate of about 50kb/s. It's exactly the same code as on the webpage. What could be the problem?
private MediaProjectionCallback mMediaProjectionCallback;
private int mScreenDensity;
private MediaRecorder mMediaRecorder;
private MediaProjectionManager mProjectionManager;
private VirtualDisplay mVirtualDisplay;
private static final int DISPLAY_WIDTH = 720;
private static final int DISPLAY_HEIGHT = 1280;
private static final int SCREEN_CAPTURE_REQUEST_CODE = 10; //random number
private static final int WRITE_STORAGE_AND_RECORD_AUDIO_CODE = 11; //random number
private MediaProjection mMediaProjection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "service is started!");
DisplayMetrics metrics = getApplicationContext().getResources().getDisplayMetrics();
mScreenDensity = metrics.densityDpi;
mMediaRecorder = new MediaRecorder();
mProjectionManager = (MediaProjectionManager) getSystemService
(Context.MEDIA_PROJECTION_SERVICE);
// check permissions
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) + ContextCompat
.checkSelfPermission(MainActivity.this,
Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "Permissions not granted!");
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission
.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO},
WRITE_STORAGE_AND_RECORD_AUDIO_CODE);
}
else {
Log.i(TAG, "Permissions is granted!");
initRecorder();
shareScreen();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.i(TAG, "Timer went off!");
stopScreenSharing();
}
}, 10000);
}
}
//ActivityCompat.requestPermissions callback
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if(requestCode == WRITE_STORAGE_AND_RECORD_AUDIO_CODE)
{
//relaunch mainactivity
Intent i = new Intent(getBaseContext(), MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
return;
}
Log.i(TAG, "ERROR: onRequestPermissionsResult");
}
private void initRecorder() {
try {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setOutputFile(Environment
.getExternalStoragePublicDirectory(Environment
.DIRECTORY_DOWNLOADS) + "/video.mp4");
mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncodingBitRate(512 * 1000);
mMediaRecorder.setVideoFrameRate(10);
mMediaRecorder.setOrientationHint(0);
mMediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
private void shareScreen() {
if (mMediaProjection == null) {
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), SCREEN_CAPTURE_REQUEST_CODE);
return;
}
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != SCREEN_CAPTURE_REQUEST_CODE) {
Log.e(TAG, "Unknown request code: " + requestCode);
return;
}
if (resultCode != RESULT_OK) {
Log.e(TAG, "Screen capture request not granted: " + requestCode);
shareScreen();
return;
}
mMediaProjectionCallback = new MediaProjectionCallback();
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
mMediaProjection.registerCallback(mMediaProjectionCallback, null);
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
private class MediaProjectionCallback extends MediaProjection.Callback {
@Override
public void onStop() {
mMediaRecorder.stop();
mMediaRecorder.reset();
Log.v(TAG, "Recording Stopped");
mMediaProjection = null;
stopScreenSharing();
}
}
private void stopScreenSharing() {
Log.v(TAG, "Stop Screen sharing");
if (mVirtualDisplay == null) {
return;
}
mVirtualDisplay.release();
//mMediaRecorder.release(); //If used: mMediaRecorder object cannot
// be reused again
destroyMediaProjection();
}
private void destroyMediaProjection() {
if (mMediaProjection != null) {
mMediaProjection.unregisterCallback(mMediaProjectionCallback);
mMediaProjection.stop();
mMediaProjection = null;
}
Log.i(TAG, "MediaProjection Stopped");
}
private VirtualDisplay createVirtualDisplay() {
return mMediaProjection.createVirtualDisplay("MainActivity",
DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null /*Callbacks*/, null
/*Handler*/);
}
}
Upvotes: 0
Views: 277
Reputation: 1752
You are missing your if
statement around the code in your onStop()
function.
@Override
public void onStop() {
if (mToggleButton.isChecked()) {
mToggleButton.setChecked(false);
mMediaRecorder.stop();
mMediaRecorder.reset();
Log.v(TAG, "Recording Stopped");
}
mMediaProjection = null;
stopScreenSharing();
}
This isn't the issue, but needed to be pointed out.
The issue is in your run()
statement.
I'm not sure what you are trying to accomplish in this method, as it isn't in the tutorial.
@Override
public void run() {
Log.i(TAG, "Timer went off!");
stopScreenSharing();
}
That method is calling stopScreenSharing(). Which makes it appear that your recording has stopped, but it doesn't stop writing to your file or call the onStop()
method. So it keeps filling the file.
Upvotes: 1