Delphi Android -ban exception kezelés

Delphi Android -ban exception kezelés
2016-08-08T18:20:28+02:00
2016-08-14T09:05:25+02:00
2022-10-15T21:56:00+02:00
akos123
Android alatti progival 5 percenként kapcsolódok egy mysql adatbázishoz és beleirok egy "insert into" val egy sort.
Valamit elronthatok a kivétel kezelésben mert nem kezelem a kivételt hanem ha nincs internet kapcsolata a telónak amikor kapcsolódna z adatbázishoz akkor leáll az egész app, ahelyett hogy csak simán kihagyná az adat beirást, addig amig nem lesz ujra internet kapcsolat.

A program kód rész itt látható:
const mysqldatumh='DATE_FORMAT(SYSDATE(),"%Y%m%d%H%i")';

procedure beir;

begin
  try
      if not adatok.adatbazis.Connected then
              adatok.adatbazis.Connected:=true;
      adatok.sql.SQL.Text:='insert into log set ido='+mysqldatumh+', tel="'+tel+'"';
      adatok.sql.ExecSQL;
    except
      adatok.nincskapcsolat;
  end;
end;

Látja esetleg valaki hogy mit csinálok rosszul ? Az én értelmezésem szerint ha nincs NET kapcsolat akkor az adatok.nincskapcsolat eljárást kellene végrehajtsa. Ehelyett leáll az egész mindenféle hibaüzenet nélkül.

Delphi XE7 és MyDAC van használva az adatbázis kapcsolathoz.

Köszönök minden megoldást a kivételkezelésre vagy annak vizsgálatára hogy éppen van -e internet kapcsolat a telón. Bármelyik érdekelne és megoldást hozna nekem .
Mutasd a teljes hozzászólást!
Hello,

Az except ilyetén való használata nem fog neked sok segítséget adni. Eleve problémás lehet a sok exception a kódban, pláne, ha még nem is kezeled le a különböző problémákat.

Másik: az adatbázis kapcsolatok nem feltétlenül van tisztában az internetkapcsolat meglétével - ezt korábban valaki írta is neked.

Harmadik: ha internetkapcsolatra van szükség a feladat végrehajtására, akkor
  1: lokális adatmentés
  2: időszakos próbálkozás a lementett adatok átküldésére.
Az internet meglétét ping útján ismerjük meg, amelyhez indy komponensek ragyogóan használhatóak. Találsz példát a neten, nem lehet gond.
Lokálisan meg bárhogyan menthetsz. Ha nem jó a sima txt, akkor a clientdataset jó lehet.
Mutasd a teljes hozzászólást!

  • Esetleg valami környezeti beállítás kel hozzá amit nem tudok a fordítóban vagy az XE7 IDE -ben ?
    Mutasd a teljes hozzászólást!
  • Szia!
    Nagyon régen foglalkoztam Delphivel és őszíntén megmondom az Androidos Delphi programozással egyáltalán nem foglalkoztam.
    Ám lehet az a hiba, hogy az "if - then" szerkezet után a többes utasítást nem tetted "begin" és "end" páros közé, így:

    procedure beir; begin try if not adatok.adatbazis.Connected then begin adatok.adatbazis.Connected:=true; adatok.sql.SQL.Text:='insert into log set ido='+mysqldatumh+', tel="'+tel+'"'; adatok.sql.ExecSQL; end; except adatok.nincskapcsolat; end; end;
    Mutasd a teljes hozzászólást!
  • Szia,

    nem tudom milyen adatbázis elérő komponenst használsz, de szerintem jobb lenne:
    - utána nézni, hogy a kapcsolódás mekkora timeout-al van, lehet próbál kapcsolódni, de nincs kapcsolat és 30-60 másodperc a timeout.
    - ellenőrizni, hogy az egyes adatbázis műveleteknek mekkora timeout van beállítva, ezekre is alapból egy két perc szokott lenni.
    - ha nem használod az adatbázis kapcsolatot 5 percig, jobb lekapcsolódni, feleslegesen ne legyél bekapcsolódva.
    - a program lapvetően jó, de tesztelted-e, hogy mennyi idő után veszi észre az adatbázis komponensed, hogy megszakadt az adatbázis kapcsolat? A "adatok.adatbazis.Connected" csak annyit mond, hogy a komponensed szerint van-e kapcsolat, a valóság ettől lehet más... Lehet, hogy csak az adatbázis műveletednél veszi észre, ami majd valamekkora timeout után hibát ad, addig a programod "befagy".
    Mutasd a teljes hozzászólást!
  • Jogos!!!

    adatok.sql.SQL.Text:='insert into log set ido='+mysqldatumh+', tel="'+tel+'"';adatok.sql.ExecSQL;

    Ez a két sor mindenképp végrehajtódik, ha konnektid, ha nem ::)
    Mutasd a teljes hozzászólást!
  • Az excep rész lehet a ludas. Szerintem ilyesmi kéne:

    try
    ...
    except
      on E: Exception do ...
    end;

    Meg persze oda nem kéne olyan kód, ami szintén kivételt válthat ki.
    Mutasd a teljes hozzászólást!
  • Szia  lehet nem irtam le jól illetve félreérthetően fogalmaztam:
    Amikor nincsen kapcsolat azaz kikapcsolom a telon a wifi -t meg az adatkapcsolatot, tesztként és úgy hajtom végre a programrészt akkor nem megáll a program és vár mint egy timaout -nál kellene szerintem hanem kilép és eltünik a képernyőről egy villanás nélkül. Ezt jelenti a  "befagy" és nem azt hogy esetleg vár a timeout -ra és nem csinál semmit sem.
    Mutasd a teljes hozzászólást!
  • Innen kiindulva:
    Delphi Android folyamatosan futó program probléma

    egyéb problémák is lehetnek:
    * a tadatok Timer1, Timer2 (egyébként minek 2 timer felváltva?) elindít egy-egy threadet
      hol véded meg a foablak.Button1Click(Sender); kódot attól, hogy több thread egyszerre akarjon hozzáférni?
    * minek a 2 timer
    * az adatok.nincskapcsolat is válthat ki további exception-t amit nem kezelsz
    * ugye egyik threadben sem akarsz az UI -hoz nyúlni?
    * a connected = true szinkron hívás?
      ha nem akkor ez így nem jó!
    * az hogyan van megoldva ebben a komponensben, ha már volt kapcsolat és megszakad?
      ha észreveszi, hogy nincs kapcsolat akkor dob egy exceptiont? (mert azt ebbena try-exceptben nem tudod elkapni)
    Mutasd a teljes hozzászólást!
  • Szia SixHouse !

    Ha jól sejtem inkább ehhez a kérdésemhez akartad irni a válaszodat: Delphi Android folyamatosan futó program probléma
    Legalábbis ebben a kódrészletben volt a timer1 és timer2 emlékeim szerint. :)

    Igen evvel a kódrészlettel több probléma is van, ezért irtam hogy nem túl szép megoldás.
    Ezekkel a problémákkal egyáltalán nem foglalkoztam hogy párhuzamos inditás, illetve mi van ha megszűnik a kapcsolat és hasonlók amiket irtál. Elsőre egyedül arra kerestem a megoldást hogy ne álljon le a program ha a háttérben marad és nem nyúl hozzá senki sem. Erre találtam ezt ki., ami úgy tűnik eléri ezt  a hatást hogy ne állítsa le az android a háttérben. Ha esetleg lenne egy szebb megoldásod nagyon örülnék neki. 

    Nagyon jól megláttad hogy a következő probléma az lesz ha megszakad az adatbázis kapcsolat. Jelenleg pont erre keresem a megoldást egy másik kérdésben:
    Delphi Android -ban exception kezelés probléma

    Ugyanis azt tapasztalom hogy hiába irom try except közé a kérdéses kódrészletet, míg windows alatt tökéletesen kezeli a kivételt és ugrik az except mögé amennyiben megszakadt a kacsolat, addig androidon csak egyszerűen kiakad és eltűnik a képernyőről valamint a memóriából a progi. Utána már nem látom a feladat kezelőben sem.
    Ha esetleg lenne ötleted a megoldásra , nagyon örülnék neki. 
    Jelenleg az IDE beállításai között keresem , hogy hátha találok olyan beállítást ami azt a leállást okozza amit fentebb irtam , ahelyett hogy ugrana az except rész mögé.
    Mutasd a teljes hozzászólást!
  • Szerintem nem igazán értetted meg amit leírtam.
    Gyakorlatilag attól, hogy összeakadnak a szálak elég sok mellékhatással fog küzdeni a program.

    A jó megoldás a service app írása és egy köztes réteg beiktatása (nem közvetlen kapcsolat a db-vel hanem egy szerver amihez befutnak a kérések - pl: REST ; RAD REST lib)

    Az, hogy szálakat gyártasz folyamatosan - hogy a program ne álljon le - nem csak nem szép, hanem rossz is és később ez csak egyre rosszabb lesz, ahogy próbálsz új funkciókat implementálni az egyébként is instabil kódba.

    Még mindig nem tudjuk mi van a:
    * foablak.Button1Click(Sender);
    * adatok.nincskapcsolat
    rutinokban.

    pár dolog amivel közelebb juthatsz a problémához:
    * Minden kódot amit a threadből hívsz védd meg szinkronizációs objektummal (nem tudom firemonkey alatt mi érhető el, talán mutex...)
    * ha az előző nem sikerül akkor a próbáld meghívni a threadben futó kódot TThread.Syncronize-al -> így a főszálon fut (biztonságban) az összes kód de a threadek így is létrejönnek
    * Globális hibakezelő bekötésével (Application.OnException) - ez threaden belül nem fog működni, viszont, ha máshol van a probléma azt megmutatja
    * Log - sok sok log pl:

    procedure beir; begin Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => start'); try Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => test connection'); if not adatok.adatbazis.Connected then begin Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => start connect'); try adatok.adatbazis.Connected:=true; except Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => connect error'); raise; // továbbadjuk a kivételkezelést, a lényeg nekünk a log end; end; Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => database connected'); Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => set sql'); adatok.sql.SQL.Text:='insert into log set ido='+mysqldatumh+', tel="'+tel+'"'; Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => fire sql'); try adatok.sql.ExecSQL; except Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => sql error'); raise; // továbbadjuk a kivételkezelést, a lényeg nekünk a log end; Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => sql ready'); except Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => error'); try adatok.nincskapcsolat; except Log('ThreadID: ' + TThread.Current.ThreadID.ToString() + '; "beir" => error at @adatok.nincskapcsolat'); end; end; end;
    szerk:
    kicsit durvának tűnhet a sok log, de így be tudod azonosítani a probléma pontos helyét,
    ha az except blockban használod az On e: exception -t akkor az e.message-t hozzáfűzve a log végéhez a pontos hibát is megkapod (ha itt van a baj)
    Mutasd a teljes hozzászólást!
  • Hello,

    Az except ilyetén való használata nem fog neked sok segítséget adni. Eleve problémás lehet a sok exception a kódban, pláne, ha még nem is kezeled le a különböző problémákat.

    Másik: az adatbázis kapcsolatok nem feltétlenül van tisztában az internetkapcsolat meglétével - ezt korábban valaki írta is neked.

    Harmadik: ha internetkapcsolatra van szükség a feladat végrehajtására, akkor
      1: lokális adatmentés
      2: időszakos próbálkozás a lementett adatok átküldésére.
    Az internet meglétét ping útján ismerjük meg, amelyhez indy komponensek ragyogóan használhatóak. Találsz példát a neten, nem lehet gond.
    Lokálisan meg bárhogyan menthetsz. Ha nem jó a sima txt, akkor a clientdataset jó lehet.
    Mutasd a teljes hozzászólást!
  • Nagyon szépen köszönöm a sok értékes választ !

    Úgy látom hogy a sok fölösleges kódsorom elviszi rossz irányba a hibakeresést, ezért irtam egy egyszerű kódot amin ugyanúgy látszik a hibajelenség és nem kell olyan kérdéssel foglalkozni hogy mi van a  nem látszó sorokban és funkciókban, ugyanakkor ugyanúgy jelentkezik a hiba azaz  windows alatt jól működik a kódban az except rész android alatt viszont csak leáll a progi hibaüzenet nélkül és eltűnik a képernyőről.



    Kérlek ezen az egyszerű kódsoron keresztül próbáljatok meg segíteni nekem egy ötlettel hogy mitől nem működik Android alatt ? Tehát win32 -re forditva tökéletes, váltok androidra és nem működik.

    Mellékelem a unit1.pas  is.

    unit Unit1;

    interface

    uses
    System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
    FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
    FMX.Controls.Presentation, FMX.Edit, FMX.StdCtrls, IdBaseComponent,
    IdComponent, IdRawBase, IdRawClient, IdIcmpClient;

    type
    TForm1 = class(TForm)
    Button1: TButton;
    function Ping(const AHost : string) : Boolean;
    procedure Button1Click(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.fmx}

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    if ping('www.google.com') then
    showmessage('Van net !')
    else
    showmessage('Nincs net');
    end;

    function TForm1.Ping(const AHost : string) : Boolean;
    var
    MyIdIcmpClient : TIdIcmpClient;
    begin
    Result := True;
    MyIdIcmpClient := TIdIcmpClient.Create(nil);
    MyIdIcmpClient.ReceiveTimeout := 200;
    MyIdIcmpClient.Host := AHost;
    try
    MyIdIcmpClient.Ping;
    Application.ProcessMessages;
    except
    Result := False;
    MyIdIcmpClient.Free;
    Exit;
    end;
    if MyIdIcmpClient.ReplyStatus.ReplyStatusType <> rsEcho Then result := False;
    MyIdIcmpClient.Free;
    end;

    end.
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • A fő probléma (sztem) a try-finally nem használata.

    Ami viszont ugyanúgy el tud szállni mint bármi más hívás:

    if MyIdIcmpClient.ReplyStatus.ReplyStatusType <> rsEcho Then result := False;
    Ez miért nem a try-except blokkon belül van kiolvasva?
    Mutasd a teljes hozzászólást!
  • Köszönöm szépen a sok értékes választ mindenkinek !

    Végül az indy komponenes (ping) használatával sikerült megoldanom a problémát (Kalmanka) és egy delphi ujra telepitéssel ... :)



    Külön köszönöm Sixhouse -nak az értékes hozzászólásait meglátásait ...



    Sokat segítettek a hozzászólásaitok ....
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd