30 Haziran 2014 Pazartesi

Delphi Mobile Duyuru Componenti

Merhabalar,

Sizlere bu yazımda kendi çapımda hazırladığım bir procedure'den bahsedeceğim. Bu procedure sayesinde Google Analytics'in kullandığı şekil objeleriniz olacak ve böyle şeyler kullanıcıya duyuru vs. gösteriminde görünüş olarak size artı puan sağlayacağına inanmaktayım.

Google Analytics Görünümü:

Şimdi örnek projemiz için forumumuza yerleştireceğimiz objeler:
-Editbox 1 adet
-Button 1 adet
-VertScrollBox 1 adet ve Align = Client yapın ki bütün ekranı kaplasın.

Uses FMX.Layouts,FMX.Effects,FMX.Objects;// Eklenmesi gerekenler

procedure DuyuruEkle(Yazi, YBaslik: String; Scroll: TVertScrollBox);
var
  Pano,BPano: TRectangle;
  Metin,Baslik: TText;
  Golge: TShadowEffect;
begin
  TThread.CreateAnonymousThread(procedure
  begin
    Pano := TRectangle.Create(Scroll);
    with Pano do
    begin
      Parent := Scroll;
      Align := TAlignLayout.alTop;
      with Margins do
      begin
        Left := 5;
        Right := 5;
        Top := 5;
        Bottom := 5;
      end;
      Padding.Left := 5;
      Fill.Color := $FFECF0F1;
      Sides := [];

      Golge := TShadowEffect.Create(Scroll);
      with Golge do
      begin
        Parent := Pano;
        Direction := 90;
        Distance := 2;
        Opacity := 0.6;
        ShadowColor := TAlphaColorRec.Black;
        Softness := 0.1;
      end;

      BPano := TRectangle.Create(Scroll);//Baslik Arkafon
      with BPano do
      begin
        Parent := Pano;
        Position.X := 15;
        Position.Y := 0;
        Fill.Color := $FFCF3F30;
        Sides := [];

        Baslik := TText.Create(Scroll);//Baslik yazı
        with Baslik do
        begin
          Parent := BPano;
          Text := UpperCase(YBaslik);
          Align := TAlignLayout.alContents;
          WordWrap := False;
          Font.Family := 'Calibri';
          Color := TAlphaColorRec.White;
          Font.Size := 15;
        end;
         BPano.Width := Baslik.Width + 30 + 30;
         BPano.Height := 30;
      end;

      Metin := TText.Create(Scroll);
      with Metin do
      begin
        Parent := Pano;
        Margins.Top := 40;
        Text := Yazi;
        Font.Family := 'Arial';
        Align := TAlignLayout.alClient;
      end;

      Pano.Height := ((Length(Metin.Text) / (Scroll.Width / 15)) * 15) ;
      if Pano.Height < 80 then
        Pano.Height := 90;
    end;
  end).Start;
end;

Gerekli procedure tanımını yaptıktan sonra Buton içerisine gelerek:

DuyuruEkle(DuyuruEdit.Text,'ÖNEMLİ',VertScrollBox);


1-) Gördüğünüz gibi. "DuyuruEdit.text" editboxdan gönderdiğimiz yani elimizle yazdığımız yazıdır.
2-) "ÖNEMLİ" yazan yeri örnekte manuel olarak ayarladım ben, siz isterseniz başka bir edit ile orayıda değiştirebilirsiniz.
3-) Son parametremizde işlem görecek olan VertScrollBox'dır.

Bu çalışmada renkleri istediğiniz gibi değiştirebilirsiniz. Ben burada form rengini "#FFCF3F30" yaptım.

Projenin son hali:

28 Haziran 2014 Cumartesi

Delphi Android Uygulamayı arka planda devam ettirme

Merhabalar bu işlem sayesinde programdan çıkmak yerine uygulamayı arka planda sürdürmeye devam etmektedir. Kodu şahsen denemedim deneyen Ali Yıldırım arkadaşımıza teşekkürler.


Uses FMX.VirtualKeyboard,FMX.Platform, FMX.Helpers.Android;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char;
  Shift: TShiftState);
Var
  keyboard: IFMXVirtualKeyboardService;
begin
  if (Key = vkHardwareBack) then
  Begin
 
    keyboard := TPlatformServices.Current.GetPlatformService(IFMXVirtualKeyboardService) as IFMXVirtualKeyboardService;
 
    if  TVirtualKeyboardState.Visible in keyboard.VirtualKeyBoardState then   Exit;
 
    SharedActivity.moveTaskToBack(True);
 
    Key := 0;
 
  End;
end;

26 Haziran 2014 Perşembe

Delphi Android kendi telefon numaranı öğrenme

Merhabalar,

Başlık biraz garip gelebilir farkındayım :)
Yapılmak istenen cihazda mevcut olan sim kartın numarasını almaktır.

Kodlar her cihazda çalışmayabilir.

uses

Androidapi.JNI.Telephony;

var
  tMgr: JTelephonyManager;
  PhoneNumber: String;
begin
  tMgr := TJTelephonyManager.Wrap((SharedActivityContext.getSystemService(TJContext.JavaClass.TELEPHONY_SERVICE)
as ILocalObject).GetObjectID);
  PhoneNumber := JStringToString(tMgr.getLine1Number);
end;
Orjinal konu için tıklayınız.

25 Haziran 2014 Çarşamba

Delphi Android harici ve dahili hafıza kullanımı

Merhabalar,

Bir özelliğimden bahsetmek isterim hazır delphinin hazır fonksiyonları yerine "ilkel" de olsa kendi fonksiyonlarımla işlem yapmaya bayılırım :)

Bu yazımda sizlere Android cihazınızın "Hafıza Kartlarına" nasıl erişebileceğiniz hakkında örneklerle ve kendi buldugum Samsung ve LG cihazlarda denediğimde olumlu sonuç aldığım örneği anlatacağım. Bu kartlar cihazınızda mevcut ise  Harici ve Dahili hafıza kartı olmak üzere ikiye ayrılır.

İlk olarak Root dizinine erişmekle başlayalım. Root dizinindeki Storage "LG ve bazı cihazlarda adı MNT olabilir"

İlk Ekran Görüntüsü:


//Eklenmesi gereken USES : StrUtils
function GetRoot: String;
  function KacTane(Seperator,Str: String):Integer;
  begin
    Result := 0;
    while Pos(Seperator,Str) >0 do
    begin
      System.Delete(str,1,Pos(Seperator,str) );
      Inc(Result);
    end;
  end;
var
  Tmp: String;
begin
  Tmp := AnsiReverseString(TPath.GetSharedMusicPath);

  while KacTane('/',Tmp) > 1 do
  begin
    System.Delete(Tmp,1,Pos('/',Tmp) );
  end;
  Tmp := AnsiReverseString(Tmp);
  Result := Tmp + '/';
end;

Root dizinimizi bulduğumuza göre artık root dizinimizdeki klasörlerden sadece hafıza kartlarımızı
Listboxumuza eklemek kaldı. Bu olay içinde yine kendi hazırladığım procedure'e geçelim tekrar belirteyim ilkel olabilir tercih meselesi.

procedure HafizaListesi(Combo:TComboBox);
var
  FileList: TStringDynArray;
  s: string;
begin
    Combo.Items.Clear;
    FileList := TDirectory.GetDirectories(GetRoot);
    for s in FileList do
      if Pos('sd',LowerCase(s)) > 0 then
        Combo.items.Add(s);
end;

Şimdi sıra geldi yazdığımız kodların açıklamalarına:

TStringDynArray bildiğimiz Array of String yazılışının hızlı yazmak için kullanıldığı şeklidir aralarında hiçbir fark yoktur yani;
FileList değişkenimize TDirectory.GetDirectories("Klasör Dizini") fonksiyonu ile klasör dizinini belirtip içerisine Dizi elemanı olarak atayacağız. Bu işlemi "GetRoot" yani benim hazırlamış olduğum fonksiyon ile manuel olarak Root dizinini bulmuştuk ve tam olarak dizinin String karşılığını döndürmüştük.

Sıradaki işlemimiz içerisine Dizinler atanan FileList değişkenimizin içerisindekilerden sadece işimize yarayacak olanları almak.

Ben basit bir mantıkla araştırdığımda artık kendi baktığım cihazlarda diyim; Harici ve Dahili kartların hepsinin klasör isimelrinin içerisinde "sd" söz dilimi geçmektedir ve onların haricinde hiç gözüme çarpan olmadığı için sadece bir if sorgusu ile içerisinde "sd" geçenleri alabiliriz. Aldığımız dizi elemanlarınıda listboxa yazdırıyoruz.

Örnek Resim:
İşlemlerimiz bu kadardır. Buradan yola çıkarak kafanızda dosyalar ile ilgili birçok şeyin yapılabileceği belirebilir. Örneğin sadece Harici kartın yolunu öğrenmek istiyorsunuz if sorgusundaki "sd" yerine "ext" yazın Harici kartın yolunu getirecektir ve "ext" söz dilimi bütün harici kartlarda vardır.

Sürçü lisan olduysa affola.

Delphi Android ve IOS Mac adresi bulma

Örnek Resim

ANDROID:
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wInfo = wifiManager.getConnectionInfo();
String macAddress = wInfo.getMacAddress();


IOS:
 Uses
{$IFDEF IOS}
 iOSApi.UIKit;
{$ENDIF}

var
  {$IFDEF IOS}
    Device    : UIDevice;
  {$ENDIF}
begin
  {$IFDEF IOS}
    Device := TUIDevice.Wrap(TUIDevice.OCClass.currentDevice);
    ShowMessage(Device.uniqueIdentifier.UTF8String);
    ShowMessage(Device.identifierForVendor.UUIDString.UTF8String);
  {$ENDIF}
end;

23 Haziran 2014 Pazartesi

Delphi Dialog ile klasör seçme



with TFileOpenDialog.Create(nil) do
try
  Options := [fdoPickFolders];
  if Execute then
  begin
    //Buradan Dönen "FileName" ile bir değişkene seçilen klasör yolunu alabilirsiniz.
  end;
finally
  Free;
end;

Delphi XE6 Admob

XE6 Admob


 Merhabalar, Bu yazımda sizlere Embarcadero'nun bizlere sunmuş olduğu nimetlerden bir tanesinden bahsetmek istiyorum. XE6 Admob sayesinde artık uygulamalarından para kazanmak gibi düşüncesi olanlara şimdiden söyliyim gözünüzü çok yükseklere dikmeyin :) Burada Admob hesap nasıl açılır UnitID nasıl bulunur gibi anlatımlara girmek istemiyorum Hz. Google'a sorabilirsiniz size seve seve yardımcı olacaktır :) Örnek projemiz için bize lazım olan ekipman: 1 Adet Android Cihaz :) Formumuza Eklenecek olan elemanlar: 1-) TBannerAd 2-)Label 3-)Button İşlemlere başlamadan önce "INTERNET" ve "ACCESS_NETWORK_STATE" yetkilerinin açılmış olması gerektiğini unutmayalım. Görselliğe uyması için TBannerAd nesnemizin Align özelliğini Top yaptıktan sonra formumuza labeli ve butonu yerleştiriyoruz. Formun OnCreate Eventine:
BannerAd1.AdUnitID := 'ADMOB ID BURAYA';

Buton İçerisine :
BannerAd1.LoadAd;

Ve biraz işe aksiyon katmak istersek Reklamın ne kadar zaman boyunca izlendiğini labelimize yazdıralım. Bu iş için öncelikle "Var" bloğumuz altına "ActionBeginDate: TDateTime; WastedSeconds: Integer;" değişkenlerini tanımlıyoruz. TBannerAd nesnemizin Event sekmesinden OnActionCanBegin  içerisine  admobun aktif olduğu saati kayıt etmesi için: OnActionCanBegin
ActionBeginDate := Now;

Ve reklamlar arası geçiş, Reklama tıklanma vb. eventler olduğu zaman bu TBannerAd nesnemizin OnActionDidFinish Eventine yansayacaktır ve bizde bunu yakalıyalım: OnActionDidFinish
var
Seconds: Integer;
begin
Seconds := SecondsBetween(ActionBeginDate, Now);
WastedSeconds := WastedSeconds + Seconds;
Label1.Text := IntToStr(WastedSeconds) + ' boyunca reklam izlenmiş ve bitmiş.'


 Bu sayede Loglarımızı da tutmuş olabiliriz. Ayrıca yazılımcı kusursuz değildir "UnitID" olsun başka birşey olsun TBannerAd nesnesinde de olabilir birçok sorun cıkabilir bunun için TBannerAd nesnesinin "OnDidFail" eventine yazacağımız kodlar TBannerAd nesnesinde herhangi bir hata çıktığı anda aktif olacak olan eventtir. OnDidFail
Label1.Text := 'Hata : ' + Error;

Delphi IDE üzerinde yapacağımız değişiklikler bu kadardır sıradaki ve son işlemimiz "AndroidManifest.template.xml" dosyası içerisindedir.  <activity>  tagının bitim </activity>nin bir alt satırına aşağıda verdiğimi eklemeniz gerekmektedir. "<activity android:name="com.google.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>"

Android Cihazın üreten bilgilerini öğrenme

Android Cihazın üretini bilgilerini öğrenme

Test etmedim embarcaderonun formunda birisi sormuş oradan aldım.
Label1.Text := 'Manufacturer : ' + JStringToString(TJBuild.JavaClass.MANUFACTURER);

Delphi Variantın tipini öğrenme

Merhabalar, Bazen size dönecek olan variantın tipini bilmediğiniz zamanlar olur ozamanlarda aşağıdaki yazdıklarımı bilmeyen arkadaşlar için tam bir kabûs zamanıdır. Sadece variantı procedure'ye parametre olarak verirseniz size tipini söyleyecektir sizde bunu projenizde istediğiniz gibi değiştirip kullanabilirsiniz.

procedure ShowVariantType(varVar: Variant);
var
typeString : string;
begin

// Gelen variantın hangi tipe sahip olduğunu stringimize atıyoruz
case VarType(varVar) of
varEmpty : typeString := 'varEmpty';
varNull : typeString := 'varNull';
varSmallInt : typeString := 'varSmallInt';
varInteger : typeString := 'varInteger';
varSingle : typeString := 'varSingle';
varDouble : typeString := 'varDouble';
varCurrency : typeString := 'varCurrency';
varDate : typeString := 'varDate';
varOleStr : typeString := 'varOleStr';
varDispatch : typeString := 'varDispatch';
varError : typeString := 'varError';
varBoolean : typeString := 'varBoolean';
varVariant : typeString := 'varVariant';
varUnknown : typeString := 'varUnknown';
varByte : typeString := 'varByte';
varWord : typeString := 'varWord';
varLongWord : typeString := 'varLongWord';
varInt64 : typeString := 'varInt64';
varStrArg : typeString := 'varStrArg';
varString : typeString := 'varString';
varAny : typeString := 'varAny';
varTypeMask : typeString := 'varTypeMask';
end;

// Stringimize attığımız tipi artık ekranda gösterebiliriz
ShowMessage('Variantın tipi '+typeString);
end;

KAYNAK için tıklayınız!

XE5 - XE6 Android QR Code Okuma

Merhabalar,




Bu yazımda sizlere XE5 Android QR Code Okuma'dan bahsedeceğim ve tabiki siz isterseniz sadece QR yerine normal barcode bile okuyabilirsiniz size kalmış sadece göndereceğiniz parametre ile alakalı. Bu olay için kendime bir .pas dosyası hazırlamıştım, konu hiçbir şekilde bi yerden alıntı değildir. Lafı uzatmadan kodlarımıza geçelim. Hazırladığım .pas dosyasını buradan indirebilirsiniz!. Aşağıdaki kod parçalarını gerekli yerlere yazarsanız tam teşekkürlü bir Qr Code okucusunu XE5 üzerinden kullanmış olacaksınız. Ek olarak XE5'de Qr veya Barcode okumak için ZXing Barcode Scanner  programının cihazınızda yüklü olması gerekmektedir. Programın linki.

Aşağıdaki QR Codu okutabilirsiniz.


Uses
Android.QRCode
,FMX.Platform.Android
,FMX.Helpers.Android
,AndroidApi.JNI.GraphicsContentViewText
,AndroidApi.JNI.JavaTypes
,Androidapi.JNI.Net;

//Form Var
QRCodeScanner: TQRCode;

//FormCreate
QRCodeScanner := TQRCode.Create;
ZxingControl;

//FormDestroy
QRCodeScanner.Free;

//Scan Button - Tara Butonu
var
  Intent: jIntent;
begin

//İlk gönderilen parametre hangi Tür kod okutacağınızdır. Seçenekler:
//cmPRODUCT_MODE, cmQR_CODE_MODE, cmSCAN_MODE

  QRCodeScanner.Scan(cmQR_CODE_MODE, procedure(const Str: String)
  begin
    TThread.Synchronize(TThread.CurrentThread, procedure
    begin
      Memo1.Text := Str;
    end);
  end);

Ek olarak yazacağınız program için cihazda ZXing Barcode Scanner programının var olup olmadığını kendi kullandığım bir procedure ile kontrol etmiştim onuda sizler ile paylaşıyorum.

procedure ZxingControl;
  function GetZXingIntent: JIntent;
  const
    GOOGLE_ZXING = 'com.google.zxing.client.android.SCAN';
   GOOGLE_ZXING_PACKAGE = 'com.google.zxing.client.android';
 begin
    Result := TJIntent.JavaClass.init(StringToJString(GOOGLE_ZXING)); 
    Result.setPackage(StringToJString(GOOGLE_ZXING_PACKAGE)); 
  end;

  function IsIntentCallable(const AIntent: JIntent): Boolean;
  var
    LJPackageManager: JPackageManager; 
  begin
    Result := False; 
    if Assigned(AIntent) then 
    begin 
      LJPackageManager := SharedActivityContext.getPackageManager; 
      Result := LJPackageManager.queryIntentActivities(AIntent, 
      TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size <> 0; 
    end; 
  end;

  procedure OpenURL(const AURL: string);
  var
    LIntent: JIntent; 
  begin
    LIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, 
    TJnet_Uri.JavaClass.parse(StringToJString(AURL))); 
    MainActivity.startActivity(LIntent); 
  end;

Var
  LIsZXingCallable: Boolean;
begin //ANA BEGİN
  LIsZXingCallable := IsIntentCallable(GetZXingIntent);
  if not LIsZXingCallable then
  begin
    MessageDlg('Cihazda ZXing bulunamadı lütfen yükleyiniz!',TMsgDlgType.mtError,[TMsgDlgBtn.mbOK] , 0); 
    OpenURL('https://play.google.com/store/apps/details?id=com.google.zxing.client.android&hl=tr'); 
    MainActivity.finish(); 
  end;
end;

Delphi MD5 Şifreleme

Merhabalar, İlk defa yakın bir süre önce kendi projemde gerek duymamdan kaynaklanan sebeblerden dolayı araştırınca Delphinin MD5 şifreleme için kendi kütüphanelerinin olduğunu fark ettim ve bunu sizlerle paylaşmak istedim. Kullanımı çok basitir. Örnek kod ile göstermeye çalışacağım.

Uses IdHashMessageDigest; // Mutlaka ekliyoruz.

 

//Kullanımı

//Örneğin site ismimizi MD5 teknik ile şifreleyelim

IdMD5.HashStringAsHex('brsatalay.com');

//Dönen değer aşağıdakidir.

{E3BACBDA1115398D93FC2EFC06DA663E}

procedure TForm10.Md5ButtonClick(Sender: TObject);
var
IdMD5: TIdHashMessageDigest5;
begin
IdMD5 := TIdHashMessageDigest5.Create;
try
Memo1.Text := Memo1.Text + IdMD5.HashStringAsHex(edit1.Text) + #13+#10;
finally
IdMD5.Free;
end;
end;

DbGrid hücre renklendirme

DbGrid hücre renklendirme

Merhabalar, Eski yazılarımın bir tanesinde Cxgrid üzerinden renklendirmeyi anlatmıştım şimdi sıra Dbgrid'de hücre renklendirmeye geldi. Bunun için DbGridin DrawColumnCell  eventine girip önce işlemi yapacağımız Alan adının koşulunu sağlamalıyız bunun için if sorgumuzu aşağıdaki şekilde yazıyoruz.
if Column.FieldName = AnimesQryStates.FieldName then  //Benim alan adım States sizinki farklı birşey olabilir.

Sıra geldi bu Alanın değerlerinin koşullarını ele almaya mesela 3 tane Statümüz olsun Messenger gibi düşünelim (Uygun,Dışarda,Meşgul) durumlarımızı sırasıyla (0,1,2)  şeklinde değerler aldığını varsayarak renklendirme için kodlarımıza geçiyoruz.
case AnimesQryStates.AsInteger of //Ben case yaptım daha kısa anlasılır isteyen if sorguları ile uzatabilir
0: DBGrid1.Canvas.Brush.Color:=clGreen; // Durum Uygun ise
1: DBGrid1.Canvas.Brush.Color:=clYellow;// Durum Dışarda ise
2: DBGrid1.Canvas.Brush.Color:=clRed;// Durum Meşgul ise
end;


Android Google Play Store Manuel Uygulama Yükleme

Selamlar bu yazımda resimler ile XE5'de hazırladığımız uygulamanın nasıl Google Play Store için sitesinden yüklendiğini anlatacağım. Bu adımları izlerken google play hesabınızın var olduğunu kabul ediyorum, olmayanlar googleden araştırıp kolayca açabilirler. Göndereceğimiz APK; provizyon alınmış ve imzalanmış olması gerekmektedir. Yani DEBUG halindeki değil RELEASE halinde olmak zorunda. Resimler anlatıma başlayalım: Adım 1: Resimde gördüğünüz adımları tek tek uygulayalım.



Adım 2: Uygulamamızı kaydettiğimiz dizi içerisinden "\Android\Release\Akdeniz\bin" dosyasının içine kadar girelim ve 2. resimde gördüğünüz .apk dosyasını kolaylık olması için masasütüne kopyalayalım.



Adım 3: https://play.google.com/apps/publish/‎ adresine giriş yapılır. Adım 4: Ekranın orta kısmında gelen aşağıdaki resimdede göreceğiniz gibi "Yeni uygulama ekle" butonuna basarak APK yükleme sayfası açılır.



Adım 5: Ekrana gelen yerden uygulama dili ve uygulamamızın Google Play Store'de gözükmesini istediğiniz ismi yazılır ve APK yükle butonuna basılır.



Adım 6: %100 olup APK dosyanız yüklendikten sonra ayarlarını yapacağınız kısım açılır bu kısmı ben önce doldurduğum için bilgi amaçlı tek ekran resmi yüklüyorum fakat resimde kırmızı kutu içerisine alınmış 1. numaralı yere tıkladığınızda göreceğiniz üzerine uygulamanızın yayınlanması için zorunlu doldurmanız gereken yerleri orada size söylecektir. Eğer orada yazan zorunlu yerleri tamamlarsanız yine aynı  yere basınca göreceksiniz ki uygulama yayınlamaya müsait hâle gelmiştir. Yayınla butonuna basınca ortalama 1-3 saat arası bir sürede uygulamanız Google Play Store'de hizmete açılmış olacaktır.

 

XE5 Chat Ekranı | Whatsapp gibi

XE5 Chat Ekranı | Whatsapp gibi

Merhabalar, Bu yazımda whatsapp, facebook vb. uygulamalardaki chat ekranı yapısını anlatacağım. Sizde Rad Studio'nun XE5 ile bize sağladığı platform seçekleri ile birçok uygulama geliştirmişsinizdir ve bazılarımız da TCP Client Server yapısı veya vb.  yapılar ile kendilerine veya şirketlerine özel sohbet sistemi  yazmaya karar vermiştir. Fakat Rad Studionun bize chat için özel bir component sağladığı söylenemez bunu üzerine herkes kendi başının çaresine bakmaya çalışmaktadır. Yabancı kaynaktan bulduğum bu yapıyı tek bir procedure altında belirli parametreleri verip istediğimiz şekilde yönetmek için ve daha basite indirgeyip sizlerle paylaşmak için kolları sıvamış bulunmaktayım bakarsınız ileriki günlerde bunu componente dökebilirim :) Herşey zaman meselesi.. Neyse biz konumuza dönelim:



//ÖRNEK KULLANIM

NewMessage('R',// R= Sağdan  L= Soldan
           'Bu mesaj sağ tarafta çıkan bir mesajdır. www.brsatalay.com', // Mesajımız
           ChatScreen,//TVertScrollBox'un namesi
           Image1,// Gözükmesini istediğiniz resim, profil resmi olabilir.
           Self);/ Formumuzun adı

 

procedure NewMessage(IO, Messages: String; Parent: TVertScrollBox; Image: TImage;Form:TForm);
var
CR: TCalloutRectangle;
L: TText;
TmpImg: TImage;
begin
CR := TCalloutRectangle.Create(Form);
CR.Parent := Parent;
CR.Align := TAlignLayout.alTop;

if IO = 'R' then CR.CalloutPosition := TCalloutPosition.cpRight
else
if IO = 'L' then CR.CalloutPosition := TCalloutPosition.cpLeft;

CR.Margins.Top := 10;
CR.Margins.Bottom := 10;
CR.Margins.Left := 5;
CR.Height := 55;

L := TText.Create(Form);
L.Parent := CR;
L.Align := TAlignLayout.alClient;
L.Text := Messages;
L.Margins.Right := 15;
if IO = 'R' then
L.Margins.Left := 5
else if IO = 'L' then
L.Margins.Left := 15;
L.Width := CR.Width-20;

L.WordWrap := True;
L.AutoSize := True;

TmpImg := TImage.Create(Form);
TmpImg.Parent := CR;

if IO = 'R' then TmpImg.Align := TAlignLayout.alLeft
else
if IO = 'L' then TmpImg.Align := TAlignLayout.alRight;

TmpImg.Bitmap.Assign(Image.Bitmap);
TmpImg.Width := 65;
end;

 Kaynak

XE5 Android GetVersion | Application Version

XE5 Android GetVersion

Merhabalar bu yazıda uygulamamızın içerisinden info, about us gibi kendi uygulamamız bilgilerini listelediğimiz ekran için versiyon bilgisini native olarak bulmayı öğreneceğiz. Böyle bir olay için android sınıflarından "JPackageManager" kullanmamız gerekmektedir. Ben bu işi fonksiyon ile çağırdım sizde istediğiniz gibi kullanabilirsiniz.

uses// Eklenecek Kütüphaneler
Androidapi.JNI.JavaTypes,
FMX.Helpers.Android,
Androidapi.JNI.GraphicsContentViewText;

 

Function GetVersion: String;
var
PackageManager: JPackageManager;
PackageInfo : JPackageInfo;
begin
PackageManager := SharedActivity.getPackageManager;
PackageInfo := PackageManager.getPackageInfo(SharedActivityContext.getPackageName(), TJPackageManager.JavaClass.GET_ACTIVITIES);
Result := JStringToString(PackageInfo.versionName);
end;

  Not: Kodu stackoverflow.com adresinde gezinirken ilgimi çeken bir konuda bulmuştum konu linkinide veriyorum. Link

XE5 Android Native Takvim ve Etkinliklere erişim

Öncelikle Android 4.0 (API Level 14)'nin indirilmiş olması gerekmektedir. Eğer Apileriniz hazır ise kodlara geçebiliriz.
uses
  Androidapi.JNI.GraphicsContentViewText,
  FMX.Helpers.Android,
  Androidapi.JNI.JavaTypes;

procedure TForm1.Button1Click(Sender: TObject);
var
  Intent: JIntent;
  Calendar: JCalendar;
begin
  Calendar := TJCalendar.JavaClass.getInstance;
  Intent := TJIntent.Create;
  Intent.setType(StringToJString('vnd.android.cursor.item/event'));
  intent.putExtra(StringToJString('beginTime'), Calendar.getTimeInMillis());
  intent.putExtra(StringToJString('allDay'), true);
  intent.putExtra(StringToJString('rrule'), StringToJString('FREQ=YEARLY'));
  intent.putExtra(StringToJString('endTime'), Calendar.getTimeInMillis()+3600*1000);
  intent.putExtra(StringToJString('title'), StringToJString('Hello from Delphi'));
  SharedActivity.startActivity(Intent);
end;
  Not: Kodu stackoverflow.com adresinde gezinirken ilgimi çeken bir konuda bulmuştum konu linkinide veriyorum. Link

XE5 Android Splash Screen

Merhabalar, Bu yazımda XE5 Android Splash Screen kullanımından bahsedeceğim. Zaman zaman uygulamanız ilk açılışta internet yavaşlığından, verileri databaseden çekerken veya benzeri sebebler ile siyah ekranda birazda olsa bir bekleme süresi yapar amacımız bunun önüne geçip bizim kendi istediğimiz bir resimin bu ekranda gösterilmesi. ilk olarak: Projemizin anadizininde "res" adında bir klasör oluşturup içerisine Splash Screen'de gözükmesini istediğiniz resmi atıyoruz ben "Loading.png" olarak yaptım. Sonrasında bir .xml dosyası oluşturacas aynı "res" klasörüne atacas ve bunun adı "styles.xml" olacak içeriği ise:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<style name="MyTheme.NoTitleBar.CustomBackground" parent="@android:Theme.Black">
<item name="android:windowBackground">@drawable/loading</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
</resources>

Projemizi açıyoruz "Project>>Deployment" tıklayınca açılan sekmede sol üsteki "Add Files" butonuna basarak "res" klasörümüzün içerisindeki 2 dosyamızı seçiyoruz. Şimdi yapmamız gereken ekrana eklenen 2 dosyanın platform özelliğini sadece "Android" yapmak, bunun için eklediğimiz dosyalara sıra ile gelip "Platform" bölümünden seçip f2 basınca dikkatinizi çekecektir browse butonu aktif olur "..." şeklinde yanında yer alır tıklarak Ekrana gelen bölümde sadece Android seçili kalacak şekilde ikisinide ayarlıyoruz. Bir sonraki aşamamız "Remote Path" ayarlamalarıdır. Biraz önce yaptığımız gibi "Remote Path" bölümünden sıra ile eklediklerimize tıkladıktan sonra f2 basın göreceksiniz ki edit moda geçerek düzeltmenize izin verecektir. Bu sayede doğrusu aşağıdakiler olacak şekilde değiştiriniz.

Loading.png                  =               res\drawable-port
styles.xml                      =                res\values

Ayarlamaları yaptıktan sonra 1 kere CTRL + F9 basınız ve "AndroidManifest.template.xml" dosyasının oluşmasını sağlayacaktır. "AndroidManifest.template.xml" dosyasının içini açın ve android:theme="%theme%" olan yeri android:theme="@style/MyTheme.NoTitleBar.CustomBackground" olarak değiştiriniz. Dosyayı kaydettikten sonra F9 basarak Keyfini çıkarabilirsiniz.   Not: Bu anlatımı bir Çin sitesinden bulmuştum suan linkini tekrar bulamadığım için kaynak gösteremiyorum.

XE5 Android IMEI Okuma

XE5 Android IMEI Okuma

Merhabalar XE5 ile zaman ilerledikçe kendi uygulamalarımızı geliştirmeye devam ediyoruz. Günü geldikçede kendimizde lisanslı uygulamalar üretme isteği er yada geç uyanacağı kesindir. Bunun için birçok çeşitli yöntemler vardır; Kullanıcı adına göre, Modeme göre veya Cihaz sayısına göre buda IMEI numaraları ile gerçekleşmektedir. IMEI NEDIR?



Bu sayede yazdığınız uygulamalarda kullanıcıların kaç hesabı olursa olsun sizin belirlediğiniz IMEI numaralarına göre bir lisanslama gerçekleştirirseniz çaresiz sınırlar içerisinde kullanmak durumunda kalacaktır. Lafı fazla uzatmadan kodumuzu paylasıyorum bir fonksiyon içerisinde yazılı olan bu kodumuzun çalışması için Uses kısmına aşağıdakileride yazmayı unutmamanız gerekmektedir.
uses
Androidapi.JNI.Telephony, Androidapi.JNI.Provider ,
Androidapi.JNIBridge, Androidapi.JNI.GraphicsContentViewText,
Androidapi.JNI.JavaTypes,FMX.Helpers.Android;

READ_PHONE_STATE permission = true  //Okumak izin sağlamış oluyoruz

function IMEIOku():String;
var
obj     : JObject;
tm      : JTelephonyManager;
strIMEI : String;
begin
obj := SharedActivityContext.getSystemService(TJContext.JavaClass.TELEPHONY_SERVICE);
if obj <> nil then
begin
tm := TJTelephonyManager.Wrap( (obj as ILocalObject).GetObjectID );
if tm <> nil then
strIMEI := JStringToString(tm.getDeviceId);
end;
if strIMEI = '' then
strIMEI := JStringToString( TJSettings_Secure.JavaClass.getString( SharedActivity.getContentResolver, TJSettings_Secure.JavaClass.ANDROID_ID ) );
Result := strIMEI;
end;

    Bu güzel örneğini bizlere sunan Muharrem ARMAN (mrmarman) hocamıza teşekkürler.

XE5 Android diğer uygulamalara TEXT gönderme

Merhabalar, Bu yazıda kendi yazdığımız uygulama üzerinden text veri kabul eden diğer uygulamalara veri göndermeyi göreceğiz. Bu uygulamalar : Facebook, Wassap, Android SMS, Google Plus vb.
  


 Ben bir procedure içine yaptım kendi uygulamamda farklı yerlerde kullanacağım için
Uses,FMX.Helpers.Android,Androidapi.JNI.GraphicsContentViewText,Androidapi.JNI.JavaTypes,FMX.Platform.Android;

 

procedure Paylas(Str: String);
var
Intent: JIntent;
begin
Intent := TJIntent.Create;
Intent.setType(StringToJString('text/plain'));// Burada göndereceğimiz verinin türünü belirtiyoruz.

//Kullanacağı Android Sınıfı SEND olacak kendiniz SENDTO sınıfınıda araştırabilirsiniz karşınıza eğlenceli şey gelecektir.
Intent.setAction(TJIntent.JavaClass.ACTION_SEND);
Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT,
StringToJString(Str)); //Göndereğimiz metni ben Str değişkenine atamıştım oradan alıyor.
MainActivity.startActivity(Intent);
end;

XE5 Android ekran ayarları

Merhabalar, Bir çoğumuz projelerimizin hizalamalarında zaman zaman sorunlarla karşılaşırız ve dikeyde ayarladıklarımız her zaman yatayda sağlıklı gözükmeye bilir. Bu sebebden dolayı projelerimizi belirli ekran durumlarında sabit kullanmamız gerekebilir. Bu ekran ayarları nelerdir:
Dikey, Ters dikey, Her zaman sağa yatay, Her zaman sola yatay.
Şimdi bu ekran ayarlarını nasıl sabitleyeceğimizi Resimler ile görelim:



        

XE5 Android player ile online video

Merhabalar, Gerek dışardan belirli konularda yardım alarak gerekse kendi cabalarımla XE5'i daha fazla öğrenmeye çalışırken kendimce güzel bir örnek çıkardım ve düşündüm ki birçok arkadaşımız yararlanmak isteyebilir.
Projenin içeriği:
 ~VK.comdan XSuperObject yardımı ile Json verilerini parse edip Android playerde video izleme, ~Sibnet.com dan Android playerde video izleme,
~TurkanimeTv.net video playerinden Android playerde video izleme. Hatalarım varsa düzeltenleri için teşekkürler.

İndirmek  için tıklayın. - Download!



XE5 32-bit'de Mobil Preview Sorunu

Merhabalar, Birçok arkadaşımızında başına geldiğini düşünerek bulduğumuz kücük bir şeyi sizlerle paylaşmak istiyorum. Denemeleriniz üzerine Android veya IOS ortamında hazırladığınız uygulamayı daha hızlı bir şekilde debug vs. işleminden geçirmek istediğinizde platform seçeneklerinden 32-bit seçeneği ile windows ortamında çalıştırabilirsiniz. Fakat bu 32-bit çevrildiğinde componentlerin hiç birinin orjinal şekillerinde olmadığı dikkatinizi çekecektir. Uzun lafın kısası bahsettiğim şey:

 

 İşte bu resimde görmüş olduğunuz ekran gibi. Bu olay XE5 Update 2 ile gelmiştir. Eğer ki XE5 Update 2 sürümününe güncellemeden önce 32-bit platformunu eklemişseniz ilk önce kaldırınız ve tekrar 32-bit platformunu ekleyiniz ki Project.dpr dosyamızın Uses bölümüne FMX.MobilePreview kütüphanesini ekleyebilsin.

  

 Bu kısa işlemden sonra fark edeceksiniz ki StyleLookup'dan seçtiğiniz özellikleri Windows platformdada rahatça kullanabileceksiniz.

 Kaynaklar: http://blog.marcocantu.com/blog/fmx_mobile_preview_xe5upd2.html http://docwiki.embarcadero.com/RADStudio/XE5/en/Mobile_Preview

XE5 Android Video Açma

Herkese merhaba. Bu yazıda deploy ettiğimiz videoyu cihazın kendi video playeri ile çalıştıracağız. Benzer yöntemleri internetteki kaynaklardan edinebilirsiniz fakat en doğru yöntemi bilmemiz her zaman zorunludur. Resimdeki gibi bir ekran tasarlayabilirsiniz.

 
 

 Play butonuna aşağıdaki kodları yazıyoruz
procedure TForm1.Button1Click(Sender: TObject);
var
Intent: JIntent;
FileName, DestFileName: string;
Data: Jnet_Uri;
CompName: JComponentName;
const
VIDEO_FILENAME = 'videoviewdemo.mp4';
begin
FileName := System.IOUtils.TPath.GetDocumentsPath + PathDelim + VIDEO_FILENAME;
DestFileName := TPath.GetSharedDownloadsPath + PathDelim + VIDEO_FILENAME;
// Copy the file into a public path (you can use any public path)
TFile.Copy(FileName, DestFileName, true);
Data := TJnet_Uri.JavaClass.parse(StringToJString('file://' + DestFileName));
Intent := TJIntent.Create;
Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
if CheckBox1.IsChecked then
begin
CompName := TJComponentName.JavaClass.init(StringToJString('android'),
StringToJString('com.android.internal.app.ResolverActivity'));
Intent.setComponent(CompName);
end;
Intent.setDataAndType(Data, StringToJString('video/mp4'));
try
MainActivity.startActivity(Intent);
except
on E: Exception do
begin
Label1.Text := E.Message;
end;
end;
end;
Orjinal konu için tıklayınız. İngilizcem pek iyi sayılmaz ama anlayabildiğimce sizlere anlatmaya çalıştım.

Android Pdf Açma - Open PDF

uses
Androidapi.JNI.GraphicsContentViewText,
Androidapi.JNI.JavaTypes,
FMX.Helpers.Android;

procedure TForm3.Button1Click(Sender: TObject);
var
Intent: JIntent;
begin
Intent := TJIntent.Create;
Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
Intent.setDataAndType(StrToJURI('filepath'), StringToJString('application/pdf'));
SharedActivity.startActivity(Intent);
end;

Android kütüphanelerini XE5'de kullanma

Android ortamındaki tüm kütüphaneler henüz Delphi tarafından implemente edilmiş durumda değil. Ancak; ilgili sınıfları delphi ortamına implemente etmek genellikle çok da zor olmuyor. Bunun için d.android.com adresinden ilgili sınıfı bulup; öncelikle sınıf içinde static olan metodların varlığını kontrol etmelisiniz. Bunları bir köşeye not edin, ardından sınıf içinde constant(sabit) olarak tanımlı olan değişkenleri bulun, bunları da bir köşeye not edin. Şimdi not ettiğiniz static metodlar ve const sabitler için bir sınıf tanımlamalısınız. Kısaca bir örnek vermek gerekir ise; d.android.com'dan Toast sınıfını inceleyelim; (http://developer.android.com/reference/android/widget/Toast.html) java.lang.Object ↳ android.widget.Toast Gördüğünüz gibi sınıf, Object sınıfından türetilmiş. Demekki bizde Delphi tarafında Java Object sınıfından türeteceğiz sınıfımızı. Const bölümündeki tanımlarımıza da bakalım; int LENGTH_LONG Show the view or text notification for a long period of time. int LENGTH_SHORT Show the view or text notification for a short period of time. Görüldüğü üzere iki adet sabit tanım mevcut. Şimdi static metodlarımızı arayalım. static Toast makeText(Context context, int resId, int duration) Make a standard toast that just contains a text view with the text from a resource. static Toast makeText(Context context, CharSequence text, int duration) Make a standard toast that just contains a text view. Yukarıda görüldüğü gibi 2 adet static metodumuz var. Yazımın başında da belirttiğim gibi, static olan metodları ve sabit tanımları bir sınıf içinde yazacaktık. Hadi onu yazalım;
JToast = interface;

JToastClass = interface(JObjectClass)
['{Ctrl+Shift+G ye basınız}']
function GetLengthLong : Integer; cdecl;
function GetLengthShort : Integer; cdecl;

function makeText(Context : JContext; ResID : Integer; Duration : Integer) : JToast; cdecl;
function makeText(Context : JContext; Text : JCharSequence; Duration : Integer) : JToast; cdecl;

property LENGTH_LONG : Integer read GetLengthLong;
property LENGTH_SHORT: Integer read GetLengthShort;
end;
d.android.com da Toast sınıfı içindeki istediğimiz sabit tanımları ve static metodları bulup yukarıdaki interface'de implemente ettik. Dikkatinizi çekeceği gibi, interface'imiz JObjectClass interface'inden türüyor. Bunun sebebi Toast android sınıfının da Java Object sınıfından türüyor olması idi. Eğer Toast java domates sınıfından türüyor olsa idi, bu durumda bizim interface'imiz de JDomatesClass gibi bir interface'den türeyecekti. Delphi'ciler pek çok sınıfı bizim için implemente etmişler ama JDomatesClass gibi bir tanımlama bulamıyorsanız bu durumda o interface'i de sizin implemente etmeniz icap edecekti. Neyseki buna pek gerek kalmıyor. Ardından; dikkat çeken başka bir nokta ise; metodların cdecl ile işaretlenmesi gerekliliği. Şimdi hızlıca ilerlemeye devam edelim. Henüz işimiz bitmedi. Şimdi JToast interface'ini implemente etmeliyiz.
[JavaSignature('android/widget/Toast')]
JToast = interface(JObject)
['{Ctrl+Shift+G ye basınız}']
procedure cancel; cdecl;
function getDuration : Integer; cdecl;
function getHorizontalMargin : Single; cdecl;
..
..
..
end;
Yukarıdaki interface'imizde ise en önemli nokta JavaSignature attribute'si. İlgili interface'i bu attribute ile işaretliyoruz. Peki JavaSignature attributesi içindeki 'android/widget/Toast' da neyin nesi diyebilirsiniz. O da d.android.com 'da Toast yardımında görebileceğiniz gibi ilgili sınıfın hiyerarşisini gösteriyor. (java.lang.Object ↳ android.widget.Toast) Yine yukarıdaki interface'de dikkatinizi çekmiştir, java'da void olan dönüş türleri bir şey dönmeyecek anlamına gelir, Delphi'de de bu procedure ile temsil edildiğinden cancel metodu procedure olarak tanımlanmıştır. Ayrıca belirtmek isterim ki, android sınıfının içindeki tüm metodları implemente etmek zorunda değilsiniz, sadece ilgilendiklerinizi implemente edebilirsiniz. Henüz test etmedim ama büyük ihtimalle büyük-küçük harf ayrımına da dikkat etmeniz faydalı olacaktır. Şimdi son aşamaya geldik. Malumunuz olduğu üzere, Delphi'de herhangi bir interface'i direkt olarak create edemiyoruz. Bu interface'i implemente edecek bir sınıfa ihtiyacımız var. İlgili interface'e o sınıf instance'ı üzerinden erişim sağlayacağız. Bu vesile ile son adım olarak bir de sınıf deklare etmemiz gerekiyor. Hadi onu da yazalım;
TSucukluTost = class(TJavaGenericImport<JToastClass, JToast>)
end;
İşte bu kadar basit; artık kodlarımız içinden TSucukluTost.JavaClass.makeText(SharedActivityContext, StrToJCharSequence('Deneme'), TJToast.JavaClass.LENGTH_SHORT).show; biçiminde kullanabiliriz. Diğer sınıflar elbette bundan çok daha karmaşık olacaktır, ancak benzer adımları izleyerek sonuçlara ulaşabilirsiniz. Tabii bir çok java nesnesinin delphi'cesinin yazıldığı ilgili unitleri'de uses ile eklemeyi unutmamalısınız. Örneğin;
Androidapi.JNIBridge,
Androidapi.JNI.JavaTypes,
Androidapi.JNI.GraphicsContentViewText,
FMX.Helpers.Android;
Kolay gelsin   Bu konuyu bizimle paylaşan Tuğrul HELVACI  hocamıza teşekkür ederim. DelphiForumu.com'dan alıntıdır. Orjinal KonuAndroid ortamındaki tüm kütüphaneler henüz Delphi tarafından implemente edilmiş durumda değil. Ancak; ilgili sınıfları delphi ortamına implemente etmek genellikle çok da zor olmuyor. Bunun için d.android.com adresinden ilgili sınıfı bulup; öncelikle sınıf içinde static olan metodların varlığını kontrol etmelisiniz. Bunları bir köşeye not edin, ardından sınıf içinde constant(sabit) olarak tanımlı olan değişkenleri bulun, bunları da bir köşeye not edin. Şimdi not ettiğiniz static metodlar ve const sabitler için bir sınıf tanımlamalısınız. Kısaca bir örnek vermek gerekir ise; d.android.com'dan Toast sınıfını inceleyelim; (http://developer.android.com/reference/android/widget/Toast.html) java.lang.Object ↳ android.widget.Toast Gördüğünüz gibi sınıf, Object sınıfından türetilmiş. Demekki bizde Delphi tarafında Java Object sınıfından türeteceğiz sınıfımızı. Const bölümündeki tanımlarımıza da bakalım; int LENGTH_LONG Show the view or text notification for a long period of time. int LENGTH_SHORT Show the view or text notification for a short period of time. Görüldüğü üzere iki adet sabit tanım mevcut. Şimdi static metodlarımızı arayalım. static Toast makeText(Context context, int resId, int duration) Make a standard toast that just contains a text view with the text from a resource. static Toast makeText(Context context, CharSequence text, int duration) Make a standard toast that just contains a text view. Yukarıda görüldüğü gibi 2 adet static metodumuz var. Yazımın başında da belirttiğim gibi, static olan metodları ve sabit tanımları bir sınıf içinde yazacaktık. Hadi onu yazalım;
JToast = interface;

JToastClass = interface(JObjectClass)
['{Ctrl+Shift+G ye basınız}']
function GetLengthLong : Integer; cdecl;
function GetLengthShort : Integer; cdecl;

function makeText(Context : JContext; ResID : Integer; Duration : Integer) : JToast; cdecl;
function makeText(Context : JContext; Text : JCharSequence; Duration : Integer) : JToast; cdecl;

property LENGTH_LONG : Integer read GetLengthLong;
property LENGTH_SHORT: Integer read GetLengthShort;
end;
d.android.com da Toast sınıfı içindeki istediğimiz sabit tanımları ve static metodları bulup yukarıdaki interface'de implemente ettik. Dikkatinizi çekeceği gibi, interface'imiz JObjectClass interface'inden türüyor. Bunun sebebi Toast android sınıfının da Java Object sınıfından türüyor olması idi. Eğer Toast java domates sınıfından türüyor olsa idi, bu durumda bizim interface'imiz de JDomatesClass gibi bir interface'den türeyecekti. Delphi'ciler pek çok sınıfı bizim için implemente etmişler ama JDomatesClass gibi bir tanımlama bulamıyorsanız bu durumda o interface'i de sizin implemente etmeniz icap edecekti. Neyseki buna pek gerek kalmıyor. Ardından; dikkat çeken başka bir nokta ise; metodların cdecl ile işaretlenmesi gerekliliği. Şimdi hızlıca ilerlemeye devam edelim. Henüz işimiz bitmedi. Şimdi JToast interface'ini implemente etmeliyiz.
[JavaSignature('android/widget/Toast')]
JToast = interface(JObject)
['{Ctrl+Shift+G ye basınız}']
procedure cancel; cdecl;
function getDuration : Integer; cdecl;
function getHorizontalMargin : Single; cdecl;
..
..
..
end;
Yukarıdaki interface'imizde ise en önemli nokta JavaSignature attribute'si. İlgili interface'i bu attribute ile işaretliyoruz. Peki JavaSignature attributesi içindeki 'android/widget/Toast' da neyin nesi diyebilirsiniz. O da d.android.com 'da Toast yardımında görebileceğiniz gibi ilgili sınıfın hiyerarşisini gösteriyor. (java.lang.Object ↳ android.widget.Toast) Yine yukarıdaki interface'de dikkatinizi çekmiştir, java'da void olan dönüş türleri bir şey dönmeyecek anlamına gelir, Delphi'de de bu procedure ile temsil edildiğinden cancel metodu procedure olarak tanımlanmıştır. Ayrıca belirtmek isterim ki, android sınıfının içindeki tüm metodları implemente etmek zorunda değilsiniz, sadece ilgilendiklerinizi implemente edebilirsiniz. Henüz test etmedim ama büyük ihtimalle büyük-küçük harf ayrımına da dikkat etmeniz faydalı olacaktır. Şimdi son aşamaya geldik. Malumunuz olduğu üzere, Delphi'de herhangi bir interface'i direkt olarak create edemiyoruz. Bu interface'i implemente edecek bir sınıfa ihtiyacımız var. İlgili interface'e o sınıf instance'ı üzerinden erişim sağlayacağız. Bu vesile ile son adım olarak bir de sınıf deklare etmemiz gerekiyor. Hadi onu da yazalım;
TSucukluTost = class(TJavaGenericImport<JToastClass, JToast>)
end;
İşte bu kadar basit; artık kodlarımız içinden TSucukluTost.JavaClass.makeText(SharedActivityContext, StrToJCharSequence('Deneme'), TJToast.JavaClass.LENGTH_SHORT).show; biçiminde kullanabiliriz. Diğer sınıflar elbette bundan çok daha karmaşık olacaktır, ancak benzer adımları izleyerek sonuçlara ulaşabilirsiniz. Tabii bir çok java nesnesinin delphi'cesinin yazıldığı ilgili unitleri'de uses ile eklemeyi unutmamalısınız. Örneğin;
Androidapi.JNIBridge,
Androidapi.JNI.JavaTypes,
Androidapi.JNI.GraphicsContentViewText,
FMX.Helpers.Android;
Kolay gelsin   Bu konuyu bizimle paylaşan Tuğrul HELVACI  hocamıza teşekkür ederim. DelphiForumu.com'dan alıntıdır. Orjinal KonuAndroid ortamındaki tüm kütüphaneler henüz Delphi tarafından implemente edilmiş durumda değil. Ancak; ilgili sınıfları delphi ortamına implemente etmek genellikle çok da zor olmuyor. Bunun için d.android.com adresinden ilgili sınıfı bulup; öncelikle sınıf içinde static olan metodların varlığını kontrol etmelisiniz. Bunları bir köşeye not edin, ardından sınıf içinde constant(sabit) olarak tanımlı olan değişkenleri bulun, bunları da bir köşeye not edin. Şimdi not ettiğiniz static metodlar ve const sabitler için bir sınıf tanımlamalısınız. Kısaca bir örnek vermek gerekir ise; d.android.com'dan Toast sınıfını inceleyelim; (http://developer.android.com/reference/android/widget/Toast.html) java.lang.Object ↳ android.widget.Toast Gördüğünüz gibi sınıf, Object sınıfından türetilmiş. Demekki bizde Delphi tarafında Java Object sınıfından türeteceğiz sınıfımızı. Const bölümündeki tanımlarımıza da bakalım; int LENGTH_LONG Show the view or text notification for a long period of time. int LENGTH_SHORT Show the view or text notification for a short period of time. Görüldüğü üzere iki adet sabit tanım mevcut. Şimdi static metodlarımızı arayalım. static Toast makeText(Context context, int resId, int duration) Make a standard toast that just contains a text view with the text from a resource. static Toast makeText(Context context, CharSequence text, int duration) Make a standard toast that just contains a text view. Yukarıda görüldüğü gibi 2 adet static metodumuz var. Yazımın başında da belirttiğim gibi, static olan metodları ve sabit tanımları bir sınıf içinde yazacaktık. Hadi onu yazalım;
JToast = interface;

JToastClass = interface(JObjectClass)
['{Ctrl+Shift+G ye basınız}']
function GetLengthLong : Integer; cdecl;
function GetLengthShort : Integer; cdecl;

function makeText(Context : JContext; ResID : Integer; Duration : Integer) : JToast; cdecl;
function makeText(Context : JContext; Text : JCharSequence; Duration : Integer) : JToast; cdecl;

property LENGTH_LONG : Integer read GetLengthLong;
property LENGTH_SHORT: Integer read GetLengthShort;
end;
d.android.com da Toast sınıfı içindeki istediğimiz sabit tanımları ve static metodları bulup yukarıdaki interface'de implemente ettik. Dikkatinizi çekeceği gibi, interface'imiz JObjectClass interface'inden türüyor. Bunun sebebi Toast android sınıfının da Java Object sınıfından türüyor olması idi. Eğer Toast java domates sınıfından türüyor olsa idi, bu durumda bizim interface'imiz de JDomatesClass gibi bir interface'den türeyecekti. Delphi'ciler pek çok sınıfı bizim için implemente etmişler ama JDomatesClass gibi bir tanımlama bulamıyorsanız bu durumda o interface'i de sizin implemente etmeniz icap edecekti. Neyseki buna pek gerek kalmıyor. Ardından; dikkat çeken başka bir nokta ise; metodların cdecl ile işaretlenmesi gerekliliği. Şimdi hızlıca ilerlemeye devam edelim. Henüz işimiz bitmedi. Şimdi JToast interface'ini implemente etmeliyiz.
[JavaSignature('android/widget/Toast')]
JToast = interface(JObject)
['{Ctrl+Shift+G ye basınız}']
procedure cancel; cdecl;
function getDuration : Integer; cdecl;
function getHorizontalMargin : Single; cdecl;
..
..
..
end;
Yukarıdaki interface'imizde ise en önemli nokta JavaSignature attribute'si. İlgili interface'i bu attribute ile işaretliyoruz. Peki JavaSignature attributesi içindeki 'android/widget/Toast' da neyin nesi diyebilirsiniz. O da d.android.com 'da Toast yardımında görebileceğiniz gibi ilgili sınıfın hiyerarşisini gösteriyor. (java.lang.Object ↳ android.widget.Toast) Yine yukarıdaki interface'de dikkatinizi çekmiştir, java'da void olan dönüş türleri bir şey dönmeyecek anlamına gelir, Delphi'de de bu procedure ile temsil edildiğinden cancel metodu procedure olarak tanımlanmıştır. Ayrıca belirtmek isterim ki, android sınıfının içindeki tüm metodları implemente etmek zorunda değilsiniz, sadece ilgilendiklerinizi implemente edebilirsiniz. Henüz test etmedim ama büyük ihtimalle büyük-küçük harf ayrımına da dikkat etmeniz faydalı olacaktır. Şimdi son aşamaya geldik. Malumunuz olduğu üzere, Delphi'de herhangi bir interface'i direkt olarak create edemiyoruz. Bu interface'i implemente edecek bir sınıfa ihtiyacımız var. İlgili interface'e o sınıf instance'ı üzerinden erişim sağlayacağız. Bu vesile ile son adım olarak bir de sınıf deklare etmemiz gerekiyor. Hadi onu da yazalım;
TSucukluTost = class(TJavaGenericImport<JToastClass, JToast>)
end;
İşte bu kadar basit; artık kodlarımız içinden TSucukluTost.JavaClass.makeText(SharedActivityContext, StrToJCharSequence('Deneme'), TJToast.JavaClass.LENGTH_SHORT).show; biçiminde kullanabiliriz. Diğer sınıflar elbette bundan çok daha karmaşık olacaktır, ancak benzer adımları izleyerek sonuçlara ulaşabilirsiniz. Tabii bir çok java nesnesinin delphi'cesinin yazıldığı ilgili unitleri'de uses ile eklemeyi unutmamalısınız. Örneğin;
Androidapi.JNIBridge,
Androidapi.JNI.JavaTypes,
Androidapi.JNI.GraphicsContentViewText,
FMX.Helpers.Android;
Kolay gelsin   Bu konuyu bizimle paylaşan Tuğrul HELVACI  hocamıza teşekkür ederim. DelphiForumu.com'dan alıntıdır. Orjinal Konu

Android geri tuşu iptali

Formun keydown eventinin içine

if Key = vkHardwareBack then// Buradaki Cihazın geri tusunu temsil etmektedir.

begin

Key := 0;

end;

WebBrowser ile pdf okuma


filename := TPath.Combine(TPath.GetDocumentsPath, 'Test.pdf');
WebBrowser1.Navigate('file:/' + filename);

Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir.  Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

Mail Gönderme - Android Send Mail


uses
FMX.Helpers.Android,
Androidapi.JNIBridge,
Androidapi.JNI.JavaTypes,
Androidapi.JNI.GraphicsContentViewText;
...
procedure CreateEmail(const Recipient, Subject, Content: string);
var
Intent: JIntent;
Recipients: TJavaObjectArray<JString>;
begin
Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_SEND);
Recipients := TJavaObjectArray<JString>.Create(1);
Recipients.Items[0] := StringToJString(Recipient);
Intent.putExtra(TJIntent.JavaClass.EXTRA_EMAIL, Recipients);
Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(Subject));
Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(Content));
//Intent.setType(StringToJString('plain/text'));
Intent.setType(StringToJString('message/rfc822'));
//SharedActivity.startActivity(Intent);
SharedActivity.startActivity(TJIntent.JavaClass.createChooser(Intent,
StrToJCharSequence('Which email app?')));
end;

  Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir.  Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

Android SMS gönder- Android Send SMS


Örnek 1:

//Öncelikle izinlerimizi açalım Project/Options/Permissions "app to send SMS"  seçili olmalı.
//Remember to go into Project/Options/Permissions and allow the app to send SMS. The code is:

uses
FMX.Helpers.Android,
Androidapi.JNI.GraphicsContentViewText,
Androidapi.JNI.Net,
Androidapi.JNI.JavaTypes,
Androidapi.JNI.Telephony;

procedure SendSMS (target,messagestr:string);
var
smsManager: JSmsManager;
smsTo: JString;
begin
smsManager:= TJSmsManager.JavaClass.getDefault;
smsTo:= StringToJString(target);
smsManager.sendTextMessage(smsTo, nil, StringToJString(messagestr), nil, nil);
end;
*************************************************
Örnek 2:

Try to pass empty value (nil) to the scAddress parameter of the sendTextMessage function call to use the current default SMS center:

uses
Androidapi.JNI.JavaTypes, Androidapi.JNI.Telephony;

procedure TForm1.Button1Click(Sender: TObject);
var
smsTo: JString;
smsManager: JSmsManager;
begin
smsManager := TJSmsManager.JavaClass.getDefault;
smsTo := StringToJString('091...');
smsManager.sendTextMessage(smsTo, nil, StringToJString('Test SMS'), nil, nil);
end;

  Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir.  Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

SMS geldiğinde uyarı - SMS Notification


************JAVA***********
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
Take a look at BroadCastReceivers you must implement and register a Reciever for android.provider.Telephony.SMS_RECEIVED

Here is a code snippet that lets you read messages as they arrive.
public class SMSReceiver extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent)
{
Bundle myBundle = intent.getExtras();
SmsMessage [] messages = null;
String strMessage = "";

if (myBundle != null)
{
Object [] pdus = (Object[]) myBundle.get("pdus");
messages = new SmsMessage[pdus.length];

for (int i = 0; i < messages.length; i++)
{
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
strMessage += "SMS From: " + messages[i].getOriginatingAddress();
strMessage += " : ";
strMessage += messages[i].getMessageBody();
strMessage += "n";
}

Toast.makeText(context, strMessage, Toast.LENGTH_SHORT).show();
}
}
}
And here what you have to add to your AndroidManifest.xml file:

<receiver android:name=".SMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>

  Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir.  Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

Android Rehber Oku - Read guide


USES Androidapi.JNI.GraphicsContentViewText,
FMX.Helpers.Android,
Androidapi.JNI.Provider,
Androidapi.JNI.JavaTypes;

function RehberOku: TStringList;
var
cContacts,
cContactsPhone : JCursor;
iNumaraSayisi : Integer;
iIdx : Int64;
strGorunenAd,
strTelNo,
strKisiID : string;
begin
Result := TStringList.Create;
cContacts := SharedActivity.getContentResolver.query( TJContactsContract_Contacts.JavaClass.CONTENT_URI, nil, nil, nil, nil );
if (cContacts.getCount > 0) then
begin
while (cContacts.moveToNext) do
begin
iIdx := cContacts.getLong( cContacts.getColumnIndex(StringToJString('_ID')) );
strGorunenAd := JStringToString(cContacts.getString(cContacts.getColumnIndex(StringToJString('DISPLAY_NAME'))));
iNumaraSayisi := cContacts.getInt(cContacts.getColumnIndex(StringToJString('HAS_PHONE_NUMBER')));
if (iNumaraSayisi > 0) then
begin
cContactsPhone := SharedActivity.getContentResolver.query(TJCommonDataKinds_Phone.JavaClass.CONTENT_URI, nil,StringToJString('CONTACT_ID = ' + IntToStr(iIdx)),nil, nil);
while (cContactsPhone.moveToNext) do
begin
strTelNo := JStringToString(cContactsPhone.getString(cContactsPhone.getColumnIndex(StringToJString('DATA1'))));
strKisiID := JStringToString(cContactsPhone.getString(cContactsPhone.getColumnIndex(StringToJString('CONTACT_ID'))));
Result.Add(strGorunenAd + ': ' + strTelNo);
end;
cContactsPhone.close;
end;
end;
end;
cContacts.close;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Items.AddStrings( RehberOku() );
end;

Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir. Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

SD kart klasör listesi - SD folder list

Uses bloğuna System.IOUtils ekleyiniz.

uses

System.IOUtils, System.Types;

procedure TForm1.Button1Click(Sender: TObject);
var
FileList: TStringDynArray;
DocDir: string;
s: string;
begin
Memo1.Lines.Clear;
DocDir := TPath.GetDocumentsPath;
FileList := TDirectory.GetFiles(DocDir);
for s in FileList do
Memo1.Lines.Add(s);
end;

  Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir.  Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

XE5 - XE6 Projenin adını değiştirme - Change project name

~Project ~Project Option ~Version ~Label Projenin adını istediğiniz gibi düzenleyebilirsiniz - I changed with the name I wanted

MyDAC bağlantı Ayarları


var
Connection: TMyConnection;
begin
Connection := TMyConnection.Create(nil);
try
Connection.Options.Direct := True;
Connection.Server := 'server';
Connection.Port := 3306;
Connection.Database := 'database_name';
Connection.Username := 'user_name';
Connection.Password := 'password';
Connection.Connect;
finally
Connection.Free;
end;
end;

Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir. Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

İnternet bağlantısı - Internet connection


uses
Androidapi.JNI.Location,
Androidapi.JNIBridge,
FMX.Helpers.Android,
Androidapi.JNI.GraphicsContentViewText;

{$R *.fmx}

 

procedure TForm1.Button1Click(Sender: TObject);
var
locationManager : JLocationManager;
begin
locationManager := TJLocationManager.Wrap( ((SharedActivity.getSystemService(TJContext.JavaClass.LOCATION_SERVICE)) as ILocalObject).GetObjectID);

if locationManager.isProviderEnabled(TJLocationManager.JavaClass.GPS_PROVIDER) then
; //do something

if locationManager.isProviderEnabled(TJLocationManager.JavaClass.NETWORK_PROVIDER) then
; //do something else
end;

Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir. Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

Geri tuşu işlemleri - Back Button


uses
FMX.Platform, FMX.VirtualKeyboard;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
var
FService : IFMXVirtualKeyboardService;
begin
if Key = vkHardwareBack then
begin
TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
if (FService <> nil) and (vksVisible in FService.VirtualKeyBoardState) then
begin
// Back button pressed, keyboard visible, so do nothing...
end else
begin
// Back button pressed, keyboard not visible or not supported on this platform, lets exit the app...
if MessageDlg('Exit Application?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbOK, TMsgDlgBtn.mbCancel], -1) = mrOK then
begin
// Exit application here...
end else
begin
// They changed their mind, so ignore the Back button press...
Key := 0;
end;
end;
end
...
end;

Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir. Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

Inboxa düşen SMSler


uses
SysUtils,
FMX.Helpers.Android,
Androidapi.JNI.GraphicsContentViewText,
Androidapi.JNI.Net,
Androidapi.JNI.JavaTypes,
Androidapi.JNI.Telephony;

function FetchSms:string;
var
cursor: JCursor;
uri: Jnet_Uri;
address,person,msgdatesent,protocol,msgread,msgstatus,msgtype,
msgreplypathpresent,subject,body,
servicecenter,locked:string;
msgunixtimestampms:int64;
addressidx,personidx,msgdateidx,msgdatesentidx,protocolidx,msgreadidx,
msgstatusidx,msgtypeidx,msgreplypathpresentidx,subjectidx,bodyidx,
servicecenteridx,lockedidx:integer;
begin
uri:=StrToJURI('content://sms/inbox');
cursor := SharedActivity.getContentResolver.query(uri, nil, nil,nil,nil);
addressidx:=cursor.getColumnIndex(StringToJstring('address'));
personidx:=cursor.getColumnIndex(StringToJstring('person'));
msgdateidx:=cursor.getColumnIndex(StringToJstring('date'));
msgdatesentidx:=cursor.getColumnIndex(StringToJstring('date_sent'));
protocolidx:=cursor.getColumnIndex(StringToJstring('protocol'));
msgreadidx:=cursor.getColumnIndex(StringToJstring('read'));
msgstatusidx:=cursor.getColumnIndex(StringToJstring('status'));
msgtypeidx:=cursor.getColumnIndex(StringToJstring('type'));
msgreplypathpresentidx:=cursor.getColumnIndex(StringToJstring('reply_path_present'));
subjectidx:=cursor.getColumnIndex(StringToJstring('subject'));
bodyidx:=cursor.getColumnIndex(StringToJstring('body'));
servicecenteridx:=cursor.getColumnIndex(StringToJstring('service_center'));
lockedidx:=cursor.getColumnIndex(StringToJstring('locked'));
while (cursor.moveToNext) do begin
address:=JStringToString(cursor.getString(addressidx));
person:=JStringToString(cursor.getString(personidx));
msgunixtimestampms:=cursor.getLong(msgdateidx);
msgdatesent:=JStringToString(cursor.getString(msgdatesentidx));
protocol:=JStringToString(cursor.getString(protocolidx));
msgread:=JStringToString(cursor.getString(msgreadidx));
msgstatus:=JStringToString(cursor.getString(msgstatusidx));
msgtype:=JStringToString(cursor.getString(msgtypeidx));
msgreplypathpresent:=JStringToString(cursor.getString(msgreplypathpresentidx));
subject:=JStringToString(cursor.getString(subjectidx));
body:=JStringToString(cursor.getString(bodyidx));
servicecenter:=JStringToString(cursor.getString(servicecenteridx));
locked:=JStringToString(cursor.getString(lockedidx));
Result:=IntToStr(trunc(msgunixtimestampms/1000))+' '+address+' '+body;
end;
end;

Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir. Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

Android Dosya yolları - Android Path

Uses bloğuna System.IoUtils.TPath ekleyin.

uses
SysUtils;
var
AppPath, CardPath: string;
AppPath := TPath.GetHomePath;
CardPath := TPath.GetDocumentsPath;
Örnek: GetTempPath GetPublicPath GetCameraPath GetMusicPath GetDownloadsPath Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir. Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

Android Çıkış sorgusu


procedure TfMain.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
begin
if Key = vkHardwareBack then
begin
Key := 0;
if TabControl.ActiveTab = TabItem1 then
begin
if MessageDlg('Çıkmak istediğinize emin misiniz?', TMsgDlgType.mtWarning, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0) = mrYes then
begin
MainActivitiy.Finish;
end;
end else
begin
ChangeTabAction1.Execute;
end;
end;
end;

Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir. Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

Android Ses oynatma - Android Play Sound

From Delphi IDE click on "Project". Then select "Resources and Images...". Choose your media file and set it as RCDATA. Remember your resource identifier. Note: Make sure the media type is supported by TMediaPlayer otherwise it won't work.

procedure PlayAudio(ResourceID: string);
var
ResStream: TResourceStream;
TmpFile: string;
begin
ResStream := TResourceStream.Create(HInstance, ResourceID, RT_RCDATA);
try
TmpFile := TPath.Combine(TPath.GetTempPath, 'tmp.mp3');

ResStream.Position := 0;
ResStream.SaveToFile(TmpFile);
MediaPlayer1.FileName := TmpFile;

MediaPlayer1.Play;

finally
ResStream.Free;
end;
end;
//Kullanımı:

PlayAudio('Resource_1');

Önemli Not: Kodlarımın çoğu farklı kaynaklardan not defterlerine toplanarak biriktirilmiştir. Bu sebeble bir çoğunda Kaynak belirtemiyorum. Bu gibi durumda olan ve kaynağını bildiğiniz bir Kod Yazım var ise yorum olarak bildirmeniz rica olur. Saygılar.

XE5 Mobil Uygulamada SQLite Veritabanı kullanımı

XE5 Mobil Uygulamada SQLite Veritabanı kullanımı
 



Merhabalar, Biraz sonra baslayacağımız örnekte XE5 Android üzerinden manuel olarak kod ile sqlite bağlantı, silme, ekleme ve listvievin otomatik yenilenmesi islemlerini göreceğiz. Bu işlemi gerçekleştirmek için birçok yöntem vardır ve ben XE5'in bize sunduğu FireDAC aracılığı ile yapacağım. İnternette XE5 hakkında türkçe çok sıkıntılı oldugu için bende kendi çerçevemde yapabildiğim kadar bütün yazılarımda buna değinmeye çalışacağım. Projemize baslangıçta resimde göreceğiniz üzere: 1 Toolbar 3 buton 1 listviev ekliyoruz ve tasarımını istersek resimdeki gibi yapabilirsiniz devam ediyoruz.

 


 Bilmeyen arkadaslar için butonların native android iconlarını almalari için, butona tıklayıp soldaki Object Inspector'den StyleLookup içerisinden seçmeleri gerekmektedir. Sıradaki ekleyeceğimiz elemanlar veritabanı bağlantısı için: 1-)FDConnection 2-)FDQuery 3-)BindingsList 3-)BindSourceDB 3-)FDPhysSQLiteDriverLink 3-)FDGUIxWaitCursor Bir sorun çıkmasına karşın Uses bloğumu da yazıyorum eksiklerinizi tamamlayabilirsiniz.
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
Data.DB, Data.SqlExpr, FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Comp.Client,
FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt,
FireDAC.Comp.DataSet, FMX.Layouts, FMX.ListBox, Data.Bind.Components,
Data.Bind.DBScope, FireDAC.Stan.ExprFuncs, FireDAC.Phys.SQLite,
FireDAC.FMXUI.Wait, FireDAC.Comp.UI, FMX.Platform.Android, FMX.ListView.Types,
FMX.ListView, DateUtils, System.Rtti, System.Bindings.Outputs,
Fmx.Bind.Editors, Data.Bind.EngExt, Fmx.Bind.DBEngExt, FMX.Edit;
Sıradaki ekleyeceğimiz elemanlar veritabanına kayıt için işlemi: 2 adet panel ve her birinin içine 1 tane label ve 1 tane edit ekliyoruz ve asağıdaki görüntüdeki gibi bir şekil yapabilirsiniz.

 


 Benim kişisel tavsiyem kod yazarken kafanızın karışmaması için eklediğiniz ve sık kullanacağınız bileşenlerin isimlerini olduğu gibi bırakmamanızdır. Şimdi kod yazımına geçiyoruz ve ilk yapacağımız ise USES kısmına "System.IOUtils" kütüphanesini ekleme sebebi ise manuel oluşturacağımız sqlitenin yerini ayarlamak için. Veritabani bağlantı işlemi için sol üsteki bağlan butonuna : Var blogumuza 2 adet değişken tanımlayacağız
Var
LFCF : TLinkFillControlToField; // Listviewin Veritabanına bağlanması için gerekli
DbYol : String; // manuel olusturacağımız sqlitenin yerini ayarlamak için
Begin blogunun altından başlayarak öncelikle veritabanı yolumuzu Dbyol değişkenine kaydediyoruz.
DbYol := System.IOUtils.TPath.GetDocumentsPath + PathDelim + 'SqliteDers.s3db'; // Burada yanlış hatırlamıyorsam uygulamamız ile aynı dizine kayıt yolu belirtiyorduk
Sırada Connectionumuzun ayarları var:
With FDConnection1 do
begin
LoginPrompt := False;
Params.Clear;
Params.Values['Database'] := DbYol; // yukarıda belirttiğimiz kayıt dizini
Params.Values['DriverID'] := 'SQLite';// veritabanı türümüz
Params.Values['CharacterSet'] := 'utf8'; // yazı karakteri türü
Connected := True; // bağlantımızı aktif yaptık
// Yoksa SQL veritabanı kendiliğinden otomatik olarak CREATE edilmiş olacaktır...
end;
Veritabanını oluşturduğumuza göre tablomuzu oluşturma evresine geçebiliriz:
With FDQuery1 do
begin
Active := False; // Aktif olma olasılığına karşı kapatılıyor.

// DERS adında tablomuz yoksa baştan yaratıyoruz buranın içerigi size kalmış.
Connection := FDConnection1;
SQL.Clear;
SQL.Add( 'CREATE TABLE IF NOT EXISTS DERS (' );
SQL.Add( ' ADI nvarchar(10)');
SQL.Add( ' );');
ExecSQL; //Tablo yaratma işlemi tamamlandı.
// Listviewe bağlanacak querymizin sql içeriğini nasıl bir listeleme yapmak istiyorsak ona göre ayarlıyoruz
SQL.Clear;
SQL.Add( 'SELECT');
SQL.Add( ' ADI' );
SQL.Add( ' FROM DERS' );
Active := True;
// ListBox'a Bind etmek için hazırlık...
// BindSurceDB1 bu sayede Fieldlari görür.
// DetailFields := 'Adi;Soyadi';
end;
Sırada en önemli yeri olan listview'in binding ayaları var:
ListView1.BeginUpdate; //Listview yükleme işlemine başlatılıyor
BindSourceDB1.DataSet := FDQuery1;
while BindingsList1.BindCompCount > 0 //Aynı butona 1'den fazla basılırsa diye
do BindingsList1.BindComps[0].Free;

LFCF := TLinkFillControlToField.Create(nil);//köprü bağlantı için Linkfillcontrol nesnemizi oluşturuyoruz
With LFCF do //Nesnemiz manuel olduğu için Object inspectorünü buradan ayarlıyoruz.
begin
Control := ListView1;
FillDataSource := BindSourceDB1;
FillDisplayFieldName := 'ADI';
Category := 'Quick Bindings';
AutoFill := True;
AutoActivate := True;
end;
BindingsList1.InsertComponent( LFCF );//Bindigslistin baz alacağı LinkFill'i gösterdik
LFCF.Free; // Artık objemizi serbest bırakabiliriz

FDQuery1.Active := False;
FDQuery1.Active := True;
ListView1.EndUpdate //yükleme işlemi tamamlandı.
Bağlantı butonu ile işimiz bittiğine göre artık kayıt ve silme işlemine geçebiliriz. Kayıt butonumuza:




With TFDQuery.Create(nil) do //Sanal bir FireDAC Query oluşturuyoruz.
begin
Connection := FDConnection1; //Verıtabanı bağlantısını ayarlıyoruz.
SQL.Clear;
SQL.Add( 'INSERT INTO DERS ' ); //Buradaki "DERS" kullandığımız tablonun adı.
SQL.Add( '( ADI )' ); //Buradaki "ADI" alanımızın adı.
SQL.Add(' VALUES ' );
SQL.Add(' (:d0) '); //Rahat olması bakımından parametre ile yapılmıştır bu örnekte.
Params[0].Value := Aditxt.Text; //editin değerini parametremize eşitliyoruz.
ExecSQL; //ExecSQL geri dönüsü olmayan sorgular için kullanılır INSERT DELETE gibi.
Free; //Artık query ile işimiz bittiğine göre serbest bırakabiliriz.
end;
FDQuery1.Active := False; //Yapılan değişikliklerin gözükmesi için query i kapatıyoruz.
FDQuery1.Active := True; //Yapılan değişikliklerin gözükmesi için query i açıyoruz.

Şöyle bir bakılınca Ekle butonumuzdan yapı olarak pek bir farkı yoktur yine parametre göndereceğiz sadece burada sql sorgusunu değiştirecegiz. Sil butonumuza:




With TFDQuery.Create(nil) do //Sanal bir FireDAC Query oluşturuyoruz.
begin
Connection := FDConnection1; //Veritabanı bağlantısını ayarlıyoruz.
SQL.Clear;
SQL.Add( 'Delete From DERS Where ADI = ' ); //Buradaki "DERS" kullandığımız tablonun ve "ADI" yazanda kolonun adı.
SQL.Add( ' :d0 ' ); //Rahat olması bakımından parametre ile yapılmiştir bu örnekte.
Params[0].Value := ListView1.Selected.Text; //listviewin seçilen elemanının değerini parametremize eşitliyoruz.
ExecSQL; //ExecSQL geri dönüsü olmayan sorgular için kullanılır INSERT DELETE gibi.
Free; //Artık query ile işimiz bittiğine göre serbest bırakabiliriz.
end;
FDQuery1.Active := False; //Yapılan değişikliklerin gözükmesi için query i kapatıyoruz.
FDQuery1.Active := True; //Yapılan değişikliklerin gözükmesi için query i açıyoruz.
İste bütün işlem bu kadar yapacağınız projeye göre bunları procedureler içine alıp istediğiniz şekilde kullanabilirsiniz. Yorumlarınzı esirgemeyin. Bu konularda Daha çok bulduğum kaynakları paylaşmaya devam edeceğim. Bu olayı kavramamda yardımcı olan ve bu güzel örneğini bizlere sunan Muharrem ARMAN (mrmarman) teşekkürler.

XE5 Titreşim - XE5 Vibration

Açıklayabileceğim fazla bir şey yok titreşim olayını bende net üzerinden ararken bulmuştum bu Titreşim proceduresini. Javanın VIBRATOR_SERVICE  sınıfından yararlanılarak yapılan bir procedur. Benim eklediğim kısım sadece *1000 olan kısımdır ve amacı titreşim için procedureye gönderilen sayının mili saniye olarak değilde direk saniye cinsinden olması içindir.
procedure Titret(Saniye: Integer);
var
TitresimServisi: JObject;
Titrek: JVibrator;
begin
TitresimServisi := SharedActivity.getSystemService(TJActivity.JavaClass.VIBRATOR_SERVICE);
Titrek := TJVibrator.Wrap((TitresimServisi as ILocalObject).GetObjectID);
Titrek.vibrate(Saniye*1000);
end;
  Tugrul Helvacı hocamızdan alıntıdır. Orjinal konu için tıklayınız

Delphide versiyon kontrolu yaparak açık olan programı güncelleme

Herkese selam, Bir çok arkadaşımız formlardan yararlanarak delphi ile download işlemini başarıyla gerçekleştiriyor fakat hep karşımıza dostlardan şöyle bir soru geliyor zamanında bende sormuştum bilirim o yüzden "Programım açıkken güncellemeyi nasıl yapacağım?","Açık exeyi güncellesek inen dosya ile yer değiştirir mi eski olan?" cevaba gelirsek yer değiştirmez fakat bazı Rename olayları ile bunu gerçekleştirebiliriz. Aşağıda bu olaylar için küçük ama kullanışlı bir örnek yapacağız. Öncelikle ve bana kalırsa programınızın güncel versiyonunu sorabileceği bir yer olması gerekir bunu kendi web sitenizin ftpsine versiyon.txt dosyası atarak yapabilirsiniz ben bu adım üzerinden gideceğim. Formumuza ekleyeceğimiz componentler: 1-)IdHTTP Bu örnek XE3 üzerinden yapılmıştır ve eksik kütüphane tanımlamanıze karşı kulandıklarımın hepsini yazıyorum.
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdHTTP,Vcl.ExtActns, Vcl.ComCtrls,
Vcl.StdCtrls;
Versiyon kontrolümüzle başlayalım başlayalım; VerisiyonKontrol adında proceduremizi gerekli kısma tanımladıktan sonra içerisine alta vericeğim kod parçasını yazınız. Açıklamaya gelirsek; SiteVersiyon değişkenimizin içine güncel versiyon bilgisini yazdığımız txt dosyasını çekiyoruz örneğin: 1.0.0.1 GetBuildInfo ile açık olan exemizin versiyon bilgilerini kontrolde kullanacağımız değişkenleri alıyoruz ve bunları ExeVersiyon değişkenimize sitedeki txt ile karşılastıracağımız şekilde formatlayarak aynı şekil şemale getiriyoruz. SiteVersiyon ve ExeVersiyon değişkenleri ile aldığımız versiyon bilgilerini karşılastırdığımız if sorgusundan dönen sonuca göre indirme işlemimizi gerçekleştireceğiz. Versiyonlar eşit ise güzel bir MessageBox ile şuan kullandığı versiyonu kullanıcıya gösterdik.
procedure TAnaSayfaForm.VersiyonKontrol;
var SiteVersiyon,ExeVersiyon: string; V1, V2, V3, V4: word;
begin
SiteVersiyon:=IdHTTP1.Get('http://www.siteadı.com/version.txt'); {YENİ SÜRÜMÜN VERSİYONUNUN YAZILI OLDUĞU TEXT DOSYASI}
GetBuildInfo(Application.ExeName, V1, V2, V3,V4);
ExeVersiyon:= Format('%d.%d.%d.%d', [V1, V2, V3,V4]);
if SiteVersiyon <> ExeVersiyon then
begin
if Application.MessageBox('Yeni versiyon çıkmış indirmek ister misiniz?','SORGU',MB_YESNO+MB_ICONQUESTION)=6 then
begin

Indir;

end;
end else
begin
ShowMessage('En güncel '+ ExeVersiyon +' versiyonunu kullanıyorsunuz.');
end;
end;

procedure TAnaSayfaForm.GetBuildInfo(const AppName: string; var V1, V2, V3,
V4: Word);
var
VerInfoSize, VerValueSize, Dummy: DWORD;
VerInfo: Pointer;
VerValue: PVSFixedFileInfo;
begin
VerInfoSize:= GetFileVersionInfoSize(PChar(AppName), Dummy);
GetMem(VerInfo, VerInfoSize);
GetFileVersionInfo(PChar(AppName), 0, VerInfoSize, VerInfo);
VerQueryValue(VerInfo, '', Pointer(VerValue), VerValueSize);
with VerValue^ do
begin
V1:= dwFileVersionMS shr 16;
V2:= dwFileVersionMS and $FFFF;
V3:= dwFileVersionLS shr 16;
V4:= dwFileVersionLS and $FFFF;
end;
FreeMem(VerInfo, VerInfoSize);
end;
Eğer versiyonlar eşit değil ise sıradaki işlemimiz olan indirme işlemine geçiyoruz. AdDeğiştir fonsiyonumuzdan bahsedeyim; Sebebi şuanki exemizin yeni gelen exe ile güncellenme sırasında uzantılarının aynı olmaması çünkü üzerine yazmayı deniyecektir indirme işleminde açık olan exenin üzerine yazamadığı için işlemi yapılmış olarak kabul edip devam edecektir. Bu yüzden Orjinal exemizin yolunu Fonksiyonumuza atıyoruz ve fonsiyon açık olan exemizin uzantısını .old yapıyor. Bu işlem gerçekleştikten sonra indirme işlemine kaldığımız yerden devam ediyoruz. Urlye yeni güncellenecek exemizin linkini yazacağız ve alta filename'ye dosya yolu + exenin adı, ki buradaki dosya yolunu açık olan projemizin dizinini alıyor. Try komutumuz işlevini yapınca görevini finally e devredince can alıcı yere geliyoruz. Burada programımızı hoş bir mesaj ile istersek Manuel kapatmalarını söyleyebiliriz fakat ben bunu tavsiye etmiyorum çünkü bazı şeyleri insanımızın gözüne ne kadar soksak da oradaki güncelleme = yeni şeyler olan yeri anlamayacaktır ve o an açık olan bir önceki versiyondan devam edecektir. Bu sebeple formumuzu close ediyoruz ki açılışta şöyle bir kontrol yapacağız o da .old uzantısına çevirdiğimiz programımızın eski versiyon exe'sini temizlemek amacı ile
procedure TAnaSayfaForm.AdDegistir(FileName: String);
var newName : string;
begin
newName := ChangeFileExt(FileName, '.old');
RenameFile(FileName, newName);
end;

procedure TAnaSayfaForm.Indir;
begin
AdDegistir('.Anime Listem.exe');
with TDownloadURL.Create(self) do
try
Screen.Cursor:=crHourGlass;
URL:='http://www.siteadı.com/Anime Listem.exe';
FileName :=ExtractFilePath(Application.ExeName)+'Anime Listem.exe';
ExecuteTarget(nil) ;
finally
Screen.Cursor:=crDefault;
Application.MessageBox('Güncelleme Tamamlandı.'+#13+'Lütfen programı tekrar başlatılıyor.','Bilgi',MB_OK or MB_ICONINFORMATION);
Free;
Self.Close;
end;
Formumuzun onCreate eventine geliyoruz burada 2 satırlık işimiz var ki bu 2 satırlarda; 1-) Biraz önce bahsettiğim .old uzantılı eski exemizi silecez 2-) VersiyonKontrol proceduremizi çağıracaz ki programımız açıldığında kontrole başlasın Delphinin DeleteFile komuzu ile dizinimizdeki eski exemizin yol ve adını yazıp kısa kodumuzu bitiriyoruz.

procedure TAnaSayfaForm.FormCreate(Sender: TObject);
begin
DeleteFile('.Anime Listem.old');
VersiyonKontrol;
end;

Eğer düzgün bir şekilde adımlarımızı uygulayarak giderseniz sorunsuz güncelleme işlemini yapabilirsiniz ek olarak internetten progressbar ilerleme özelliğinide araştırıp çok kolay bir şekilde entegre ederek daha hoş oto güncellemeler çıkartabilirsiniz. Yardımı dokunursa ne mutlu bize. Sürçü lisan ettiysek, haddimizi aştıysak hocalarımız ve arkadaşlarımızdan tekrar özür dilerim.

X-SuperObject

Günümüz teknolojisi ile gelişen Delphi'de bir çoğumuzun JSON kullandığı ve bunu en güzel bir biçimde SuperObject ile yaptığı aşikardır. Rad Studio'nun son versiyonu olan XE5 ile artık IOS yanında Android platformunada el atmış bulunmaktayız. Ne yazıkki SuperObject bu yeni platformlarda çalışmamasından dolayı DBXJson kullanmak istemeyenler için bizim şirketten bir abimin hazırladığı X-SuperObject'i Delphi'de IOS, Android, MacOS, Windows platformlarının hepsinde hiç bir sorun yaşamadan kullanabilirsiniz. Örnekleri inceleyerek nasıl kullanıldığı hakkında bilgi edinebilirsiniz.

Link X-SuperObject için Tıklayınız.

Örnek JSON
{
"name": "Barış ATALAY",
"vip": true,
"telephones": ["000000000", "111111111111"],
"age": 24,
"size": 1.72,
"adresses": [
{
"adress": "blabla",
"city": "Antalya",
"pc": 7160
},
{
"adress": "blabla",
"city": "Adana",
"pc": 1170
}
]
}

Delphi Code
var
X: ISuperObject;
begin
X := TSuperObject.Create('{}');
X.S['name'] := 'Barış ATALAY';
X.B['vip'] := true;
with X.A['telephones'] do
begin
Add('000000000');
Add('111111111111');
end;
X.I['age'] := 24;
X.F['size'] := 1.72;
with X.A['adresses'].O[0] {Auto Create} do
begin
S['adress'] := 'blabla';
S['city'] := 'Antalya';
I['pc'] := 7160;
end;
// or
X.A['adresses'].O[1].S['adress'] := 'blabla';
X.A['adresses'].O[1].S['city'] := 'Adana';
X.A['adresses'].O[1].I['pc'] := 1170;

Super Expression
const
JSON = '{ "o": { '+
' "1234567890": {'+
' "last use date": "2010-10-17T01:23:20",'+
' "create date": "2010-10-17T01:23:20",'+
' "name": "iPhone 8s"'+
' }'+
' },'+
' "Index": 0, '+
' "Data": {"Index2": 1}, '+
' "a": [{'+
' "last use date": "2010-10-17T01:23:20",'+
' "create date": "2010-11-17T01:23:20",'+
' "name": "iPhone 8s",'+
' "arr": [1,2,3] '+
' }, '+
' {'+
' message: "hello"'+
' }]'+
'}';

var
X: ISuperObject;
NewJSon: ISuperObject;
NewArray: ISuperArray;
begin
X := SO(JSON);
ShowMessage( X['o."1234567890"."last use date"'].AsString );
ShowMessage( X['a[Index]."create date"'].AsString );
ShowMessage( X['a[Data.Index2].message'].AsString );
X['a[0].arr'].AsArray.Add('test1');
// -----
NewJSON := X['{a: a[Index], b: a[Data.Index2].message, c: o."1234567890".name, d: 4, e: a[0].arr[2], f: " :) "}'].AsObject;
NewArray := X['[a[Index], a[Data.Index2].message, Data.Index2, Index, 1, "1", "test"]'].AsArray;
end;

Variant
var
X: ISuperObject;
begin
X := TSuperObject.Create;
X.V['A'] := 1;
X.V['B'] := '2';
X.V['C'] := 1.3;
X.V['D'] := False;
X.V['E'] := Null;
Memo1.Lines.Add(X.AsJSON);
end;
Output

{"A":1,"B":"2","C":1.3,"D":false,"E":null}

Sample 2
const
JSN = '{ '+
' "adresses": [ '+
' { '+
' "adress": "blabla", '+
' "city": "Antalya", '+
' "pc": 7160 '+
' },'+
' { '+
' "adress": "blabla", '+
' "city": "Adana", '+
' "pc": 1170 '+
' } '+
' ] '+
'}';
var
X, Obj: ISuperObject;
J: Integer;
begin
X := TSuperObject.Create(JSN);
with X.A['adresses'] do
for J := 0 to Lenght -1 do
begin
Obj := O[J];
Obj.First;
while not Obj.EoF do
begin
Memo1.Lines.Add( Obj.CurrentKey + ' = ' + VarToStr(Obj.CurrentValue.AsVariant));
Obj.Next;
end;
Memo1.Lines.Add('------');
end;
end;

OR (Enumerator)
var
X: ISuperObject;
AMember,
OMember: IMember;
begin
X := TSuperObject.Create(JSN);

for AMember in X.A['adresses'] do
begin
for OMember in AMember.AsObject do
Memo1.Lines.Add(OMember.Name + ' = ' + OMember.ToString);

Memo1.Lines.Add('------');
end;
Output

adress = blabla
city = Antalya
pc = 7160
------
adress = blabla
city = Adana
pc = 1170
Marshalling

type

TTestSet = (ttA, ttB, ttC);

TTestSets = set of TTestSet;

TSubRec = record
A: Integer;
B: String;
end;

TSubObj = class
A: Integer;
B: Integer;
end;

TTest = class // Field, Property Support
private
FB: String;
FSubObj: TSubObj;
FSubRec: TSubRec;
FTestSets: TTestSets;
public
A: Integer;
B: TTestSet;
C: Boolean;
property D: String read FB write FB;
property E: TSubRec read FSubRec write FSubRec;
property F: TSubObj read FSubObj write FSubObj;
property G: TTestSets read FTestSets write FTestSets;
end;

TTestRec = record // Only Field Support
A: Integer;
B: TTestSet;
C: Boolean;
D: String;
E: TSubRec;
F: TSubObj;
G: TTestSets;
end;

implementation
...

var
Parse: TTest; // For Class;
S: String;
begin
Parse := TTest.FromJSON('{"A": 1, "B": 0, "C": true, "D": "Hello", "E":{"A": 3, "B": "Delphi"}, "F": {"A": 4, "B": 5}, "G": [0,2]}');
S := Parse.AsJSON;
end;

...
var
Parse: TTestRec; // For Record;
S: String;
begin
Parse := TSuperRecord.FromJSON('{"A": 1, "B": 0, "C": true, "D": "Hello", "E":{"A": 3, "B": "Delphi"}, "F": {"A": 4, "B": 5}, "G": [0,2]}');
S := TSuperRecord.AsJSON(Parse);
end;