Android 9+ 上的媒体投影问题

Posted

技术标签:

【中文标题】Android 9+ 上的媒体投影问题【英文标题】:Mediaprojection issues on Android 9+ 【发布时间】:2019-11-18 13:01:37 【问题描述】:

我制作了一个 OCR 应用程序,它使用 android mediaprojection 制作屏幕截图并处理此图像中的文本。这工作正常,除了在 Android 9+ 上。当 mediaprojeciton 启动时,总​​是会弹出一个窗口警告可能记录的敏感数据,以及一个取消或开始记录的按钮。我怎样才能实现这个窗口只会显示一次?

我尝试通过创建两个额外的私有静态变量来存储 mediaprojection 的意图和结果数据来防止它弹出,如果它不为空,则重新使用它。但它不起作用(在另一篇文章中了解此方法)。

// 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);


        


我的代码在 Android 9 以下的 Android 版本上运行良好。在旧的 Android 版本上,我可以选择保留授予录制权限的决定,并且它永远不会再次出现。那么我可以在 Android 9 中做什么?

提前致谢,我很高兴你的每一个想法:)

【问题讨论】:

我从未见过那个对话框。你在什么设备上测试? 我正在使用 Api 29 的 Android 模拟器上进行测试。即使我在谷歌中输入此对话框文本,我也没有得到任何结果 :( 该对话框在什么时候出现?是来自您的startProjection() 方法还是来自您调用getMediaProjection() 的地方? 这使对话框出现:startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE); 每次进程调用只需要调用一次。 【参考方案1】:

问题是我在打电话 startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE); 每次,这是不必要的(createScreenCaptureIntent() 导致请求用户交互的对话窗口) 我的解决方案使对话框仅出现一次(如果应用程序已关闭,它将再次请求许可)。 我所要做的就是制作额外的 Intent 和 int 类型的私有静态变量。

private static Intent staticIntentData; private static int staticResultCode;

在活动结果中,我为这些变量分配了传递的结果代码和意图:

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

每次我调用我的 startprojection 方法时,我都会检查它们是否为空:

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

如果为null,它将请求权限,如果不是,它将使用静态意图数据和静态int结果代码开始投影,因此不需要再次请求该权限,只需重用您在活动结果中获得的内容。

sMediaProjection = mProjectionManager.getMediaProjection(staticResultCode, staticIntentData);

就这么简单!现在,每次您使用该应用程序时,它只会显示一次。我猜这就是 Google 想要的,因为在该对话框中没有像以前的 android 版本那样保留决定复选框。

【讨论】:

从系统堆栈重新启动设备或应用程序终止后,它会再次询问,所以任何解决方案都不要询问。

以上是关于Android 9+ 上的媒体投影问题的主要内容,如果未能解决你的问题,请参考以下文章

基于androi的医院挂号预约系统app

Android面试收集录 电话短信和联系人多媒体技术

数学平面向量上的投影是啥

投影媒体查询:浏览器支持和解决方法?

如何从前台服务启动媒体投影

Android 上的媒体播放器