我目前正在開發和Android和iOS用Delphi XE7 Firemonkey應用。此應用程序需要脫機工作,以便用戶可以使用它,當手機上線時,即使應用程序在後臺或手機處於待機狀態,應用程序也會將所有工作發送到服務器。
Android平臺的解決方案:
正如我發現,物體的TThread和TTimer,因爲他們停止運行,一旦應用程序被切換到後臺或手機進入待機不起作用。
我最終找到了這個類似於TTimer對象的android庫,但它在應用程序轉到背景或手機處於待機狀態時仍然有效。
https://github.com/dkstar88/AsyncTask
遺憾的是它並沒有在iOS上,因爲它的行爲就像TThread類和TTimer工作,並停止一旦應用程序切換到後臺。
的iOS試圖解決方案
我試了幾種方法,但我發現,很多人有很多關於Android,但信息的iOS少了很多。
我嘗試的第一件事是在plist文件中添加所需的權限,告訴iOS我想在後臺執行某些操作。我嘗試了「獲取」屬性。
這一點在TTimer,TThread或AsyncTask在Android中嘗試不起作用。
所以,我認爲你必須告訴iOS你想在後臺做些什麼,以及你希望iOS在背景中執行什麼程序或代碼。
最promsinig代碼,我發現這個鏈接(查看評論):
http://qc.embarcadero.com/wc/qcmain.aspx?d=128968
這裏是我使用的代碼,改編自以前的鏈接。它只是將一行添加到備註字段進行測試。
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.
這不適用於我的iPhone 4與iOS 8.4.1。我將手機擱置了一會兒,當我查看應用程序時,備忘錄字段爲空。
有什麼想法可能是錯的?我在這裏有點死路一條。
非常感謝!在我原來的文章中,我把更多的鏈接和來源(包括其他stackoverflow帖子),但不幸的是我只剩下最相關的兩個,因爲我沒有10個聲望需要發佈更多。
從這兩個例子混合代碼,我做了如下單位:
http://qc.embarcadero.com/wc/qcmain.aspx?d=128968(見註釋) 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.
此代碼不能正常工作。我在應用程序啓動時調用initializeBackgroundFetch。我確信我做錯了什麼,但不知道它是什麼。
另外我注意到我的應用程序沒有出現在背景允許應用程序在iPhone設置,應該出現嗎?我在info.plist文件中添加了以下內容:
<?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>
任何想法?
的另外的源: iOS的背景屬性:[鏈接](http://delphi.radsoft.com .au/2013/10/provides-background-services-support-to-your-ios-apps-with-delphi /) StackOverflow相關鏈接:[link](https://stackoverflow.com/questions/24168144/ delphi-firemonkey-ios-background-fetch) Objective-C示例: [鏈接](http://hayageek.com/ios-background-fetch/) [li nk](https://possiblemobile.com/2013/09/ios-7-background-fetch/) –
也試過這個[link](http://codeverge.com/embarcadero.delphi.ios/does-delphi- for-ios-support-complete -b/1095555) 但引發了「外部異常0」。 –
用新代碼更新了主文章 –