2015-09-02 22 views
5

Sorun Açıklaması:Delphi FireMonkey iOS arkaplan işleme

Şu anda geliştiriyorum ve Delphi XE7 FireMonkey sahip Android ve iOS uygulaması. Bu uygulamanın çevrimdışı çalışabilmesi için kullanıcı bununla çalışabilir ve telefon çevrimiçi olduğunda uygulama arka plandaysa veya telefon beklemede olsa bile uygulamanın tüm sunuculara gönderilmesini sağlar.

Android çalışma çözeltisi: öğrendim gibi

, uygulama arka planda çalışmaya başlar veya telefon stand by gider kez onlar yayından olarak TThread ve TTimer çalışmıyor nesneleri.

Bu kütüphaneyi bir TTimer nesnesi gibi çalışan android için bulmayı başardım ancak uygulama arka plana veya telefonun standında kaldığında çalışmaya devam ediyor. o TThread ve TTimer gibi davranır olarak

https://github.com/dkstar88/AsyncTask

Ne yazık ki iOS'ta çalışmaz ve uygulama arka planda çalışmaya başlar kez durur.

iOS Birkaç yaklaşımlar çalıştı çözümleri

çalıştı ama bir sürü insan Android hakkında bilgi ancak iOS için çok daha az bir yeri vardır bulundu.

Denediğim ilk şey, iOS'a arka planda bir şeyler yapmak istediğimi söylemek için gerekli izinleri plist dosyasına ekliyordu. "Getir" özelliğini denedim.

Yalnız bu, Android'de denenmiş TTimer, TThread veya AsyncTask ile çalışmaz.

Bu yüzden, iOS'a arka planda bir şeyler yapmak istediğinizi söylemelisiniz. IOS'ta ne zaman işlem yapılacağını veya kodun olmasını istediğinizi belirtin.

buldum en promsinig kodu bu bağlantıların (görünüm yorum) idi: Burada

http://qc.embarcadero.com/wc/qcmain.aspx?d=128968

önceki bağlantıdan uyarlanan kullandığım kod vardır. Test için bir not alanına sadece bir çizgi ekler.

unit uBackgroundiOS_2; 

interface 

uses iOSapi.UIKit,Macapi.ObjCRuntime,Macapi.ObjectiveC,iOSapi.CocoaTypes,FMX.Platform.iOS,iOSapi.Foundation,Macapi.Helpers, 

FMX.Memo, system.SysUtils; 

const UIBackgroundFetchResultNewData:NSUInteger = 0; 
     UIBackgroundFetchResultNoData:NSUInteger = 1; 
     UIBackgroundFetchResultFailed:NSUInteger = 2; 

     UIApplicationBackgroundFetchIntervalMinimum:NSTimeInterval = 0; 
     UIApplicationBackgroundFetchIntervalNever:NSTimeInterval = -1; 

type 
     id=Pointer; 
     IMP = function(self : id; cmd : SEL; Param1 : NSUInteger) : id; cdecl; 

Var UIApp : UIApplication; 
    memo: TMemo; 

function imp_implementationWithBlock(block :Pointer) : IMP; cdecl; external libobjc name _PU + 'imp_implementationWithBlock'; 
function imp_removeBlock(anImp : IMP) : integer; cdecl; external libobjc name _PU + 'imp_removeBlock'; 
function objc_addClass(Cls: Pointer): Integer; cdecl; external libobjc name _PU + 'objc_addClass'; 

procedure performFetchWithCompletionHandler(self:id; _cmd: SEL;application:id; handler:id); 


procedure Init(p_memo: Tmemo); 

implementation 

procedure Init(p_memo: Tmemo); 
var 
    Res: Integer; 
begin 
{ 
Info: 
use .\plist\BackgroundOPs.info.plist from Project Main Pfad and copy to Info.plist 

include the Keys: 
<key>UIBackgroundModes</key> 
<array> 
<string>fetch</string> 
<string>remote-notification</string> 
<string>newsstand-content</string> 
</array> 
} 
UIApp := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication); 

objc_msgSend((UIApp as ILocalObject).GetObjectId,sel_getUid('setMinimumBackgroundFetchInterval:'),UIApplicationBackgroundFetchIntervalMinimum); 
Res := class_addMethod(objc_getClass('DelphiAppDelegate') , sel_getUid('application:performFetchWithCompletionHandler:'), @performFetchWithCompletionHandler,'[email protected]:@?'); 

memo := p_memo; 
end; 



procedure performFetchWithCompletionHandler(self:id; _cmd: SEL;application:id; handler:id); 
{ 
Using your device you can fire application:performFetchWithCompletionHandler with the following steps: 
Put your app in the Background state. 
Lock your device and wait 5 minutes. (I know, it's a waste of time, get some coffee) 
Unlock your device, this is will fire the method. 
} 
var 
    ahandlerimp: IMP; 
begin 
    try 
    // here your code max. 30 Sec. 
    Memo.Lines.Add(FormatDateTime('hh:nn:ss', Now)); 

    ahandlerimp := imp_implementationWithBlock(handler); 
    ahandlerimp(self,_cmd,UIBackgroundFetchResultNewData); // return the Do- code 
    imp_removeBlock(ahandlerimp); 
    except 
    end; 
end; 

end. 

Bu, iphone 4'te iOS 8.4.1 ile çalışmıyor. Telefonu bir süre beklemede bıraktım ve uygulamayı kontrol ettiğimde not alanı boştu.

Neyin yanlış olabileceği hakkında bir fikriniz var mı? Burada biraz çıkmaz biriyim.

Çok teşekkürler!

Not: özgün yazımda daha fazla bağlantı ve kaynak ekledim (diğer stackoverflow yayınları dahil) ama maalesef en alakalı iki sayfayı bıraktım çünkü daha fazla yayınlamak için gereken 10 itibarı yok.

http://qc.embarcadero.com/wc/qcmain.aspx?d=128968 (bkz yorum) Bu kod çalışmıyor Calling objective C code block from delphi

unit uBackgroundiOS; 

interface 

uses fmx.platform.iOS,iOSapi.CocoaTypes, Macapi.ObjCRuntime, Macapi.ObjectiveC, 
    iOSapi.UIKit; 

const 
    UIBackgroundFetchResultNewData:NSUInteger = 0; 
    UIBackgroundFetchResultNoData:NSUInteger = 1; 
    UIBackgroundFetchResultFailed:NSUInteger = 2; 

    UIApplicationBackgroundFetchIntervalMinimum:NSTimeInterval = 0; 
    UIApplicationBackgroundFetchIntervalNever:NSTimeInterval = -1; 

type 

    // copied from fmx.platform.iOS as it's on private declaration 
    id = Pointer; 
    SEL = Pointer; 
    PUIApplication = Pointer; 

    IMP = function(self : id; cmd : SEL; Param1 : NSUInteger) : id; cdecl; 

    function imp_implementationWithBlock(block :id) : IMP; cdecl; external libobjc name _PU + 'imp_implementationWithBlock'; 
    function imp_removeBlock(anImp : IMP) : integer; cdecl; external libobjc name _PU + 'imp_removeBlock'; 

    procedure performFetchWithCompletionHandler(self : id; _cmd : SEL; application: PUIApplication; handler : id); 

    procedure initializeBackgroundFetch; 

    //to test if procedure is called in background 
    var fecth_string_test: string; 

implementation 

procedure performFetchWithCompletionHandler(self : id; _cmd : SEL; application: PUIApplication; handler : id); 
var 
    ahandlerimp: IMP; 
begin 
    //Code to perform fetch 
    fecth_string_test := 'entered background code!!'; 

    ahandlerimp := imp_implementationWithBlock(handler); //Create c function for block 
    ahandlerimp(self,_cmd, UIBackgroundFetchResultNewData); //Call c function, _cmd is ignored 
    imp_removeBlock(ahandlerimp); //Remove the c function created two lines up 
end; 

procedure initializeBackgroundFetch; 
Var 
    UIApp : UIApplication; 
    Interval: Pointer; 
begin 
    UIApp := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication); 

    Interval := objc_msgSend((UIApp as ILocalObject).GetObjectId, 
          sel_getUid('setMinimumBackgroundFetchInterval:')); 
//    Interval); 
    class_addMethod(objc_getClass('DelphiAppDelegate') , 
        sel_getUid('application:performFetchWithCompletionHandler:'), 
        @performFetchWithCompletionHandler, 
        '[email protected]:@?' 
); 
end; 

end. 

: Bu iki örnekte kod Karıştırma


i aşağıdaki birimi yaptı. Uygulama başladığında initializeBackgroundFetch çağrısı. Eminim yanlış bir şey yapıyorum ama ne olduğunu anlayamıyorum.

Ayrıca, uygulamanızın arka planda görünmemesine izin verdiğimi fark ettim. Aşağıdakileri info.plist dosyasında ekledim:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
<dict> 
[...] 
    <key>UIBackgroundModes</key> 
    <array> 
     <string>fetch</string> 
     <string>remote-notification</string> 
     <string>newsstand-content</string> 
    </array> 
</dict> 
</plist> 

Herhangi bir fikir var mı?

+0

Ek kaynaklar: iOS arkaplan özellikleri: [link] (http://delphi.radsoft.com (ı Getirme kullanılan)

2- Bu kullandığım kodudur ihtiyaç UIBackgroundModes Kontrol .au/2013/10/sağlama-arka plan-hizmetler-destek-kendi-ios-apps-ile-delphi /) StackOverflow ilgili bağlantı: [link] (https://stackoverflow.com/questions/24168144/ delphi-firemonkey-ios-background-fetch) Amaç-C örnekleri: [bağlantı] (http://hayageek.com/ios-background-fetch/) [li nk] (https://possiblemobile.com/2013/09/ios-7-background-fetch/) –

+0

Ayrıca bunu denedim [link] (http://codeverge.com/embarcadero.delphi.ios/does-delphi- for-ios-support-complete-b/1095555) Ancak "Harici istisna 0" yükseltir. –

+0

, ana postayı yeni kod –

cevap

2

iOS Çalışma Çözeltisi

Sonunda o Delphi 10 Seattle (ben xe8 denemedim, ben XE7 denedim ve çalışmıyor, bu sürümü gerekir) altında çalışmak lazım. İşte adımları:

1- Proje> Seçenekler> Sürüm Bilgisi.

unit uBackgroundiOS; 

interface 

uses fmx.platform.iOS,iOSapi.CocoaTypes, Macapi.ObjCRuntime, Macapi.ObjectiveC, 
    iOSapi.UIKit; 

const 
    UIBackgroundFetchResultNewData:NSUInteger = 0; 
    UIBackgroundFetchResultNoData:NSUInteger = 1; 
    UIBackgroundFetchResultFailed:NSUInteger = 2; 

    UIApplicationBackgroundFetchIntervalMinimum:NSTimeInterval = 0; 
    UIApplicationBackgroundFetchIntervalNever:NSTimeInterval = -1; 

type 

    // copied from fmx.platform.iOS as it's on private declaration 
    id = Pointer; 
    SEL = Pointer; 
    PUIApplication = Pointer; 

    IMP = function(self : id; cmd : SEL; Param1 : NSUInteger) : id; cdecl; 

    function imp_implementationWithBlock(block :id) : IMP; cdecl; external libobjc name _PU + 'imp_implementationWithBlock'; 
    function imp_removeBlock(anImp : IMP) : integer; cdecl; external libobjc name _PU + 'imp_removeBlock'; 

    procedure performFetchWithCompletionHandler(self : id; _cmd : SEL; application: PUIApplication; handler : id); 

    procedure initializeBackgroundFetch; 

    function objc_msgSend(theReceiver: Pointer; theSelector: Pointer): Pointer; cdecl; varargs; 
    external libobjc name _PU + 'objc_msgSend'; 

    //to test if procedure is called in background 
    var fecth_string_test: string; 

implementation 

procedure performFetchWithCompletionHandler(self : id; _cmd : SEL; application: PUIApplication; handler : id); 
var 
    ahandlerimp: IMP; 
begin 
    //Code to perform fetch HERE!!!! 
    fecth_string_test := 'entered background code!!'; 

    ahandlerimp := imp_implementationWithBlock(handler); //Create c function for block 
    ahandlerimp(self,_cmd, UIBackgroundFetchResultNewData); //Call c function, _cmd is ignored 
    imp_removeBlock(ahandlerimp); //Remove the c function created two lines up 
end; 

procedure initializeBackgroundFetch; 
Var 
    UIApp: UIApplication; 
begin 
    UIApp := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication); 

    objc_msgSend((UIApp as ILocalObject).GetObjectId, 
       sel_getUid('setMinimumBackgroundFetchInterval:'), 
       UIApplicationBackgroundFetchIntervalMinimum); 

    class_addMethod(objc_getClass('DelphiAppDelegate') , 
        sel_getUid('application:performFetchWithCompletionHandler:'), 
        @performFetchWithCompletionHandler, 
        '[email protected]:@?'); 
end; 

end. 
İlgili konular