From 48b9084c040cccf894565884f6eb26b0ed2a0bc2 Mon Sep 17 00:00:00 2001 From: Vicky Daniel Date: Tue, 31 Jul 2018 22:59:31 +0530 Subject: [PATCH 1/4] permissions --- .idea/caches/build_file_checksums.ser | Bin 543 -> 533 bytes .idea/vcs.xml | 6 + app/build.gradle | 7 +- app/src/main/AndroidManifest.xml | 2 + .../x11screenrecorder/MainActivity.java | 116 ++++++++++++++++++ app/src/main/res/layout/activity_main.xml | 35 ++++-- 6 files changed, 153 insertions(+), 13 deletions(-) create mode 100644 .idea/vcs.xml diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 753c0550bbf7d7ebe20547485f20ce879fafdab3..08687031a87e72879d3be4d706e36ab64fe7a801 100644 GIT binary patch delta 87 zcmV-d0I2_;1eFAkm;~`tW_gjEu?7%qZ)0I>lW_qR9b^F~{j7jyOKtgs{F9B!B6I*G tFKBOVWiMfJZf}!f0X6{j^5w|YbaXm4$0FLP;ZX=870V|8$2VQXcRg#k8`O#vGd wZ=#cDKWOE@SkREn>K2gzbN~^PjsY8!*8wdN + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 3681459..393523c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + compileSdkVersion 27 defaultConfig { applicationId "com.deltaforce.siliconcupcake.x11screenrecorder" minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 27 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -20,9 +20,10 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:28.0.0-beta01' + implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' + implementation 'com.android.support:design:27.1.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ab170d1..cdf2da8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,8 @@ + + 0) && (grantResults[0] + + grantResults[1]) == PackageManager.PERMISSION_GRANTED) { + + } else { + toggleButton.setChecked(false); + Snackbar.make(findViewById(android.R.id.content), "PERMIT", + Snackbar.LENGTH_INDEFINITE).setAction("ENABLE", + new View.OnClickListener() { + @Override + public void onClick(View v) { + ActivityCompat.requestPermissions(MainActivity.this, + new String[]{Manifest.permission + .WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, + REQUEST_PERMISSIONS); + } + }).show(); + } + return; + } + } + } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 84f1951..eddd65d 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,18 +1,33 @@ - - - \ No newline at end of file + + + + + + + \ No newline at end of file From 273d1f8360dcb612e63b93b4f0117e4ffd9e570c Mon Sep 17 00:00:00 2001 From: Vicky Daniel Date: Thu, 2 Aug 2018 23:43:39 +0530 Subject: [PATCH 2/4] recording fix --- app/src/main/AndroidManifest.xml | 2 + .../x11screenrecorder/Function.java | 19 ++ .../x11screenrecorder/MainActivity.java | 223 ++++++++++++++---- 3 files changed, 194 insertions(+), 50 deletions(-) create mode 100644 app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/Function.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cdf2da8..4646ef3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + = Build.VERSION_CODES.M && context != null && permissions != null) { + for (String permission : permissions) { + if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { + return false; + } + } + } + return true; + } +} diff --git a/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java b/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java index 34a0fd0..95d21fb 100644 --- a/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java +++ b/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java @@ -4,13 +4,16 @@ import android.content.Context; 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.Environment; import android.provider.Settings; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; @@ -21,23 +24,26 @@ import android.util.SparseIntArray; import android.view.Surface; import android.view.View; +import android.widget.Toast; import android.widget.ToggleButton; -public class MainActivity extends AppCompatActivity { +import java.io.IOException; +public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final int REQUEST_CODE = 1000; + public ToggleButton toggleButton; + public boolean isRecording = false; private int mScreenDensity; - private MediaProjectionManager mProjectionManager; + private MediaProjectionManager mProjectionManager;//manages MediaProjection objects; private static final int DISPLAY_WIDTH = 720; private static final int DISPLAY_HEIGHT = 1280; - private MediaProjection mMediaProjection; + private MediaProjection mMediaProjection;//token grants ability to capture screen content; private VirtualDisplay mVirtualDisplay; private MediaProjectionCallback mMediaProjectionCallback; private MediaRecorder mMediaRecorder; private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); - private static final int REQUEST_PERMISSIONS = 10; - private ToggleButton toggleButton; + private static final int REQUEST_PERMISSION_KEY = 1; static { ORIENTATIONS.append(Surface.ROTATION_0, 90); @@ -46,84 +52,201 @@ public class MainActivity extends AppCompatActivity { ORIENTATIONS.append(Surface.ROTATION_270, 180); } + @Override - protected void onCreate(Bundle savedInstanceState) { + protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - toggleButton = (ToggleButton) findViewById(R.id.toggleButton); + String[] PERMISSIONS = { + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE + }; + Log.d("permission one", PERMISSIONS[0]); + Log.d("permission two", PERMISSIONS[1]); + if (!Function.hasPermissions(this, PERMISSIONS)) { + ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_KEY); + + + } DisplayMetrics metrics = new DisplayMetrics(); - Log.d("value of metrics", String.valueOf(metrics)); getWindowManager().getDefaultDisplay().getMetrics(metrics); - Log.d("value of metrics", String.valueOf(metrics)); mScreenDensity = metrics.densityDpi; mMediaRecorder = new MediaRecorder(); mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); + toggleButton = (ToggleButton) findViewById(R.id.toggleButton); toggleButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - if (ContextCompat.checkSelfPermission(MainActivity.this, - Manifest.permission.WRITE_EXTERNAL_STORAGE) + ContextCompat - .checkSelfPermission(MainActivity.this, - Manifest.permission.RECORD_AUDIO) - != PackageManager.PERMISSION_GRANTED) { - if (ActivityCompat.shouldShowRequestPermissionRationale - (MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) || - ActivityCompat.shouldShowRequestPermissionRationale - (MainActivity.this, Manifest.permission.RECORD_AUDIO)) { - toggleButton.setChecked(false); - Snackbar.make(findViewById(android.R.id.content), "PERMIT", - Snackbar.LENGTH_INDEFINITE).setAction("ENABLE", - new View.OnClickListener() { - @Override - public void onClick(View v) { - ActivityCompat.requestPermissions(MainActivity.this, - new String[]{Manifest.permission - .WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, - REQUEST_PERMISSIONS); - } - }).show(); - } else { - ActivityCompat.requestPermissions(MainActivity.this, - new String[]{Manifest.permission - .WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, - REQUEST_PERMISSIONS); - } - } else { - } - } + onToggleScreenShare(); + } }); + + } + + public void onToggleScreenShare() { + + + if (!isRecording) { + initRecorder(); + shareScreen(); + } else { + mMediaRecorder.stop(); + mMediaRecorder.reset(); + stopScreenSharing(); + } + + + } + + + private void initRecorder() { + try { + + mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); + mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //THREE_GPP + mMediaRecorder.setOutputFile(Environment + .getExternalStoragePublicDirectory(Environment + .DIRECTORY_DOWNLOADS) + "/video.mp4"); + mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT); + mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); + mMediaRecorder.setVideoEncodingBitRate(512 * 1000); + mMediaRecorder.setVideoFrameRate(16); // 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 shareScreen() { + if (mMediaProjection == null) { + startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE); + return; + } + mVirtualDisplay = createVirtualDisplay(); + mMediaRecorder.start(); + isRecording = true; + } + + @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; + toggleButton.setChecked(false); + return; + } + mMediaProjectionCallback = new MediaProjectionCallback(); + mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); + mMediaProjection.registerCallback(mMediaProjectionCallback, null); + mVirtualDisplay = createVirtualDisplay(); + mMediaRecorder.start(); + isRecording = true; + toggleButton.setChecked(true); + } + + private VirtualDisplay createVirtualDisplay() { + return mMediaProjection.createVirtualDisplay("MainActivity", DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity, + DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder.getSurface(), null, null); + } + + + private void stopScreenSharing() { + if (mVirtualDisplay == null) { + return; + } + mVirtualDisplay.release(); + destroyMediaProjection(); + isRecording = false; + toggleButton.setChecked(false); + } + + private void destroyMediaProjection() { + if (mMediaProjection != null) { + mMediaProjection.unregisterCallback(mMediaProjectionCallback); + mMediaProjection.stop(); + mMediaProjection = null; + } + Log.i(TAG, "MediaProjection Stopped"); } - private class MediaProjectionCallback { + private class MediaProjectionCallback extends MediaProjection.Callback { + @Override + public void onStop() { + if (isRecording) { + isRecording = false; + toggleButton.setChecked(false); + mMediaRecorder.stop(); + mMediaRecorder.reset(); + } + mMediaProjection = null; + stopScreenSharing(); + } } @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + 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(); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { switch (requestCode) { - case REQUEST_PERMISSIONS: { - if ((grantResults.length > 0) && (grantResults[0] + - grantResults[1]) == PackageManager.PERMISSION_GRANTED) { + case REQUEST_PERMISSION_KEY: { + if ((grantResults.length > 0) && (grantResults[0] + grantResults[1]) == PackageManager.PERMISSION_GRANTED) { } else { + isRecording = false; toggleButton.setChecked(false); - Snackbar.make(findViewById(android.R.id.content), "PERMIT", + 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) { - ActivityCompat.requestPermissions(MainActivity.this, - new String[]{Manifest.permission - .WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, - REQUEST_PERMISSIONS); + 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; } } - } } From c68481ea2fc16ebf8285e516bb32f055e3167bb4 Mon Sep 17 00:00:00 2001 From: Vicky Daniel Date: Fri, 3 Aug 2018 21:04:28 +0530 Subject: [PATCH 3/4] audio and video recording --- .../x11screenrecorder/MainActivity.java | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java b/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java index 95d21fb..5e5c323 100644 --- a/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java +++ b/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java @@ -3,6 +3,7 @@ import android.Manifest; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; @@ -41,9 +42,10 @@ public class MainActivity extends AppCompatActivity { private MediaProjection mMediaProjection;//token grants ability to capture screen content; private VirtualDisplay mVirtualDisplay; private MediaProjectionCallback mMediaProjectionCallback; - private MediaRecorder mMediaRecorder; + public MediaRecorder mMediaRecorder; private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); private static final int REQUEST_PERMISSION_KEY = 1; + private int counter = 0; static { ORIENTATIONS.append(Surface.ROTATION_0, 90); @@ -57,17 +59,19 @@ public class MainActivity extends AppCompatActivity { protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - String[] PERMISSIONS = { + SharedPreferences prefs = getSharedPreferences("MyPref", MODE_PRIVATE); + counter = prefs.getInt("counter" , 0); + final String[] PERMISSIONS = { Manifest.permission.WRITE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.RECORD_AUDIO }; - Log.d("permission one", PERMISSIONS[0]); - Log.d("permission two", PERMISSIONS[1]); - if (!Function.hasPermissions(this, PERMISSIONS)) { - ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_KEY); - - + Log.d("write permission", PERMISSIONS[0]); + Log.d("read permission", PERMISSIONS[1]); + if (!Function.hasPermissions(MainActivity.this, PERMISSIONS)) { + ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS, REQUEST_PERMISSION_KEY); } + DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); mScreenDensity = metrics.densityDpi; @@ -78,8 +82,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { @Override public void onClick(View view) { + onToggleScreenShare(); + } }); @@ -104,14 +110,20 @@ public void onToggleScreenShare() { private void initRecorder() { try { - + mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //THREE_GPP mMediaRecorder.setOutputFile(Environment .getExternalStoragePublicDirectory(Environment - .DIRECTORY_DOWNLOADS) + "/video.mp4"); + .DIRECTORY_DOWNLOADS) + "/video"+String.valueOf(counter)+".mp4"); + counter++; + SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE); + SharedPreferences.Editor editor = pref.edit(); + editor.putInt("counter" , counter); + editor.commit(); mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); + mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mMediaRecorder.setVideoEncodingBitRate(512 * 1000); mMediaRecorder.setVideoFrameRate(16); // 30 mMediaRecorder.setVideoEncodingBitRate(3000000); @@ -126,7 +138,7 @@ private void initRecorder() { private void shareScreen() { if (mMediaProjection == null) { - startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE); + startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);//permission to record screen! return; } mVirtualDisplay = createVirtualDisplay(); @@ -144,8 +156,10 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { Toast.makeText(this, "Screen Cast Permission Denied", Toast.LENGTH_SHORT).show(); isRecording = false; toggleButton.setChecked(false); + mMediaRecorder = new MediaRecorder(); return; } + Log.d("REQUEST_CODE", String.valueOf(REQUEST_CODE)); mMediaProjectionCallback = new MediaProjectionCallback(); mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); mMediaProjection.registerCallback(mMediaProjectionCallback, null); @@ -225,6 +239,7 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String permissi switch (requestCode) { case REQUEST_PERMISSION_KEY: { if ((grantResults.length > 0) && (grantResults[0] + grantResults[1]) == PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, "Screen Cast Permission Granted", Toast.LENGTH_SHORT).show(); } else { isRecording = false; From fdfeef7beb7ff6eb35884b4210eb3693020e992c Mon Sep 17 00:00:00 2001 From: Vicky Daniel Date: Fri, 3 Aug 2018 21:24:17 +0530 Subject: [PATCH 4/4] recordlogic --- .../siliconcupcake/x11screenrecorder/MainActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java b/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java index 5e5c323..4cd69c9 100644 --- a/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java +++ b/app/src/main/java/com/deltaforce/siliconcupcake/x11screenrecorder/MainActivity.java @@ -132,7 +132,7 @@ private void initRecorder() { mMediaRecorder.setOrientationHint(orientation); mMediaRecorder.prepare(); } catch (IOException e) { - e.printStackTrace(); + e.printStackTrace(); } }