Created
December 12, 2016 12:36
-
-
Save uziassantosferreira/af2eb26d57f40413e11871c741abb4d3 to your computer and use it in GitHub Desktop.
Screen Recording in service android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MediaRecorderHelper { | |
private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90; | |
private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270; | |
private static final SparseIntArray DEFAULT_ORIENTATIONS = new SparseIntArray(); | |
private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray(); | |
static { | |
DEFAULT_ORIENTATIONS.append(Surface.ROTATION_0, 90); | |
DEFAULT_ORIENTATIONS.append(Surface.ROTATION_90, 0); | |
DEFAULT_ORIENTATIONS.append(Surface.ROTATION_180, 270); | |
DEFAULT_ORIENTATIONS.append(Surface.ROTATION_270, 180); | |
} | |
static { | |
INVERSE_ORIENTATIONS.append(Surface.ROTATION_0, 270); | |
INVERSE_ORIENTATIONS.append(Surface.ROTATION_90, 180); | |
INVERSE_ORIENTATIONS.append(Surface.ROTATION_180, 90); | |
INVERSE_ORIENTATIONS.append(Surface.ROTATION_270, 0); | |
} | |
public static MediaRecorder configureRecorder(MediaRecorder mediaRecorder, WindowManager windowManager, int displayWidth, int displayHeight, boolean enableAudio, Integer sensorOrientation){ | |
if (enableAudio){ | |
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); | |
} | |
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); | |
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); | |
mediaRecorder.setOutputFile(FileUtils.createTempVideoFile()); | |
mediaRecorder.setVideoSize(displayWidth, displayHeight); | |
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); | |
if (enableAudio){ | |
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); | |
} | |
mediaRecorder.setVideoEncodingBitRate(10000000); | |
mediaRecorder.setVideoFrameRate(30); | |
int rotation = windowManager.getDefaultDisplay().getRotation(); | |
if (sensorOrientation != null){ | |
switch (sensorOrientation) { | |
case SENSOR_ORIENTATION_DEFAULT_DEGREES: | |
mediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation)); | |
break; | |
case SENSOR_ORIENTATION_INVERSE_DEGREES: | |
mediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation)); | |
break; | |
} | |
}else{ | |
int orientation = DEFAULT_ORIENTATIONS.get(rotation + 90); | |
mediaRecorder.setOrientationHint(orientation); | |
} | |
return mediaRecorder; | |
} | |
public static VirtualDisplay createVirtualDisplay(MediaProjection mediaProjection, MediaRecorder mediaRecorder, Context context, int displayWidth, int displayHeight, int density) { | |
return mediaProjection.createVirtualDisplay(context.getString(R.string.app_name), displayWidth, displayHeight, density, | |
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package br.com.testr.services; | |
import android.app.Service; | |
import android.content.Intent; | |
import android.hardware.display.VirtualDisplay; | |
import android.media.MediaRecorder; | |
import android.media.projection.MediaProjection; | |
import android.os.IBinder; | |
import android.support.annotation.Nullable; | |
import android.util.DisplayMetrics; | |
import android.view.WindowManager; | |
import java.io.IOException; | |
import br.com.testr.AppApplication; | |
import br.com.testr.helper.CameraHelper; | |
import br.com.testr.helper.MediaRecorderHelper; | |
import br.com.testr.helper.DraggableViewRecordingHelper; | |
/** | |
* Created by uzias on 10/3/16. | |
*/ | |
public class ScreenRecorderService extends Service { | |
private MediaProjection mediaProjection; | |
private VirtualDisplay virtualDisplay; | |
private MediaProjectionCallback mediaProjectionCallback; | |
private MediaRecorder mediaRecorder; | |
private int displayWidth; | |
private int mDisplayHeight; | |
private int mDensityDpi; | |
private WindowManager windowManager; | |
private DraggableViewRecordingHelper draggableViewRecordingHelper; | |
@Nullable | |
@Override | |
public IBinder onBind(Intent intent) { | |
return null; | |
} | |
@Override | |
public void onCreate() { | |
super.onCreate(); | |
mediaRecorder = new MediaRecorder(); | |
DisplayMetrics metrics = getResources().getDisplayMetrics(); | |
mDensityDpi = metrics.densityDpi; | |
displayWidth = metrics.widthPixels; | |
mDisplayHeight = metrics.heightPixels; | |
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); | |
draggableViewRecordingHelper = new DraggableViewRecordingHelper(this); | |
} | |
@Override | |
public int onStartCommand(Intent intent, int flags, int startId) { | |
initRecorder(); | |
return super.onStartCommand(intent, flags, startId); | |
} | |
@Override | |
public void onDestroy() { | |
super.onDestroy(); | |
stopRecorderAndScreen(); | |
} | |
private void initRecorder() { | |
try { | |
if (mediaProjectionCallback == null){ | |
mediaProjectionCallback = new MediaProjectionCallback(); | |
} | |
mediaProjection = AppApplication.mediaProjection; | |
if (mediaProjection == null){ | |
hideRecordingViewStopServicesShowError(); | |
return; | |
} | |
mediaProjection.registerCallback(mediaProjectionCallback, null); | |
mediaRecorder = MediaRecorderHelper.configureRecorder(mediaRecorder, windowManager, displayWidth, mDisplayHeight, false, null); | |
mediaRecorder.prepare(); | |
virtualDisplay = MediaRecorderHelper.createVirtualDisplay(mediaProjection, mediaRecorder, this, displayWidth, mDisplayHeight, mDensityDpi); | |
mediaRecorder.start(); | |
draggableViewRecordingHelper.showView(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
hideRecordingViewStopServicesShowError(); | |
} | |
} | |
private void destroyMediaProjection() { | |
if (mediaProjection != null) { | |
mediaProjection.unregisterCallback(mediaProjectionCallback); | |
mediaProjection.stop(); | |
mediaProjection = null; | |
} | |
} | |
private void stopRecorderAndScreen() { | |
try { | |
mediaRecorder.stop(); | |
}catch (Exception e){ | |
e.printStackTrace(); | |
hideRecordingViewStopServicesShowError(); | |
} | |
draggableViewRecordingHelper.hideView(); | |
mediaRecorder.reset(); | |
destroyMediaProjection(); | |
if (virtualDisplay != null) { | |
virtualDisplay.release(); | |
} | |
} | |
private void hideRecordingViewStopServicesShowError(){ | |
CameraHelper.hideRecordingViewStopServicesShowError(this); | |
} | |
private class MediaProjectionCallback extends MediaProjection.Callback { | |
@Override | |
public void onStop() { | |
stopRecorderAndScreen(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @uziassantosferreira !
I just found this whilst looking for one of the many useful things I hoped would be available with a rooted smartphone (android 13 s20)
is this a service that can be loaded early in the "bootup process", to record the screen(s) on the phone, either on device direct (if possible), and/or via windows machine (if required)?
Guessing from filename it does something similar, perhaps not at boot-time, not sure on intended or possible usage, eg if you need to write an app, or can "adb it", or other clever voodoo
Gist wondering 🙂