Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
vit.hlavacek's avatar
4 years ago
Solved

Problem with MediaProjection and permission dialog

Hi

Im new to oculus development (Oculus Quest 2) and im trying simple app for making screenshots and screen recording. But im having a problem with permission to retrieve MediaProjectionApi

I start activity for result, and the standard android dialog for permission shows but, but without allow/deny buttons, so im stuck.

MediaProjectionPermissionDialog

This is the dialog, sorry for the phone pic, but build in screenshot does not show this dialog.
Found simmilar issue here https://github.com/rom1v/sndcpy/issues/75 but no solution either.

My code for showing this dialog. This is in my MainActivity and the testMediaProjectionPermission method is call as onClickListener from a button.

 

ActivityResultLauncher<Intent> resultLauncher =  registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult> () {

@Override
public void onActivityResult(ActivityResult result) {
if(RESULT_OK == result.getResultCode()) {
Log.d(TAG, "Media projection permission granted");
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(result.getResultCode(), result.getData());
Log.d(TAG, "Successfully retrieved mediPerojeciton="+mediaProjection);

}
}
});

private void testMediaProjectionPermission(View view) {
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
resultLauncher.launch(mediaProjectionManager.createScreenCaptureIntent());
}

 

Any advice would be appriciated. Any kind of workaround or another option to record screen other then the build in caster.

  • Figured it out and i have when i hate a question and find bunch of same questions without an answer, so here it is. Hope it helps. 

    Propably a bug in oculus android flavor. This dialog does not work from regular activity, but works fine prom VR activity.

    So here is my part of android manifest. Notice the ScreenCaptureActivity, with the params, and meta-data inside of it (only for that one activity so it does not affect rest of my app), to launch it as VR / fullscreen.

     

     

     

    <meta-data android:name="com.oculus.supportedDevices" android:value="quest2"/>
    <activity android:name=".activity.MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity 
        android:name=".activity.ScreenCaptureActivity" 
        android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode" 
        android:launchMode="singleTask" 
        android:resizeableActivity="false" 
        android:screenOrientation="landscape" 
        android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" 
        android:noHistory="false" >
        <intent-filter>
            <action android:name="cz.test.app.SCREEN_CAPTURE" />
            <category android:name="com.oculus.intent.category.VR" />
        </intent-filter>
        <meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
    </activity>

     

     

     

    And code for my screencapture activity, its fairly simple as well. The main thing is the manifest and launching it as VR

     

     

     

    public class ScreenCaptureActivity extends ComponentActivity {
        public static final String TAG = "ScreenCaptureActivity";
        
        
         private final ActivityResultLauncher<Intent> resultLauncher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                new ActivityResultCallback<ActivityResult>() {
    
                    @Override
                    public void onActivityResult(ActivityResult result) {
                        Log.d(TAG, "resultLauncher onActivityResult");
                        if (RESULT_OK == result.getResultCode()) {
                            Log.d(TAG, "Media projection permission granted");
                            MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
                            MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(result.getResultCode(), result.getData());
                            Log.d(TAG, "Successfully retrieved mediPerojeciton=" + mediaProjection);
                            //TODO pass mediaprojection to service
                            finish();
                        }
                    }
                });
    
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
            resultLauncher.launch(mediaProjectionManager.createScreenCaptureIntent());
        }
    
    
    }

     

     

     

     

10 Replies

  • Figured it out and i have when i hate a question and find bunch of same questions without an answer, so here it is. Hope it helps. 

    Propably a bug in oculus android flavor. This dialog does not work from regular activity, but works fine prom VR activity.

    So here is my part of android manifest. Notice the ScreenCaptureActivity, with the params, and meta-data inside of it (only for that one activity so it does not affect rest of my app), to launch it as VR / fullscreen.

     

     

     

    <meta-data android:name="com.oculus.supportedDevices" android:value="quest2"/>
    <activity android:name=".activity.MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity 
        android:name=".activity.ScreenCaptureActivity" 
        android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode" 
        android:launchMode="singleTask" 
        android:resizeableActivity="false" 
        android:screenOrientation="landscape" 
        android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" 
        android:noHistory="false" >
        <intent-filter>
            <action android:name="cz.test.app.SCREEN_CAPTURE" />
            <category android:name="com.oculus.intent.category.VR" />
        </intent-filter>
        <meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
    </activity>

     

     

     

    And code for my screencapture activity, its fairly simple as well. The main thing is the manifest and launching it as VR

     

     

     

    public class ScreenCaptureActivity extends ComponentActivity {
        public static final String TAG = "ScreenCaptureActivity";
        
        
         private final ActivityResultLauncher<Intent> resultLauncher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                new ActivityResultCallback<ActivityResult>() {
    
                    @Override
                    public void onActivityResult(ActivityResult result) {
                        Log.d(TAG, "resultLauncher onActivityResult");
                        if (RESULT_OK == result.getResultCode()) {
                            Log.d(TAG, "Media projection permission granted");
                            MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
                            MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(result.getResultCode(), result.getData());
                            Log.d(TAG, "Successfully retrieved mediPerojeciton=" + mediaProjection);
                            //TODO pass mediaprojection to service
                            finish();
                        }
                    }
                });
    
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
            resultLauncher.launch(mediaProjectionManager.createScreenCaptureIntent());
        }
    
    
    }

     

     

     

     

    • CarpetFace's avatar
      CarpetFace
      Expert Protege

      Thank you for sharing this information!!!

       

      I was very excited to learn these things because I have been trying to get a non-null MediaProjection and I wasn't having any success.  I was about to give up when I found your post.  This fills me with hope.

       

      I am lacking in my Android and Java knowledge with primarily a Windows (C++/C#) background; that combined with a multi-minute inner dev loop for just testing out any of these Android specific changes to my project means my process has been a very slow iterative one.  I am determined to get this to work, and expect to be working on it for at least a few more days if not a week as I figure out all of the additional pieces.

       

      There are a few visible hurdles that I need to get past next, which I believe you have already solved.  

       

      First, I'm dumbfounded about how to even import ComponentActivity.  "import androidx.activity.ComponentActivity;" gives me the package not found error.  And a little searching seems to indicate that this is because of the "androidx" part, and that I need enable this for my project using UPL.  For which I found this article:

      How to force the Unreal Engine Android project to use AndroidX? | by Taras Leskiv | nineva | Medium

      https://medium.com/nineva/how-to-force-the-unreal-engine-android-project-to-use-androidx-f7060abd56ac

       

      But turns out I have already done everything in that article, because I'm using a solution for calling java that already does that:

      Sovahero/PluginMobileNativeCode (github.com)

      https://github.com/Sovahero/PluginMobileNativeCode

      I'm putting my java files in with the plugin's java to simplify my tests.  Still can't figure out I'm still getting this error.

       

      But once I figure that out, the next problem is how to get my android manifest to have the activity changes you showed above.  Since the manifest is generated each time, simply changing the one in the intermediate folder does not look like a path forward.  I believe I need to figure out how to use my own UPL for adding that.  

       

       

      • CarpetFace's avatar
        CarpetFace
        Expert Protege

        To get around the error "package androidx.activity does not exist" when I tried to "import androidx.activity.ComponentActivity;" I had to find this file in the plugin code:

        \MobileNativeCode\Source\MobileNativeCode\MobileNativeCode_UPL_Android.xml

         

        Then add 

        implementation "androidx.activity:activity:1.2.0"

        under buildGradleAdditions -> insert -> dependencies.  Mine looks like this now:
        dependencies {
        implementation 'com.google.guava:guava:28.2-android'
        implementation "androidx.activity:activity:1.2.0"
        }

    • CarpetFace's avatar
      CarpetFace
      Expert Protege

      Thanks for pointing that out. 🙂

       

      I'm still working to get to the point where an exception is the only problem I have.  The problem I am having now is the app process crashes, or hangs and is then closed automatically?  UE4 Launcher logs don't have a callstack; and my logging indicates that the call to startActivity didn't cause an exception.  I don't know this space well and so I have just been researching and trying various things to try and make progress on it; maybe while the update did break it, there is still a way to get it to work given the right setup.  

      From other attempts to capture audio, I tried MediaRecorder (only works for capturing Mic I now believe) and I can get a permissions dialog prompt to appear using Activity's requestPermissions.  I would have thought that they would be using similar mechanisms and so if that one still works perhaps there is still a way.

       

      • CarpetFace's avatar
        CarpetFace
        Expert Protege

        I came across an interesting sample (note: my goal is to capture audio that is being played by UE4's Android Media Player): https://github.com/lincollincol/QRecorder

         

        But I'm still can't get my activity to start.  

         

        If I keep <category android:name="com.oculus.intent.category.VR" /> in the manifest under the <intent-filter> tag, then my activity isn't found (intent.addCategory("com.oculus.intent.category.VR") doesn't appear to help?), but changing the manifest to use <category android:name="android.intent.category.DEFAULT"/> instead, I avoid the "activity not found" error; no exception is thrown, but my app immediately crashes.  

        So I think I am still just stuck on beginner problems related to android and activities and intents and all that jazz.  

  • Anonymous's avatar
    Anonymous

    I get 

    AndroidJavaException: java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/activity/ComponentActivity;
    java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/activity/ComponentActivity;
    at java.lang.Class.newInstance(Native Method)
    at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)

    when starting the ScreenCaptureActivity: 

    startActivityForResult(new Intent(this, ScreenCaptureActivity.class), SCREEN_CAPTURE_REQUEST_CODE);
    • CarpetFace's avatar
      CarpetFace
      Expert Protege

      The exception message I get when I do this call:

      resultLauncher.launch(mediaProjectionManager.createScreenCaptureIntent());

      is:

      "unable to find explicit activity class com.android.systemui/com.android.systemui.media.MediaProjectionPermissionActivity"

      Is that the same exception you are getting vit?

       

      eusebium, the way I found that got the ScreenCaptureActivity to be created was like this:

       

      public static String start(Activity activity)
      {
      	try
      	{
      		Intent intent = new Intent(activity, ScreenCaptureActivity.class);
      		intent.setAction("SCREEN_CAPTURE");
      		activity.startActivity(intent);
      
      		return "start: no exception";
      	}
      	catch (Exception e)
      	{
      		return "EXCEPTION: " + e.getMessage();
      	}
      }

       Please ignore my String return that I'm leveraging for logging.  The activity passed to this function is FJavaWrapper::GameActivityThis that the MobileNativeCode passes in with this call:

      FString TestResult = AndroidUtils::CallJavaCode<FString>(
      		"com/Plugins/MobileNativeCode/ScreenCaptureActivity",
      		"start",
      		"",
      		true);

       

      My activity in my manifest looks like this:

       

            <activity
                android:name="com.Plugins.MobileNativeCode.ScreenCaptureActivity"
                android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode"
                android:launchMode="singleTask"
                android:resizeableActivity="false"
                android:screenOrientation="landscape"
                android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
                android:noHistory="false" >
              <intent-filter>
                <action android:name="SCREEN_CAPTURE" />
                <category android:name="com.oculus.intent.category.VR" />
              </intent-filter>
              <meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
            </activity>

       

      I've been taking a few days of vacation this week; so my replies may be delayed.  The exception I mentioned is related to the more recent other thread that vit created.  Sounds like a bug may have been introduced.

      • Anonymous's avatar
        Anonymous

        Thanks! Indeed, I also get this exception if I call it from C#/Unity.

         Error Unity android.content.ActivityNotFoundException: Unable to find explicit activity class {com.android.systemui/com.android.systemui.media.MediaProjectionPermissionActivity}; have you declared this activity in your AndroidManifest.xml?