Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mediaprojection issues on Android 9+

I made an OCR application that makes a screenshot using Android mediaprojection and processes the text in this image. This is working fine, except on Android 9+. When mediaprojeciton is starting there is always a window popping up warning about sensitive data that could be recorded, and a button to cancel or start recording. How can I achieve that this window will only be showed once?

I tried preventing it from popping up by creating two extra private static variables to store intent and resultdata of mediaprojection, and reusing it if its not null. But it did not work (read about this method in another post).

popup window

// initializing MP

  mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);

// Starting MediaProjection

 private void startProjection() {
     startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
 }


// OnActivityResult
 protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {

    if (requestCode == 100) {
        if(mProjectionManager == null) {
            cancelEverything();
            return;
        }

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {

                if(mProjectionManager != null)
                sMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
                else
                    cancelEverything();
                if (sMediaProjection != null) {
                    File externalFilesDir = getExternalFilesDir(null);
                    if (externalFilesDir != null) {
                        STORE_DIRECTORY = externalFilesDir.getAbsolutePath() + "/screenshots/";

                        File storeDirectory = new File(STORE_DIRECTORY);
                        if (!storeDirectory.exists()) {
                            boolean success = storeDirectory.mkdirs();
                            if (!success) {
                                Log.e(TAG, "failed to create file storage directory.");
                                return;
                            }
                        }
                    } else {
                        Log.e(TAG, "failed to create file storage directory, getExternalFilesDir is null.");
                        return;
                    }

                    // display metrics
                    DisplayMetrics metrics = getResources().getDisplayMetrics();
                    mDensity = metrics.densityDpi;
                    mDisplay = getWindowManager().getDefaultDisplay();

                    // create virtual display depending on device width / height
                    createVirtualDisplay();

                    // register orientation change callback
                    mOrientationChangeCallback = new OrientationChangeCallback(getApplicationContext());
                    if (mOrientationChangeCallback.canDetectOrientation()) {
                        mOrientationChangeCallback.enable();
                    }

                    // register media projection stop callback
                    sMediaProjection.registerCallback(new MediaProjectionStopCallback(), mHandler);
                }



            }
        }, 2000);


        }

}

My code is working fine on Android versions below Android 9. On older android versions I can choose to keep that decision to grant recording permission, and it will never show up again. So what can I do in Android 9?

Thanks in advance, I'm happy for every idea you have :)

like image 882
Mori Ruec Avatar asked Jul 09 '19 02:07

Mori Ruec


1 Answers

Well the problem was that I was calling startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE); every time, which is not necessary (createScreenCaptureIntent() leads to the dialog window which requests user interaction) My solution makes the dialog appear only once (if application was closed it will ask for permission one time again). All I had to do was making addiotional private static variables of type Intent and int.

private static Intent staticIntentData; private static int staticResultCode;

On Activity result I assign those variables with the passed result code and intent:

if(staticResultCode == 0 && staticIntentData == null) {
    sMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
    staticIntentData = data;
    staticResultCode = resultCode;
} else {
    sMediaProjection = mProjectionManager.getMediaProjection(staticResultCode, staticIntentData)};
}

Every time I call my startprojection method, I will check if they are null:

if(staticIntentData == null) startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE); else captureScreen();

If null it will request permission, if not it will start the projection with the static intent data and static int resultcode, so it is not needed to ask for that permission again, just reuse what you get in activity result.

sMediaProjection = mProjectionManager.getMediaProjection(staticResultCode, staticIntentData);

Simple as that! Now it will only showing one single time each time you use the app. I guess thats what Google wants, because theres no keep decision checkbox in that dialog like in previous android versions.

like image 169
Mori Ruec Avatar answered Nov 19 '22 03:11

Mori Ruec