Android MediaProjection API от Delphi - PullRequest
       87

Android MediaProjection API от Delphi

0 голосов
/ 27 сентября 2018

Я написал что-то с Delphi для тестирования Android MediaProjection API.(https://developer.android.com/reference/android/media/projection/MediaProjection)

Я попытался преобразовать некоторые из кодов Java в Delphi.

java пример: https://github.com/mtsahakis/MediaProjectionDemo/blob/master/src/com/mtsahakis/mediaprojectiondemo/ScreenCaptureImageActivity.java

Когда вы нажимаете кнопку, она попросит авторизовать пользователя для захвата экрана.

Когда пользователь примет, он зарегистрирует одну процедуру в медиапроекции api.

Поэтому, когда экран изменился, API вызовет нашу процедуру с данными изображения, и мы покажем любой текст на экране для тестирования.

Я проверил мой код ниже.

Когда вы принимаете экран с запросом разрешения, приложение закрывается и мгновенно закрывается.

На Android 8.1:

поднял класс исключений Ошибка сенментации (11) ----> Система --->процедура _InstCopy () ----> Source .__ ObjAddRef

или

с повышенным классом исключений Недопустимая инструкция (4) ----> System.Internal.Excutils.SignalConverter

На Android 6.0:

поднял класс исключений EInvalidCast с сообщением «Тип неверного типа» ----> System.Rtti ---> System._DbgExcNotify

unit frmuMediaProjectionTest;

    interface

    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
      FMX.Controls.Presentation, FMX.StdCtrls,

      System.Messaging, Androidapi.JNI.GraphicsContentViewText,
      Androidapi.JNI.Media, Androidapi.JNIBridge;

    type
      TonImageAvailable = procedure (reader: JImageReader) of object;

      TImageAvailableListener = class( TJavaLocal, JImageReader_OnImageAvailableListener )
       private
         FonImageAvailable: TonImageAvailable;
       public
        procedure onImageAvailable(reader: JImageReader);cdecl;

        property onIAvailable: TonImageAvailable read FonImageAvailable write FonImageAvailable;
      end;

      TfrmMediaProjectionTest = class(TForm)
        Button1: TButton;
        Label1: TLabel;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        MPManager: JMediaProjectionManager;
        FMessageSubscriptionID: integer;

        procedure HandleActivityMessage(const Sender: TObject; const M: TMessage);
        function OnActivityResult(RequestCode, ResultCode: Integer; Data: JIntent): Boolean;

        procedure onImageAvailable(reader: JImageReader);
      public

      end;

    var
      frmMediaProjectionTest: TfrmMediaProjectionTest;

    implementation

    {$R *.fmx}

    Uses //Androidapi.JNI.Media,
         AndroidApi.Jni.JavaTypes,
         Androidapi.Helpers,
         //Androidapi.JNI.GRaphicsContentViewText,
         //Androidapi.JNIBridge,
         Androidapi.JNI.os,
         Androidapi.JNI.App;


    procedure TfrmMediaProjectionTest.FormCreate(Sender: TObject);
    begin
      MPManager := nil;
    end;


    procedure TfrmMediaProjectionTest.Button1Click(Sender: TObject);
     var MPObj: JObject;
    begin
      FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage( TMessageResultNotification, HandleActivityMessage );

      MPObj := TAndroidHelper.Context.getSystemService( TJContext.JavaClass.MEDIA_PROJECTION_SERVICE );
      MPManager := TJMediaProjectionManager.Wrap( ( MPObj as ILocalObject ).GetObjectID );
      TAndroidHelper.Activity.startActivityForResult( MPManager.createScreenCaptureIntent, 100 );
    end;


    procedure TfrmMediaProjectionTest.HandleActivityMessage(const Sender: TObject; const M: TMessage);
     begin
       if M is TMessageResultNotification then
           OnActivityResult( TMessageResultNotification( M ).RequestCode, TMessageResultNotification( M ).ResultCode,
                             TMessageResultNotification( M ).Value );
     end;


    //ResultCode: iptal: 0   kabul: -1
    function TfrmMediaProjectionTest.OnActivityResult( RequestCode, ResultCode: Integer; Data: JIntent ): Boolean;
     const RGBA_8888: integer = 1;
           mDencity: integer = 160;
           VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY: integer = 8;
           VIRTUAL_DISPLAY_FLAG_PUBLIC: integer = 1;
     var mp: JMediaProjection;
         imageReader: JImageReader;
         handler: JHandler;
         ImageAvailableListener: TImageAvailableListener;
     begin
       TMessageManager.DefaultManager.Unsubscribe( TMessageResultNotification, FMessageSubscriptionID );

       if ResultCode = -1 then
       begin
         mp := MpManager.getMediaProjection( ResultCode, Data );
         if mp <> nil then
         begin
           imageReader := TJImageReader.JavaClass.newInstance( screen.Width, screen.Height, RGBA_8888, 2 );

           handler := TJHandler.JavaClass.init();

           mp.createVirtualDisplay( StringToJString( 'Test' ), screen.Width, screen.Height, mDencity,
                                    VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY or VIRTUAL_DISPLAY_FLAG_PUBLIC,
                                    imageReader.getSurface, nil, handler );

           ImageAvailableListener := TImageAvailableListener.Create;
           ImageAvailableListener.onIAvailable := onImageAvailable;
           imageReader.setOnImageAvailableListener( ImageAvailableListener, handler );
         end;
       end
       else
       if ResultCode = 0 then showmessage( 'Canceled' );

       result := true;
     end;


    procedure TfrmMediaProjectionTest.onImageAvailable(reader: JImageReader);
    begin
       Label1.Text := 'Called from api';
    end;

    { TImageAvailableListener }

    procedure TImageAvailableListener.onImageAvailable(reader: JImageReader);cdecl;
    begin
      if assigned( FonImageAvailable ) then
      begin
        FonImageAvailable( reader );
      end;
    end;

    end.
...