HBiSoft / HBRecorder

Lightweight screen recording Android library
MIT License
423 stars 141 forks source link

Android 14 (SDK 34 ) Foreground service is not working #174

Closed arunm1407 closed 1 month ago

arunm1407 commented 2 months ago

Hi Team,

In Android 14 foreground service is crashing due to security exceptions

Caused by: java.lang.SecurityException: Starting FGS with type mediaProjection callerApp=ProcessRecord targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION] any of the permissions allOf=false [android.permission.CAPTURE_VIDEO_OUTPUT, android:project_media]

reference Issue https://stackoverflow.com/questions/77307867/screen-capture-mediaprojection-on-android-14

HBiSoft commented 2 months ago

What version are you using?

Can you reproduce it in the demo app?

What device are you using?


In the demo application we do have what you are referring to: https://github.com/HBiSoft/HBRecorder/blob/e642185b2fc40f454d72dcf3bd45340801248a88/app/src/main/AndroidManifest.xml#L8

arunm1407 commented 2 months ago

I've cloned you App and run on my machine,still facing the same.. you code handling seems correct, but still some additonal cases need to handled

I've used samsung S21 FE Android 14 HBRecorder : Version 1.0

please find the demo video for the same

https://github.com/user-attachments/assets/597c466d-718a-4608-aff8-a98e51d1d907

HBiSoft commented 2 months ago

HBRecorder : Version 1.0

Please use the latest version:

dependencies {
    implementation 'com.github.HBiSoft:HBRecorder:3.0.6'
}

A lot has happened since version 1.0 which was released in August 2019.


Edit: You can try the latest demo application here: https://github.com/HBiSoft/HBRecorder/releases/download/3.0.6/HBRecorderDemo.apk

arunm1407 commented 2 months ago

HBISoft, I have just pulled you latest changes & runned the build in machine and verified the same in your provided APK https://github.com/HBiSoft/HBRecorder/releases/download/3.0.6/HBRecorderDemo.apk

Issue is still reproducing.. can you look into this

arunm1407 commented 1 month ago

Hi HBISoft,

Do you have any updates regarding this issue?

HBiSoft commented 1 month ago

@arunm1406 Since I can't reproduce it on my end, for some reason, can you test by changing setOnClickListeners() and onRequestPermissionsResult() in the MainActivity of the demo application:

setOnClickListeners() :

private static final int PERMISSION_REQ_ID_FOREGROUND_SERVICE_MEDIA_PROJECTION = PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE + 1;

private void setOnClickListeners() {
    startbtn.setOnClickListener(v -> {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // first check if permissions were granted
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // SDK 34
                if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS, PERMISSION_REQ_POST_NOTIFICATIONS)
                        && checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO)
                        && checkSelfPermission(Manifest.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION, PERMISSION_REQ_ID_FOREGROUND_SERVICE_MEDIA_PROJECTION)) {
                    hasPermissions = true;
                }
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // SDK 33
                if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS, PERMISSION_REQ_POST_NOTIFICATIONS)
                        && checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO)) {
                    hasPermissions = true;
                }
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                if (checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO)) {
                    hasPermissions = true;
                }
            } else {
                if (checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO)
                        && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE)) {
                    hasPermissions = true;
                }
            }

            if (hasPermissions) {
                // check if recording is in progress and stop it if it is
                if (hbRecorder.isBusyRecording()) {
                    hbRecorder.stopScreenRecording();
                    startbtn.setText(R.string.start_recording);
                } else {
                    // else start recording
                    startRecordingScreen();
                }
            }
        } else {
            showLongToast("This library requires API 21>");
        }
    });
}

onRequestPermissionsResult() :

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case PERMISSION_REQ_POST_NOTIFICATIONS:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    checkSelfPermission(Manifest.permission.RECORD_AUDIO, PERMISSION_REQ_ID_RECORD_AUDIO);
                } else {
                    hasPermissions = false;
                    showLongToast("No permission for " + Manifest.permission.POST_NOTIFICATIONS);
                }
                break;
            case PERMISSION_REQ_ID_RECORD_AUDIO:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE);
                } else {
                    hasPermissions = false;
                    showLongToast("No permission for " + Manifest.permission.RECORD_AUDIO);
                }
                break;
            case PERMISSION_REQ_ID_WRITE_EXTERNAL_STORAGE:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    hasPermissions = true;
                    startRecordingScreen();
                } else {
                    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        checkSelfPermission(Manifest.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION, PERMISSION_REQ_ID_FOREGROUND_SERVICE_MEDIA_PROJECTION);
                    } else {
                        hasPermissions = false;
                        showLongToast("No permission for " + Manifest.permission.WRITE_EXTERNAL_STORAGE);
                    }
                }
                break;
            case PERMISSION_REQ_ID_FOREGROUND_SERVICE_MEDIA_PROJECTION:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    hasPermissions = true;
                    startRecordingScreen();
                } else {
                    hasPermissions = false;
                    showLongToast("No permission for " + Manifest.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION);
                }
                break;
            default:
                break;
        }
    }
HBiSoft commented 1 month ago

Please let me know if you have tried the above so that I can implement it into the library.

HBiSoft commented 1 month ago

I assume this is fixed in 3.0.7