FAQ FM
Приложение

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика

[Android] Как в run-time получить информацию, указанную в окне "Project->Options->Version Info"?

{for Delphi XE6: Add to "uses" module "Androidapi.Helpers"}
uses
  {...,} Androidapi.JNI.JavaTypes, FMX.Helpers.Android,
  Androidapi.JNI.GraphicsContentViewText
  {$IF CompilerVersion >= 20}, Androidapi.Helpers{$ENDIF};
 
// В примере показано как получить versionName
procedure TForm1.Button1Click(Sender: TObject);
var
  PackageManager: JPackageManager;
  VersionPackage, PackageName: JString;
begin
  PackageManager := SharedActivity.getPackageManager;
  PackageName := SharedActivityContext.getPackageName;
   
  VersionPackage := PackageManager.getPackageInfo(PackageName, 0).versionName;
  Label1.Text := JStringToString(VersionPackage);
end;


[MacOS] Как изменить прозрачность формы (альфа-канал)?

uses
  Macapi.AppKit, FMX.Platform.Mac;

procedure TForm1.Button1Click(Sender: TObject);
var
  Wnd: NSWindow;
begin
  Wnd := WindowHandleToPlatform(Form1.Handle).Wnd;
  Wnd.setAlphaValue(0.5); // Диапазон: 0 .. 1.0
  // Узнать значение текущего альфа-канала можно так:
  Caption := FloatToStr(Wnd.alphaValue);
end;


[MacOS] Как ограничить размер растяжения/сжатия формы?

uses
  FMX.Platform.Mac, Macapi.CoreGraphics;

procedure SetFormMinSize(const AForm: TForm; const AMinSize: TSize);
var
  MacHandle: TMacWindowHandle;
begin
  MacHandle := WindowHandleToPlatform(AForm.Handle);
  MacHandle.Wnd.setMinSize(CGSizeMake(AMinSize.Width, AMinSize.Height));
end;

procedure SetFormMaxSize(const AForm: TForm; const AMaxSize: TSize);
var
  MacHandle: TMacWindowHandle;
begin
  MacHandle := WindowHandleToPlatform(AForm.Handle);
  MacHandle.Wnd.setMaxSize(CGSizeMake(AMaxSize.Width, AMaxSize.Height));
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  SetFormMinSize(Self, TSize.Create(500, 500));
  SetFormMaxSize(Self, TSize.Create(800, 800));
end;


[Android] Как определить, установлено ли приложение или нет?

uses
  Androidapi.JNI.GraphicsContentViewText
  {$IF CompilerVersion >= 20}, Androidapi.Helpers{$ENDIF};

function IsAppInstalled(const AAppName: string): Boolean;
var
  PackageManager: JPackageManager;
begin
  PackageManager := SharedActivity.getPackageManager;
  try
    PackageManager.getPackageInfo(StringToJString(AAppName),
      TJPackageManager.JavaClass.GET_ACTIVITIES);
    Result := True;
  except
    on Ex: Exception do
      Result := False;
  end;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  if IsAppInstalled('com.google.zxing.client.android') then
    ShowMessage('Приложение установлено')
  else
    ShowMessage('Приложение не установлено');
end;


[Windows, MacOS] Как отловить перемещение формы и изменение её размеров?

type
  TForm1 = class(TForm)
  public
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  end;

{...}

implementation

procedure TForm1.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  inherited;
  Caption := Format('L: %d   T: %d   W: %d   H: %d', [ALeft, ATop, AWidth, AHeight]);
end;


[Windows, MacOS] Как перемещать форму за любой элемент?

procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
  // Свойство HitTest должен иметь значение True
  StartWindowDrag;
end;


[Android] Как установить ярлык на домашний экран Android?

uses
  Androidapi.JNI.GraphicsContentViewText, FMX.Helpers.Android, Androidapi.Helpers,
  Androidapi.JNI.JavaTypes, FMX.Platform.Android, AndroidApi.JniBridge,
  AndroidApi.JNI.App, AndroidAPI.Jni.OS;

procedure InstallShortcut( Action: string );
{$IFDEF ANDROID}
var
  ShortcutIntent: JIntent;
  addIntent: JIntent;
  wIconIdentifier: Integer;
  wIconResource: JIntent_ShortcutIconResource;
{$ENDIF}
begin
  {$IFDEF ANDROID}
  ShortcutIntent := TJIntent.JavaClass.init(SharedActivityContext, SharedActivityContext.getClass);
  ShortcutIntent.setAction(TJIntent.JavaClass.ACTION_MAIN);

  addIntent := TJIntent.Create;
  addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_INTENT,
    TJParcelable.Wrap((shortcutIntent as ILocalObject).GetObjectID));
  addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_NAME, StringToJString(Application.Title));
  addIntent.setAction(StringToJString(Action));
  // Получаем идентификатор ресурса иконки
  wIconIdentifier := SharedActivity.getResources.getIdentifier(StringToJString('ic_launcher'),
    StringToJString('drawable'), StringToJString('com.embarcadero.Project1')); // Имя должно быть указано правильно
  wIconResource := TJIntent_ShortcutIconResource.JavaClass.fromContext(SharedActivityContext, wIconIdentifier);
  // Устанавливаем значок для ярлыка
  addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_ICON_RESOURCE,
    TJParcelable.Wrap((wIconResource as ILocalObject).GetObjectID));

  SharedActivityContext.sendBroadcast(addIntent);
  {$ENDIF}
end;

// Создание ярлыка
// В манифесте должно быть прописано разрежение
// 
// На устройствах некоторых производителей (непример Sony) ярлыки можно создать
// до тех пор, пока на экране не закончится свободное место, а устройства от
// ASUS такого не допускают.
procedure TForm1.Button1Click(Sender: TObject);
begin
  {$IFDEF ANDROID}
  InstallShortcut('com.android.launcher.action.INSTALL_SHORTCUT');
  {$ENDIF}
end;

// Удаление ярлыка
// В манифесте должно быть прописано разрежение
// 
// Если для приложения создано несколько ярлыков, они будут удалены все сразу.
procedure TForm1.Button2Click(Sender: TObject);
begin
  {$IFDEF ANDROID}
  InstallShortcut('com.android.launcher.action.UNINSTALL_SHORTCUT');
  {$ENDIF}
end;


[Android] Как заставить устройство вибрировать?

// В манифесте должно быть прописано разрежение
// <uses-permission android:name="android.permission.VIBRATE" />
// Для этого в Uses Permissions» ставим галочку в пункте «Vibrate».

uses
  FMX.Helpers.Android, Androidapi.JNI.JavaTypes, Androidapi.JNI.Os,
  Androidapi.Helpers, Androidapi.JNI.App, Androidapi.JNIBridge,
  Androidapi.JNI.GraphicsContentViewText;

// Проверяем, поддерживается ли вибрация
procedure TForm1.Button1Click(Sender: TObject);
var
  VibratorObj: JObject;
  Vibrator: JVibrator;
begin
  //VibratorObj := SharedActivity.getSystemService(TJActivity.JavaClass.VIBRATOR_SERVICE);
  VibratorObj := SharedActivity.getSystemService(TJContext.JavaClass.VIBRATOR_SERVICE);
  if Assigned(VibratorObj) then
  begin
    Vibrator := TJVibrator.Wrap((VibratorObj as ILocalObject).GetObjectID);
    if Assigned(Vibrator) then
      if Vibrator.hasVibrator() then
        ShowMessage('Вибрация поддерживается!')
      else
        ShowMessage('Вибрация НЕ поддерживается!')
    else
      ShowMessage('Вибрация НЕ поддерживается!');
  end;
end;

// Включение вибрации
procedure TForm1.Button2Click(Sender: TObject);
var
  VibratorObj: JObject;
  Vibrator: JVibrator;
begin
  //VibratorObj := SharedActivity.getSystemService(TJActivity.JavaClass.VIBRATOR_SERVICE);
  VibratorObj := SharedActivity.getSystemService(TJContext.JavaClass.VIBRATOR_SERVICE);
  if Assigned(VibratorObj) then
  begin
    Vibrator := TJVibrator.Wrap((VibratorObj as ILocalObject).GetObjectID);
    if Assigned(Vibrator) then
      Vibrator.vibrate(1000);
  end;
end;

// Вибрация по шаблону
procedure TForm1.Button3Click(Sender: TObject);

  function IntArrayToJArray(const Arr: array of Integer): TJavaArray<Int64>;
  var
    i: Integer;
  begin
    Result := TJavaArray<Int64>.Create(Length(Arr));
    for i := Low(Arr) to High(Arr) do
      Result.Items[i] := Arr[i];
  end;

var
  VibratorObj: JObject;
  Vibrator: JVibrator;
begin
  //VibratorObj := SharedActivity.getSystemService(TJActivity.JavaClass.VIBRATOR_SERVICE);
  VibratorObj := SharedActivity.getSystemService(TJContext.JavaClass.VIBRATOR_SERVICE);
  if Assigned(VibratorObj) then
  begin
    Vibrator := TJVibrator.Wrap((VibratorObj as ILocalObject).GetObjectID);
    if Assigned(Vibrator) then
       // Первый параметр – массив со значениями.
       // Первое значение в массиве означает длительность паузы, второе – длительность вибрации,
       //   третье – длительность паузы, четвёртое – длительность вибрации и т.д.
       // Второй параметр – это число повторов. «-1» значит, что повторять не надо.
       Vibrator.vibrate(IntArrayToJArray(
         // Тема из "Звездных войн" :)
         [0, 500, 110, 500, 110, 450, 110, 200, 110, 170, 40, 450, 110, 200, 110, 170, 40, 500]), -1);
  end;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  VibratorObj: JObject;
  Vibrator: JVibrator;
begin
  //VibratorObj := SharedActivity.getSystemService(TJActivity.JavaClass.VIBRATOR_SERVICE);
  VibratorObj := SharedActivity.getSystemService(TJContext.JavaClass.VIBRATOR_SERVICE);
  if Assigned(VibratorObj) then
  begin
    Vibrator := TJVibrator.Wrap((VibratorObj as ILocalObject).GetObjectID);
    if Assigned(Vibrator) then
      Vibrator.cancel();
  end;
end;


[Android] Как определить текущий уровень громкости в приложении?

uses
  Androidapi.JNI.JavaTypes, Androidapi.JNI.Media, Androidapi.Helpers,
  Androidapi.JNI.App, Androidapi.JNIBridge, Androidapi.JNI.GraphicsContentViewText;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char;
  Shift: TShiftState);
var
  AudioObj: JObject;
  Audio: JAudioManager;
begin
  if (Key = vkVolumeDown) or (Key = vkVolumeUp) then
  begin
    AudioObj := SharedActivity.getSystemService(TJContext.JavaClass.AUDIO_SERVICE);
    Audio := TJAudioManager.Wrap((AudioObj as ILocalObject).GetObjectID);
    lbCurrentVolume.Text := Audio.getStreamVolume(TJAudioManager.JavaClass.STREAM_RING).ToString;
    lbMaxVolume.Text := Audio.getStreamMaxVolume(TJAudioManager.JavaClass.STREAM_RING).ToString;
  end;
end;


Как изменить предпочитаемый графический процессор?

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage('Используемая канва: ' + Canvas.ClassName);
  // • TCanvasD2D - Direct 2D (Win)
  // • TCanvasGdiPlus - GDI + (Win)
  // • TCanvasGpu - GPU (Все платормы)
  // • TCanvasQuartz - Quartz (iOS, OSX)
end;

{$IFDEF MSWINDOWS}
initialization
  FMX.Types.GlobalUseDX := False;
// FMX.Types.GlobalUseDXInDX9Mode := False;
// FMX.Types.GlobalUseDXSoftware := False;
 FMX.Types.GlobalUseDirect2D := False;
// FMX.Types.GlobalUseGPUCanvas := False;
{$ENDIF}

При использовании материала - ссылка на сайт обязательна