17

I know this question has been asked so many times and there are so many questions, answers and discussions available. But I don't know what to do and what not to do.

I already referred to the links below to get solution with no luck.

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 from App
screen recorder with kitkat
Screen Recording kitkat with button

With lots of search I didn't get any simple example to achieve this task. Since 2 days i am trying to achieve this but with no success.

So the simple question is whether it is possible to record video of our own screen in android. I just heard that it is possible from android 4.4 Kitkat and i also check some app from market.

I know to do this our device should be rooted and other things which required to do this.

But I am not getting how to develop this programmatically. If any one have any idea then please guide me how to do this. or any example or code will be great help.

I appreciate your any kind of help.

I try to develop with this simple piece of code but not getting anything

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();
        }
    }

so basically I don't know what i have to do with this Process screenrecording, I mean how can I start progress.

Nikolay Dimitrov
  • 1,766
  • 1
  • 14
  • 23
user3660803
  • 315
  • 1
  • 3
  • 15

1 Answers1

9

Good Question But the answer depends on what type of platform you want to use to record the screen in android.

Here are some tricks.....

1) Using this class you can record the screen fort that you required rooted device you can test this in genymotion 4.4 also.

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<Boolean, Void, Boolean> {
        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) You can capture the screen shots and make the video from it and it will work for the 3.0+ devices And for converting the images to video you can use FFMPEG or JavaCV.

-For Rooted devices(in that you can capture the keyboard screen also)

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();
        }
    }

-For without Rooted devices(in that you can not capture the keyboard screen)

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();
        }
    }
Smit Patel
  • 1,174
  • 3
  • 26
  • 40
  • 2
    Your code for with and without root are identical. Did you mean to call `su` in the last example? – emkman Sep 18 '14 at 22:27
  • @emkman Yes you have to give the su permission for the rooted devices. – Smit Patel Sep 19 '14 at 04:48
  • 1
    Yes but what about the unrooted device (no keyboard). Your two examples are identical. – emkman Sep 25 '14 at 04:51
  • 1
    The first set of code works for me using genymotion 4.4 Please also note to change the external storage path to /mnt/shell/emulated/0 instead of using Environment.getExternalStorage() when testing it with genymotion 4.4 or a rooted 4.4 device emulator Check this answer for more details on the directory path change http://stackoverflow.com/a/20734816/2644384 – uncannyj Dec 04 '14 at 04:17
  • @uncannyj Thanks you can up vote the answer if you got helped. – Smit Patel Dec 05 '14 at 03:43
  • @SmitPatel it seems that you can't screenrecord using any emulator. I wasn't able to use genymotion to record but I was able to produce a .mp4 file so when I tested it with a rooted 4.4 android phone it worked well based on your code 1. Thanks! – uncannyj Dec 05 '14 at 09:59
  • @SmitPatel how do I prematurely end the screen recording? – Jayson Tamayo Feb 04 '15 at 02:40
  • @JaysonTamayo which of the method from above are you using? – Smit Patel Feb 04 '15 at 05:12
  • @SmitPatel For the rooted device. using the method native to android 4.4 – Jayson Tamayo Feb 04 '15 at 09:16
  • @SmitPatel After I click the button (where i put your code). A notification says running then evntually it says 'finished'. When I click the notification it says 'Cant play the video'. What's happening? – Jayson Tamayo Feb 04 '15 at 10:53
  • @uncannyj Can you help me with my problem? – Jayson Tamayo Feb 04 '15 at 10:53
  • @JaysonTamayo please manually follow first to the PATH and check the video is there or not then pass that link in the method of that particular PATH. – Smit Patel Feb 06 '15 at 09:32
  • @SmitPatel your example for without rooted the same for rooted – Nguyen Thanh An Jul 24 '15 at 04:54
  • @NguyenThanhAn the only difference is you can not capture the keyboard screen for without rooted devices – Smit Patel Jul 24 '15 at 06:27
  • 1
    @SmitPatel : I found exception on device without root : null inviroment in line : "Process sh = Runtime.getRuntime().exec("su", null, null);" – Nguyen Thanh An Jul 28 '15 at 03:38
  • @NguyenThanhAn I also got the IOException on non-rooted device in "Process sh = Runtime.getRuntime().exec("su", null, null);". Any idea how to solve this? – Taha Rushain Mar 13 '17 at 18:58