Android Mediaprojection api from delphi

  

I have written something with delphi for testing android mediaprojection api. ( https://developer.android.com/reference/android/media/projection/MediaProjection )

I tried to convert some of the java codes to delphi.

java example: https://github.com/mtsahakis/MediaProjectionDemo/blob/master/src/com/mtsahakis/mediaprojectiondemo/ScreenCaptureImageActivity.java

When you click the button it will ask to authorize the user to capture the screen.

When the user accept, it will register one procedure to mediaprojection api.

So when the screen changed, the api will call our procedure with picture data and we will show any text on the screen for testing.

i tested my code below.

When you accept the screen asking for permission the app crash and closes instantly.

On Android 8.1:

raised exception class Senmentation fault(11) —-> System —> procedure _InstCopy() —-> Source.__ObjAddRef

or

raised exception class Illegal instruction(4) —-> System.Internal.Excutils.SignalConverter

On Android 6.0:

raised exception class EInvalidCast with message ‘Invalid class typecast’ —-> 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.

Comments are closed.