Cómo grabar Android Screen Video programáticamente en KitKat 4.4

Sé que esta pregunta se ha hecho tantas veces y que hay tantas preguntas, respuestas y discusiones disponibles. Pero no sé qué hacer y qué no hacer.

Ya he referido esto debajo de todos los enlaces para obtener una solución sin suerte.

https://stackoverflow.com/questions/23438767/how-to-record-video-on-kitkat-4-4
https://stackoverflow.com/questions/23185125/i-cannot-screen-record-with-my-kitkat-4-4-moto-x
Android KitKat start screenrecord desde la aplicación
Grabador de pantalla con kitkat
Kit de grabación de pantalla con botón

Con mucha búsqueda no obtuve ningún ejemplo simple para lograr esta tarea. Desde 2 días estoy tratando de lograr esto pero sin éxito.

Entonces la pregunta simple es si es posible grabar un video de nuestra propia pantalla en Android. Acabo de enterarme de que es posible con Android 4.4 Kitkat y también verifico alguna aplicación del mercado.

Sé que para hacer esto nuestro dispositivo debe ser rooteado y otras cosas que requieren para hacer esto.

Pero no estoy obteniendo cómo desarrollar esto programáticamente. Si alguien tiene alguna idea, por favor, guíame sobre cómo hacer esto. o cualquier ejemplo o código será de gran ayuda.

Aprecio tu tipo de ayuda.

Intento desarrollarme con esta simple pieza de código pero sin obtener nada

public void startRecording(View v) { File recordfolder = Environment.getExternalStorageDirectory(); String record = "su — bit rate 8000000 --time-limit 30 " + recordfolder + "Record.mp4"; recordfolder.mkdir(); try { Process screenrecording = Runtime.getRuntime().exec(record); } catch (IOException e) { e.printStackTrace(); } } 

así que, básicamente, no sé lo que tengo que hacer con este Process screenrecording , me refiero a cómo puedo comenzar el progreso.

Buena pregunta, pero la respuesta depende del tipo de plataforma que desee utilizar para grabar la pantalla en Android.

Aquí hay algunos trucos …..

1) Usando esta clase puedes grabar la pantalla fuerte que requieres rooteado. Puedes probar esto en genymotion 4.4 también.

 public static class MainFragment extends Fragment { private Context mContext; private EditText mWidthEditText; private EditText mHeightEditText; private EditText mBitrateEditText; private EditText mTimeEditText; private Button mRecordButton; public MainFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); mContext = getActivity(); mRecordButton = (Button) rootView.findViewById(R.id.btn_record); mRecordButton.setOnClickListener(RecordOnClickListener); mWidthEditText = (EditText) rootView.findViewById(R.id.et_width); mHeightEditText = (EditText) rootView.findViewById(R.id.et_height); mBitrateEditText = (EditText) rootView .findViewById(R.id.et_bitrate); mBitrateEditText.addTextChangedListener(BitrateTextWatcher); mTimeEditText = (EditText) rootView.findViewById(R.id.et_time); mTimeEditText.addTextChangedListener(TimeTextWatcher); return rootView; } private TextWatcher BitrateTextWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { // Not used. } @Override public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { if (TextUtils.isEmpty(charSequence)) { return; } int value = Integer.valueOf(charSequence.toString()); if (value > 50 || value == 0) { mBitrateEditText.setError(mContext .getString(R.string.error_bitrate_edittext)); return; } mTimeEditText.setError(null); } @Override public void afterTextChanged(Editable editable) { // Not used. } }; private TextWatcher TimeTextWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { // Not used. } @Override public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { if (TextUtils.isEmpty(charSequence)) { return; } int value = Integer.valueOf(charSequence.toString()); if (value > 180 || value == 0) { mTimeEditText.setError(mContext .getString(R.string.error_time_editext)); return; } mTimeEditText.setError(null); } @Override public void afterTextChanged(Editable editable) { // Not used. } }; private View.OnClickListener RecordOnClickListener = new View.OnClickListener() { @Override public void onClick(View view) { if (!TextUtils.isEmpty(mTimeEditText.getError()) || !TextUtils.isEmpty(mBitrateEditText.getError())) { Toast.makeText(mContext, mContext.getString(R.string.toast_invalid_values), Toast.LENGTH_LONG).show(); return; } boolean widthSet = !TextUtils.isEmpty(mWidthEditText.getText()); boolean heightSet = !TextUtils.isEmpty(mHeightEditText .getText()); if ((!widthSet && heightSet) || (widthSet && !heightSet)) { Toast.makeText(mContext, mContext.getString(R.string.error_invalid_wxh), Toast.LENGTH_LONG).show(); return; } boolean bitrateSet = !TextUtils.isEmpty(mBitrateEditText .getText()); boolean timeSet = !TextUtils.isEmpty(mTimeEditText.getText()); StringBuilder stringBuilder = new StringBuilder( "/system/bin/screenrecord"); if (widthSet) { stringBuilder.append(" --size ") .append(mWidthEditText.getText()).append("x") .append(mHeightEditText.getText()); } if (bitrateSet) { stringBuilder.append(" --bit-rate ").append( mBitrateEditText.getText()); } if (timeSet) { stringBuilder.append(" --time-limit ").append( mTimeEditText.getText()); } // TODO User definable location. stringBuilder .append(" ") .append(Environment.getExternalStorageDirectory() .toString()).append("/recording.mp4"); Log.d("TAG", "comamnd: " + stringBuilder.toString()); try { new SuTask(stringBuilder.toString().getBytes("ASCII")) .execute(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }; private class SuTask extends AsyncTask { private final byte[] mCommand; public SuTask(byte[] command) { super(); this.mCommand = command; } @Override protected Boolean doInBackground(Boolean... booleans) { try { Process sh = Runtime.getRuntime().exec("su", null, null); OutputStream outputStream = sh.getOutputStream(); outputStream.write(mCommand); outputStream.flush(); outputStream.close(); final NotificationManager notificationManager = (NotificationManager) mContext .getSystemService(NOTIFICATION_SERVICE); notificationManager.notify(RUNNING_NOTIFICATION_ID, createRunningNotification(mContext)); sh.waitFor(); return true; } catch (InterruptedException e) { e.printStackTrace(); Toast.makeText(mContext, mContext.getString(R.string.error_start_recording), Toast.LENGTH_LONG).show(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(mContext, mContext.getString(R.string.error_start_recording), Toast.LENGTH_LONG).show(); } return false; } @Override protected void onPostExecute(Boolean bool) { super.onPostExecute(bool); if (bool) { final NotificationManager notificationManager = (NotificationManager) mContext .getSystemService(NOTIFICATION_SERVICE); notificationManager.cancel(RUNNING_NOTIFICATION_ID); File file = new File(Environment .getExternalStorageDirectory().toString() + "/recording.mp4"); notificationManager.notify(FINISHED_NOTIFICATION_ID, createFinishedNotification(mContext, file)); } } private Notification createRunningNotification(Context context) { Notification.Builder mBuilder = new Notification.Builder( context) .setSmallIcon(android.R.drawable.stat_notify_sdcard) .setContentTitle( context.getResources().getString( R.string.app_name)) .setContentText("Recording Running") .setTicker("Recording Running") .setPriority(Integer.MAX_VALUE).setOngoing(true); return mBuilder.build(); } private Notification createFinishedNotification(Context context, File file) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "video/mp4"); PendingIntent pendingIntent = PendingIntent.getActivity( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); Notification.Builder mBuilder = new Notification.Builder( context) .setSmallIcon(android.R.drawable.stat_notify_sdcard) .setContentTitle( context.getResources().getString( R.string.app_name)) .setContentText("Recording Finished") .setTicker("Recording Finished") .setContentIntent(pendingIntent).setOngoing(false) .setAutoCancel(true); return mBuilder.build(); } } } 

2) Puede capturar las capturas de pantalla y hacer el video desde allí y funcionará para los dispositivos 3.0+. Y para convertir las imágenes a video puede usar FFMPEG o JavaCV.

Para dispositivos rooteados (en eso también puedes capturar la pantalla del teclado)

 if (Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState())) { // we check if external storage is\ available, otherwise // display an error message to the user using Toast Message File sdCard = Environment.getExternalStorageDirectory(); File directory = new File(sdCard.getAbsolutePath() + "/ScreenShots"); directory.mkdirs(); String filename = "screenshot_jpeg_" + i + ".png"; File yourFile = new File(directory, filename); try { Process sh = Runtime.getRuntime().exec("su", null, null); OutputStream os = sh.getOutputStream(); os.write(("/system/bin/screencap -p " + "/sdcard/ScreenShots/" + filename).getBytes("ASCII")); os.flush(); os.close(); sh.waitFor(); i++; } catch (Exception e) { e.printStackTrace(); } } 

Para sin dispositivos Rooteados (en que no se puede capturar la pantalla del teclado)

 if (Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState())) { // we check if external storage is\ available, otherwise // display an error message to the user using Toast Message File sdCard = Environment.getExternalStorageDirectory(); File directory = new File(sdCard.getAbsolutePath() + "/ScreenShots"); directory.mkdirs(); String filename = "screenshot_jpeg_" + i + ".png"; File yourFile = new File(directory, filename); try { Process sh = Runtime.getRuntime().exec("su", null, null); OutputStream os = sh.getOutputStream(); os.write(("/system/bin/screencap -p " + "/sdcard/ScreenShots/" + filename).getBytes("ASCII")); os.flush(); os.close(); sh.waitFor(); i++; } catch (Exception e) { e.printStackTrace(); } }