Skip to content

Instantly share code, notes, and snippets.

@viniciusfbb
Last active February 3, 2026 15:30
Show Gist options
  • Select an option

  • Save viniciusfbb/699a18e9fe982ad99e5dd65a7342893c to your computer and use it in GitHub Desktop.

Select an option

Save viniciusfbb/699a18e9fe982ad99e5dd65a7342893c to your computer and use it in GitHub Desktop.
Delphi capture screenshot from android Firemonkey form
unit PixelCopy.Android;
interface
uses
Androidapi.JNI.GraphicsContentViewText,
FMX.Graphics;
function CaptureWindowPixels(const AWindow: JWindow): TBitmap;
function CaptureSurfaceHolderPixels(const ASurfaceHolder: JSurfaceHolder): TBitmap;
implementation
uses
System.SysUtils,
System.SyncObjs,
Androidapi.JNIBridge,
Androidapi.JNI.Os,
Androidapi.JNI.JavaTypes,
Androidapi.Helpers,
FMX.Helpers.Android;
type
JPixelCopy = interface;
JPixelCopy_OnPixelCopyFinishedListener = interface;
JPixelCopyClass = interface(JObjectClass)
['{A6FA8C65-EBA0-4674-9C55-59F196FEC13C}']
procedure request(source: JSurfaceView; dest: JBitmap; listener: JPixelCopy_OnPixelCopyFinishedListener; handler: JHandler); cdecl; overload;
procedure request(source: JSurface; dest: JBitmap; listener: JPixelCopy_OnPixelCopyFinishedListener; handler: JHandler); cdecl; overload;
procedure request(source: JWindow; dest: JBitmap; listener: JPixelCopy_OnPixelCopyFinishedListener; handler: JHandler); cdecl; overload;
function _GetSUCCESS: Integer; cdecl;
property SUCCESS: Integer read _GetSUCCESS;
end;
[JavaSignature('android/view/PixelCopy')]
JPixelCopy = interface(JObject)
['{C7F027B5-12F5-4AA0-9154-2FF48CC46EFD}']
end;
TJPixelCopy = class(TJavaGenericImport<JPixelCopyClass, JPixelCopy>) end;
JPixelCopy_OnPixelCopyFinishedListenerClass = interface(IJavaClass)
['{4508A3EB-846E-4517-B91E-718D1C4DA8BD}']
end;
[JavaSignature('android/view/PixelCopy$OnPixelCopyFinishedListener')]
JPixelCopy_OnPixelCopyFinishedListener = interface(IJavaInstance)
['{9F08ECAF-3A32-43F5-935D-5AA013C48BFE}']
procedure onPixelCopyFinished(copyResult: Integer); cdecl;
end;
TJPixelCopy_OnPixelCopyFinishedListener = class(TJavaGenericImport<JPixelCopy_OnPixelCopyFinishedListenerClass, JPixelCopy_OnPixelCopyFinishedListener>) end;
type
TPixelCopyFinishedListener = class(TJavaLocal, JPixelCopy_OnPixelCopyFinishedListener)
private
FOnFinished: TProc<Integer>;
public
constructor Create(const AOnFinished: TProc<Integer>);
procedure onPixelCopyFinished(copyResult: Integer); cdecl;
end;
{ TPixelCopyFinishedListener }
constructor TPixelCopyFinishedListener.Create(const AOnFinished: TProc<Integer>);
begin
inherited Create;
FOnFinished := AOnFinished;
end;
procedure TPixelCopyFinishedListener.onPixelCopyFinished(copyResult: Integer);
begin
FOnFinished(copyResult);
end;
const
CAPTURE_TIMEOUT_MS = 3000;
function CaptureWindowPixels(const AWindow: JWindow): TBitmap;
var
Bitmap: JBitmap;
DecorView: JView;
Event: TEvent;
Handler: JHandler;
Listener: JPixelCopy_OnPixelCopyFinishedListener;
Success: Boolean;
SuccessPointer: PBoolean;
Thread: JHandlerThread;
begin
if AWindow = nil then
Exit(nil);
DecorView := AWindow.getDecorView;
if (DecorView = nil) or (DecorView.getWidth <= 0) or (DecorView.getHeight <= 0) then
Exit(nil);
Bitmap := TJBitmap.JavaClass.createBitmap(DecorView.getWidth, DecorView.getHeight,
TJBitmap_Config.JavaClass.ARGB_8888);
Event := TEvent.Create(nil, False, False, '');
try
Thread := TJHandlerThread.JavaClass.init(StringToJString('FMXScreenshot'));
Thread.start;
try
Handler := TJHandler.JavaClass.init(Thread.getLooper);
SuccessPointer := @Success;
Listener := TPixelCopyFinishedListener.Create(
procedure(ACopyResult: Integer)
begin
SuccessPointer^ := ACopyResult = TJPixelCopy.JavaClass.SUCCESS;
Event.SetEvent;
end);
TJPixelCopy.JavaClass.request(AWindow, Bitmap, Listener, Handler);
if (Event.WaitFor(CAPTURE_TIMEOUT_MS) = TWaitResult.wrSignaled) and Success then
begin
Result := TBitmap.Create;
if not JBitmapToBitmap(Bitmap, Result) then
FreeAndNil(Result);
end
else
Result := nil;
finally
Thread.quit;
end;
finally
Event.Free;
end;
end;
function CaptureSurfaceHolderPixels(const ASurfaceHolder: JSurfaceHolder): TBitmap;
var
Bitmap: JBitmap;
DecorView: JView;
Event: TEvent;
Handler: JHandler;
Listener: JPixelCopy_OnPixelCopyFinishedListener;
Success: Boolean;
SuccessPointer: PBoolean;
Thread: JHandlerThread;
begin
if (ASurfaceHolder = nil) or (ASurfaceHolder.getSurfaceFrame.width <= 0) or
(ASurfaceHolder.getSurfaceFrame.height <= 0) then
begin
Exit(nil);
end;
Bitmap := TJBitmap.JavaClass.createBitmap(ASurfaceHolder.getSurfaceFrame.width, ASurfaceHolder.getSurfaceFrame.height,
TJBitmap_Config.JavaClass.ARGB_8888);
Event := TEvent.Create(nil, False, False, '');
try
Thread := TJHandlerThread.JavaClass.init(StringToJString('FMXScreenshot'));
Thread.start;
try
Handler := TJHandler.JavaClass.init(Thread.getLooper);
SuccessPointer := @Success;
Listener := TPixelCopyFinishedListener.Create(
procedure(ACopyResult: Integer)
begin
SuccessPointer^ := ACopyResult = TJPixelCopy.JavaClass.SUCCESS;
Event.SetEvent;
end);
TJPixelCopy.JavaClass.request(ASurfaceHolder.getSurface, Bitmap, Listener, Handler);
if (Event.WaitFor(CAPTURE_TIMEOUT_MS) = TWaitResult.wrSignaled) and Success then
begin
Result := TBitmap.Create;
if not JBitmapToBitmap(Bitmap, Result) then
FreeAndNil(Result);
end
else
Result := nil;
finally
Thread.quit;
end;
finally
Event.Free;
end;
end;
end.
...
uses
PixelCopy.Android, FMX.Platform.Android, FMX.Platform.UI.Android;
procedure TForm1.Button1Click(Sender: TObject);
begin
Rectangle1.Fill.Bitmap.Bitmap := CaptureWindowPixels(MainActivity.getWindow);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Rectangle1.Fill.Bitmap.Bitmap := CaptureSurfaceHolderPixels(TAndroidWindowHandle(Screen.ActiveForm.Handle).Holder);
end;
@gustavomilena40
Copy link
Copy Markdown

obrigado por compartilhar

passei umas 6 horas tentando fazer minha pr贸pria JNI pro pixelcopy antes de achar isso aqui kkkk

@viniciusfbb
Copy link
Copy Markdown
Author

@gustavomilena40 Fico feliz em ter ajudado :) Deixe uma estrela ai 馃槄

@gustavomilena40
Copy link
Copy Markdown

@gustavomilena40 Fico feliz em ter ajudado :) Deixe uma estrela ai 馃槄

opa, vou deixar no reposit贸rio todo que tme mta coisa legal aqui

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment