Jump to content

Rollo62

Members
  • Content Count

    1945
  • Joined

  • Last visited

  • Days Won

    24

Everything posted by Rollo62

  1. Thanks Chris, this secret was well hidden I will check that.
  2. My hope is that just copy the storyboard and edit info.plist is enough. What else should be missing ? Rx10.3.3 was rock solid for me, Rx10.4 is still fragile and Im working on it.
  3. Hi there, I have a very nasty problem again with BLE background mode. Since I have the feeling that I have read all available articles and references about this topic worldwide, I still got no clue howto get this working. All is working as expected under forground mode. I hope that I can find some help or new ideas from here, because my head is going to be empty right now. My setup is: Rx10.3.3, XCode 11.4.1, iOS13.4.1, modern iPhone/iPad devices, all running fine with debug and release My task: I need to connect external Bluetooth LE peripherials, which works well in foreground. They send data string (20 bytes) via unspecific custom characteristics, and I receive a HEX string, all that is fine. With integrated logging functions in the app, I can monitor all behaviour in fore- and background. Also debugging in fore- and background is no problem. The devices send new datastring every < 2 sec., and the other every < 12 sec., anyway, both get killed after a while. Maybe there are some restrictions in the datarate, I have read somewhere that peripherals > 2 sec. might considered to be killed (?), but I cannot find anything about that in the official docs (also not much in the forums, seems only one case). The connected devices stay connected, I cannot see any unusual behaviour, moreover I test with three different hardware types, all behave same. So the issue seems not to be caused by the peripheral hardware. I use the following settings: Background modes: audio, bluetooth-central (audio is used for Tts text-to-speech also in background, but its not used currently when receiving the data sting). Info PList NSBluetoothPeripheralUsageDescription (deprecated, but shouldn't it be there for older devices ?) I didn't see any hint that this might be harmful. NSBluetoothAlwaysUsageDescription (defining both should be any problem, right ?) Permissions FMLocalNotificationPermission = true; Location: I do not use that, since Apple rejected this once, for adding an "unused background operation". Some time before I added this background location as workaround to keep background mode permanently running. I've made also some experiments before to add bluetooth-peripheral mode, as workaround to keep background mode permanently running. Both workarounds should be not necessary, but I was searching for a stable way to keep background active. I touch the location in foreground, so that the Location permission alert appears to the user,, since I think that location might be relevant for Bluetooth as well, same as is under Android. But I don't use Location in foreground, but in the past it seems that location permission alert seemed to help keeping background active.. When I take the location out completely, then also the Bluetooth LE permission alert seems not to appear every time, so sometimes BLE stays unavailable, and I need re-install to fix that problem. Thats why I touch the location in foreground, to enable location, and then I don't use the location any more, but BLE works with that approach in foreground. Device capabilities: I don't set specific BluetoothLE capabilities (UIRequiredDeviceCapabilities - bluetooth-le), as I never had to, and it works in foreground. Application events, I handle all of them, and especially at WillEnterBackground I stop some unneeded timers and delay the Threaded ringbuffer for receiving and processing the data, by TThread.Sleep(500);. (I used this sleep method before, and it seem to work well under older iOS, but I never checked that too deeply). on BecameActive I restart the timer and threads With TThread.Sleep(500); I throttle the thread which processes the incoming data (there is no data overflow, datarate is too small). I can see the processed incoming data, also in background, the ReadCharacteristic appends the data to the ring buffer, and then every 500ms the thread still seems to run and process this. In background I stop running timer, and I can see data from the periperal coming in. So far, so good, but longer operation (> 1min, > 10min) might kill the app in background. With kill I mean, its not only in background stopped, but the app is killed and restarts fresh. There is no other resource shortage, enough memory, etc., no need to be killed IMHO. I don't see any place where my app could get stucked, so that Apple might push me out of business, I tried to implement all measures to keep everything lightweight, asynchronously, only the threaded ringuffer sleeps for 500ms every cycle. I can see the data package running through the process handler, even debugging in background is possible. Please let me know if you have some helpful hints here, because I got stucked a while now by this issue, I'm at my wits end right now.
  4. I have done some more tests, but cannot really say that I know whats going on here. Maybe I point out some more facts I can see: - The app works fine in foreground (FG), and may crash in (BG) - The BG crash occurs when the phone looses the IoT device, while connected in BG all is fine. - The BG crash never happens in my office, I can even move out-of-range while the IoT gracefully disconnects, and can be reconnect after that (while app in BG can be opened, its not a new start). - The app in BG can send a notification when disconnect, all this is OK. - When connected in FG, I can move about 15m, still the connection keeps active (no disconnect, no crash) When connected in BG, when I move 15m, the connection gets disconnected (no crash). - It seems that BG operation uses maybe less energy or less QoS All that would be OK, only - in some critical places the same app on same phone crashes directly when entering BG these places are offices where a lot of RF noise can be seen (about 50 BLE devices in the scan, manye WiFi devices, ...). - these places contain many surrounding IoT devices, like smartwatches, several nearby (< 50m) WiFi company routers - in normal places, I also have about 20 IoT devices, and some WiFi devices nearby, but maybe not that many as in above. What happens in those critical places is - The app works fine in foreground (FG), and crash directly when entering (BG) - No notification is sended before, means OnDisconnect is not normally fired - The app cannot really be logged, as it can be in normal places When I make experiments with different IoT, one 2sec, one 12sec., both are two different devices, so maybe also they have other different settings. The interesting I can see in the critical places: - the 2sec. device work in BG, no crash - the 12sec. device shows all negative behaviour from above This leads me to the question: Does the iOS Phones switch to different power-mode, or energy-saving mode, when the data rate is lower (e.g. < 10sec.) ? This would be my only explanation for the odd behaviour, that a fast sending device keeps iOS more active (maybe within the 10 sec. range), so the Phone has better capabilities to keep the connection. Is there any paper or site from Apple that would explain such behaviour ? I have searched the web deeply, but I have not found any matching info to my assumption, maybe there is some help out there ? This is interesting reading https://github.com/opentrace-community/opentrace-ios/issues/4 Also regarding background state restoration. I have not implemented that, but of course that may help, but its not supported in FMX. I've put this questions also as double-post into the German DP.
  5. Rollo62

    ANN HTML Library 4.1 released

    aaaand, what is the state of CSS Grid, would be also nice to have (didn't checked the current version, but I doublt it in right now).
  6. Yóu can draw like this. But the Canvas is a raster-based area, which doesn't contain graphical objects. So the only way would be to re-paint the objects, as you like. Usually this is done via FrameBuffer bitmaps, where you can do the clearing and drawing, and then paint the whole frame buffer to the canvas each frame (or when changed).
  7. Hi there, I'm looking for ways to create a simple short-time timer under iOS. via LocalNotifications: One possibility is to use LocalNotifications, but its not much customizeable, nor to make it prominent. Also it seems not to be too reliable via PushKit: that looks more interesting, but I'm afraid that all notifications (even the 15 sec. timer) has to be launched via Apples APNs server. via Calendar system: The Apple doc say that this is not the right way anyway, but to use the EventKit Calendar and EKEventStore. https://developer.apple.com/documentation/eventkit To access the EKEventKit would mean that the app needs calendar permissions Which is quite heavy requirements for a simple timer notification, of <= 2h. But at least with that I could possibly change the alarm sound. The alarm would then be handled from the central calendar app of the phone, I think that this also will open my app via LocalNotification, under the right condition, when user presses the open button. Moreover, I'm not sure if this adds an visible event in the calendar, what I don't want. But I think there should be ways to hide/delete an invisible event, but Apple docs, see note below, restricts that. There are some old calendar examples already in the D.P.F. component suite, the first 3rd party componentes of FMX, as far as I know. I think they are a little outdated by permissions now, but maybe basically still OK. The URL is deprecated, it shall use EMailAddress instead. Which also sets Sound to nil, and doesn't seem to be able to open an related app. Via EventKit this is maybe still possible, maybe with the EventStoreChanged, with a lot of overhead (see note below). Is there any lighter middle way: Two notes from Apple docs: My question is if there is maybe a middle way, or an extension to the LocalNotification, to allow a simple alarm timer running without too much permission requests or overhead ?
  8. I found some API to customize UserNotifications UI, not looked too deep into it, but maybe that could do what I want. At least the UI customization part.
  9. Rollo62

    Record and process audio

    Maybe you'looking for something like AVAudioEngine, as the blog said, this is much more tricky API, I wouldn't count that FMX can do that out-of-the-box. https://developer.apple.com/documentation/avfoundation/avaudioengine If not in the FMX library, then have a look at FmxExpress headers.
  10. Rollo62

    Record and process audio

    Don't think to difficult, its all in FMX. Uses , FMX.Media var FMicrophone : TAudioCaptureDevice; // get the microphone device FMicrophone := TCaptureDeviceManager.Current.DefaultAudioCaptureDevice; FMicrophone.FileName := AFileName; // GetAudioFileName(AUDIO_FILENAME); try if Assigned( FMicrophone ) and ( FMicrophone.State = TCaptureDeviceState.Stopped ) then begin FMicrophone.StartCapture; end; except on E : Exception do begin LTxt := E.Message; end; end; And you have to provide the NSMicrophoneUsageDescription in the version info.
  11. @Dave Nottage Yes "short time" means about 30sek ... 2h max., typically around a few minutes), while it should do the following 1. at least show a notification alert (this works also in normal FMX)- 2. it should exchange the default "bling" sound with another short ringtone (Edit: Finally I found my issue with SoundName, it shall not include the full absolute path, only the filename, see references below) 3. maybe recurring alarms, if the user doesn't react at first note (this should work with normal FMX to) 4. recurring alarms with a specific delay (this should work with normal FMX too, it seems only a range can be set (sec,min,h,...), not e.g. 20 sec. ?) 5. better to have a "customized" looking notification, which looks like a custom popup 6. while this notation popup stays a little longer visible than normal notification 7. best of all if it would wake and notify the app in the background, also before the user presses the button (I think this is probably not possible under iOS) 8. the notified app could possibly start a text-to-speech voice in the background, before the user clicked, explaining additional info to the user I think not all from my wishlist is possible, but I try to get as far as I could. I have checked also with your KastriFree implementation, with what I did the following: create a .caf file from .mp3 via "afconvert", doing the following steps: copy Snd_Bell_001.mp3 to ~/Downloads cd ~/Downloads cd /Users/username/Downloads afconvert -f caff -d LEI16 '~/Downloads/Snd_Bell_001.mp3' '~/Downloads/Snd_Bell_001.caf' add the .caf file to the ressources, to put them in iOS on iOS I create sub-folder /Library/Sounds and copy the .caf file to there, as described here (maybe I may skip the file copy to /Sounds, and use the file directly from the bundle, but I can check the right paths later) The sound file works in forground, what I could test when playing it with mediaplayer When creating a scheduled notification, I have to use the SoundName as filename (e.g. "tone.caf") only, it shall not include the full path. Edit: Only then iOS is searching in all the places above, for the SoundName. So I can confirm that your UserNotifications in KastriFree implementation work well so far. I think an app can get until step 2./3. so far, but all above that will be not possible (at least I can see no way to do it). Maybe there are other hidden APIs, or new idea, in iOS that could do it, but I cannot find them.
  12. Hi there, I have seen already a few blogs talking about the new feature internals of the coming Rx10.4 release: https://www.delphiworlds.com/2020/05/its-time-to-get-excited/ https://blog.marcocantu.com/blog/2020-may-per-control-styling.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+marcocantublog+(marcocantu.blog) https://www.uweraabe.de/Blog/2020/05/15/delphi-10-4-leverages-vcl-styles/ https://dalijap.blogspot.com/2020/05/delphi-nullable-with-custom-managed.html https://community.idera.com/developer-tools/b/blog/posts/new-vcl-tedgebrowser-component-coming-rad-studio-10-4 https://community.idera.com/developer-tools/b/blog/posts/adopting-the-openjdk-for-delphi-android-development I hope this is ending the long, long favorized age of "SORRY, I can't say anything, because of RadStudio Beta NDA will kill me and eat my soul". Hurray: That is a very good step in the right direction, open information instead of information hiding I'm with it, and this gives all customers an early insight in the new features they might have been waiting for, in a more technical perspective rather marketing. We trust our MVP's to give good advices, that also lead to make decisions about prolonging our subscriptions (so there is a little marketing inside anyway, thats fine).
  13. Hi there, I'm checking in iOS (and later for Android, Windows, etc.), what is the best, right way to Sleep in a background mode of the OS. The implementation for iOS seems to be same, as Posix, for iOS, Android, Macos, but I didn't checked that. My goal is to stop any OS operation in the background mode, to avoid killed apps by the OS. While the Thead loop is still active, but only throttled. TThread.Sleep - uses usleep, which is external function, as far as I know based on nanosleep - is this really affecting the current thread only ? class procedure TThread.Sleep(Timeout: Integer); begin {$IF Defined(MSWINDOWS)} Winapi.Windows.Sleep(Timeout); {$ELSEIF Defined(POSIX)} usleep(Timeout * 1000); {$ENDIF POSIX} end; System.SysUtils.Sleep - is bascially same {$IFDEF MSWINDOWS} procedure Sleep; external kernel32 name 'Sleep'; stdcall; {$ENDIF MSWINDOWS} {$IFDEF POSIX} procedure Sleep(milliseconds: Cardinal); begin usleep(milliseconds * 1000); // usleep is in microseconds end; {$ENDIF POSIX} System.SyncObjs.TEvent.WaitFor - is defintively based differently - uses a sem_timedwait (here and here also) - this probably waits by counting in a semaphore, so its not a "real" sleep of the OS, right ? Shall I better use Sleep or TEvent.WaitFor, to let threads sleep in the OS, while avoiding too many wakeups and operations in the background ? Is TEvent.WaitFor really sleeping, from a iOS OS perspective, or will it be seen as running app ? What I assumed before is that TThread.Sleep really stops the thread, and passes back CPU operation to other tasks, but I'm not so sure anymore under IOS.
  14. @Remy Lebeau You are talking about Android, thats all true. But my question was especially regarding iOS, where things are very much different. https://stackoverflow.com/questions/11044095/ios-keep-an-app-running-like-a-service The background mode in iOS can be kept active only by those few background modes available, like Audio, Bluetooth, Location, etc. My goal is too keep some background activity, like a alarm timer, if none of the above is active. If the timer has ended, then a special alarm tone and speech might occur, together with a local notification. I do use timed local notifications, to wake up the system right now, but the Tts and audio works not always reliable. The most reliable way to keep threads running so far I found is the Bluetooth-periperial background mode, where the app itself may act as BLE device, also in background. That may keep iOS active, but if you never need that "peripheral", only to keep it up, then Apple will ask you to show and explain where you need this mode probably. I think a possible way would be to introduce some "function", that can be shown, but may never be used in practice.
  15. The interesting thing is that it sometimes work, and sometimes not. I will do some more tests if MediaPlayer might allow longer background task, technically its working fine. In other apps I can use other background modes to keep awake, so its under some conditions possible to get around special service on iOS, but still I don't see the full picture.
  16. Hi there, I was trying to extend the iOSapi_AVFoundation.pas module, by adding the following function to the AVAudioSession function setCategoryWithOptionsError( category: NSString; withOptions : AVAudioSessionCategoryOptions; error: NSError): Boolean; cdecl; Unfortunately its crashing with an object is nil error, what do I miss here ? I make a local copy of the unit, and the following additions: uses ... const AVAudioSessionCategoryOptionDuckOthers = 2; //S4: add 14.05.20 ... type AVAudioSessionCategoryOptions = NSUInteger; //S4: add 14.05.20 AVAudioSessionClass = interface(NSObjectClass) ['{B24932F9-3C98-44E4-A4F6-0CB58AF7DE8A}'] //S4: 14.05.20 new GUID {class} function sharedInstance: Pointer; cdecl; end; AVAudioSession = interface(NSObject) ['{0B02D5EC-ED09-421A-84BE-6CEE08420E14}'] //S4: 14.05.20 new GUID ... //S4: Addition 14.05.20, the new function I need //[MethodName('setCategory:withOptions:error:')] function setCategoryWithOptionsError( category: NSString; withOptions : AVAudioSessionCategoryOptions; error: NSError): Boolean; cdecl; ... end. This is derived from the function in the Apple reference https://developer.apple.com/documentation/avfoundation/avaudiosession/1616442-setcategory Could be looking in Objective-C like this AVAudioSessionCategoryOptions AVAudioSessionCategoryOptionsNone = 0; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionsNone error:nil]; I want to call it like this LAVAudioSession := TAVAudioSession.Wrap( TAVAudioSession.OCClass.sharedInstance ); //<-- This is original method, it still can be called without exception LRes := LAVAudioSession.setCategory( AVAudioSessionCategoryPlayback, LError); //<-- This is the new method, crash with exception LRes := LAVAudioSession.setCategoryWithOptionsError( AVAudioSessionCategoryPlayback, AVAudioSessionCategoryOptionDuckOthers, LError); Do I have a stupid typo somewhere ? Can the two modules not coexist, because the old one is linked somewhere else ? Shall I use different GUID for the interfaces, or keep the same, to allow static links to find them ? Is the new method not yet in the Rx10.3.3 libraries, but I updated to latest SDK 13.4.1, they should be in there and FMX able to resolve it ? Does the module need to be initialized somehow ? Is there something missing what is needed for correct linkage ? Maybe its too late already, or I'm to blind to see.
  17. A right. I even hat that in my code in the first place, but stupid me commented that out. So I will try again.
  18. Rollo62

    Rx10.4 new feature blogs

    Well sorry Dave, I added that too. Regarding the special permission, and that htis was done in the past, thats all true. But I have the gut feeling that I see more responses these days than in the last 5-6 new releases, maybe I'm wrong, never counted that
  19. Rollo62

    Rx10.4 new feature blogs

    @Dany Marmur Sorry, I was over overexcited now its getting better .... Pfffffffffffff
  20. I have done some experiments, and see that background mode behaves a little tricky. See the little iOS test enclosed. Its missing the wonderful Grijjy TestToSpeech library, available here. Just copy all .pas files into the .dproj folder. And in the _Assets\Sounds folder you can put the downloaded Codex_Machine_-_02_-_Controlled_Relaxation.mp3 file from here. Sorry for the German texts, manby that sound fuzzy in other languages, its a poem from Paul Fleming 05.10.1609. The demo: 1.) When pressing the "Speak" button it start an infinite thread, with Sleep( 3000 ), counting and speaking the numbers. 2.) In foreground no problem, but in background the thread get stopped 3.) Back in foreground, the suspended thread resumes as it should 4.) Press "Stop" to leave the thread loop 5. ) Start long lasting spoken text, or the long playing music, by pressing "Speak long" and/or "Music long" 6.) You can move into background mode, it don't stop playing, as desired 7. ) When back in FG, you can add the "Speak" counter, and all text + musik is playing nicely together 8.) Put into background, also the thread loop with the Sleep is not still counting, that is the desired behavior. What I'm looking for is a background thread, which seems to stay active under some special conditions (either BLuetooth, Location can keep BG awake, as seen above also permanent Audio-Play can keep it awake). You can try 09.) Restart the app 10.) Play musik and/or "Speak" counter 11.) Enter background 12.) Stop music 13.) Start "Speak" counter 14.) Enter background 15.) "Speak" counter will stop, if no music is running parallel 16.) Restart the app 17.) Play musik and/or "Speak" counter 18.) Enter background 12.) Wait until the music finished (Ok takes a while, but you can use shorter .mp3 maybe) 13.) "Speak" counter is still active 14.) Enter background 15.) "Speak" counter is still active 16.) Enter foreground 17.) "Speak" counter is still active 18.) Enter background 19.) "Speak" counter is still active 20.) It seems the MediaPlayer changed the AVAudioSession awake somehow, so that is can keep the thread loop active What I have noticed: If I play music plus the "Speak", then even after music has stopped the speech contrinues !!! That is probably because the MediaPlayer opens a AVAudioSession, but didn't close it, so maybe an open session is enough to keep BG alive. But also I noticed that this sometimes works, sometimes not, timing and sequence seems very important too. Are there any signals that could keep the thread awake in background, if I don't have BLE or Location active ? Some people from iOS propose to play "Silence.mp3" sound for > 500ms, but that would be a hard way, and probably against Apple restrictions. Are there any more tricks how to that behaviour (active thread in BG, with Sleep) could be achieved reliably ? T345_BG_AudioTest.zip
  21. Rollo62

    Rx10.4 new feature blogs

    I see light in the tunnel .... this is one small step for a man - one giant leap for mankind
  22. Here is something for FPC, but quite old. https://github.com/ObjectUp/CrossRoads/blob/master/CrossRoads_DelphiVER280_Port/LSNLibrary/unLSNSound.pas I'm not sure if and how binding FPC solution into Delphi makes sense, probable the iOS bridges were too different, but since the first version of FMX based on this I still have hope that there is a second way.
  23. @Dave Nottage Or did I misunderstand your post, and you say this is currently under 10.3.3 NOT usable, even with the proposals you gave, because Objective-C bridge cannot handle it yet ? That would be the worst case, I need that urgently, my customers already ask why can't we do what other apps can do. I monitor the changes in all Delphi iOSApi and AndroidApi units since the last 5 or 6 versions, so far never changed anything since years, only copyright year is eagerly updated. My hope is that all the available system interfaces might get linked to FMX units soon. Is there maybe a helpful unit from the FPC community, at least this didn't jump in my eye yet ? Any solution welcome, to configure background and foreground audio.
  24. Rollo62

    Return background to foreground

    @Sherlock But this is also sending a notification, and the user must open the notification to start the app, right ? I think the process on the phone is quite similar from local and remote notification. Or is there any possibility to replace the default notification with lets say a more prominent view/launcher via remote notifications ?
  25. A yes, great. So I better check the c headers from now on, instead of Apple Docs. Every time I see a NSError now I will have to replace it bei PPointer, what a mess Then there were many wrong entries in the unit, I only wonder why this seems to work with setCategory, at least I get no exceptions. Unfortunately it still doesn't run without exception, and I think I've tried all optiions, see alternatives (A) to (C) and (1) to (5), I've tried most combinations with same result. When I don't use local copy with different name iOSapi_AVFoundation_Ex I do get compiler errors in FMX.Media.iOS, seems that one uses the original unit, and cannot work with my local copy. Thats why I used a different unit name, that also is working for other iOS units before. unit iOSapi_AVFoundation_Ex; //<-- local copy, with extensions and changed GUID var LAVAudioSession : AVAudioSession; LError : NSError; LRes : Boolean; (A) as PPointer, called by @LPError (B) as PPointer, called by LPError (although this makes not much sense) //LPError : PPointer; (C) as Pointer, called by @LPError LPError : Pointer; begin LAVAudioSession := TAVAudioSession.Wrap( TAVAudioSession.OCClass.sharedInstance ); // (1) this works as far as I can say, at least never see exceptions I can say LRes := LAVAudioSession.setCategory( AVAudioSessionCategoryPlayback, LError); // (2) first approach, throws exception LRes := LAVAudioSession.setCategoryWithOptionsError( AVAudioSessionCategoryPlayback, AVAudioSessionCategoryOptionDuckOthers, LError); // (3) Dave's proposal // Because the corresponding declaration in Objective-C is: // - (BOOL)setCategory:(AVAudioSessionCategory)category error:(NSError **)outError //PPointer = ^Pointer; {$NODEFINE PPointer} { defined in sysmac.h } //NSError = interface; // (A), (B) set to nil before LPError := nil; //<-- this always shows same crash, no matter what (A),(B),(C), (2)-(5) LRes := LAVAudioSession.setCategoryWithOptionsError( // (4a) this alternative both version should be identical -> get from string //CocoaNSStringConst(libAVFoundation, 'AVAudioSessionCategoryPlayback'), // (4b) this alternative get from dedicated function, doing same as above //AVAudioSessionCategoryPlayback, // (4c) this alternative from Dave's original proposal, using different mode CocoaNSStringConst(libAVFoundation, 'AVAudioSessionCategoryPlayAndRecord'), // (5a) this alternative is a simple integer constant 0x2, defined as const = 2 AVAudioSessionCategoryOptionDuckOthers, // 2 // (5b) this alternative also crashes same //2, // (5c) this alternative from Dave's original proposal, using different option 0, @LPError); if LPError <> nil then begin LError := TNSError.Wrap(LPError); end; if not LRes or (LError <> nil) then begin // Something wrong end;
×