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.
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.