Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 01/03/20 in all areas

  1. David Heffernan

    IDE Screenshot too large?

    https://devblogs.microsoft.com/oldnewthing/20150304-00/?p=44543 https://devblogs.microsoft.com/oldnewthing/20120326-00/?p=8003
  2. Remy Lebeau

    Quote of the Day...

    TIdQOTD implements the "Quote of the Day" protocol described in RFC 865. It connects to a QOTD server on port 17, grabs all of the raw bytes the server provides until the server closes the connection, and then returns the raw bytes as a string. But you are not connecting to a real QOTD server on "quotes4all.net". When you changed the TIdQOTD.Port property from 17 to 80, you are connecting to an HTTP server on "quotes4all.net" instead, and as such it requires an HTTP client rather than a QOTD client. You are not seeing any data being returned because TIdQOTD is not requesting any data, and eventually the HTTP server closes the connection when it does not receive a valid HTTP request. In Alister's demo, he connects to real QOTD servers for "alpha.mike-r.com" and "quotes4all.net" on port 17 only, not on port 80. The QOTD server on "alpha.mike-r.com" still works (I just tried it), but it does not appear that there is a QOTD server running at "quotes4all.net" on port 17 anymore (or maybe it is just offline right now, who knows. Alister's demo is over a decade old, after all). So, if you want to use TIdQOTD, you need to connect to a real QOTD server, like the one at "alpha.mike-r.com". If you want to use "quotes4all.net" then you need to use TIdHTTP instead of TIdQOTD, eg: uses ..., IdHTTP; var HTTP: TIdHTTP; Quote: string; begin HTTP := TIdHTTP.Create; try Quote := HTTP.Get('http://quotes4all.net'); finally HTTP.Free; end; end; Just know that you are going to get more data than you are expecting, since quotes4all's HTTP server delivers content in HTML format, which you will have to parse afterwards to extract the text you want.
  3. Maher Tannous

    Call from sim 2

    Thank you very much this is my working code 1- Use this unit https://github.com/DelphiWorlds/KastriFree/blob/master/API/DW.Androidapi.JNI.Telecom.pas 2- procedure CallByPhoneNumber(const PhoneNumber: string; SIMindex: Integer); var Intent: JIntent; LService: JObject; LAccounts: JList; begin LService := TAndroidHelper.Context.getSystemService (TJContext.JavaClass.TELECOM_SERVICE); Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_CALL); Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); Intent.setData(TJnet_Uri.JavaClass.parse(StringToJString('tel:' + JStringToString(TJnet_Uri.JavaClass.encode(StringToJString (PhoneNumber)))))); Intent.putExtra(StringToJString('com.android.phone.force.slot'), true); Intent.putExtra(StringToJString('Cdma_Supp'), true); Intent.putExtra(StringToJString('extra_asus_dial_use_dualsim'), SIMindex); Intent.putExtra(StringToJString('com.android.phone.extra.slot'), SIMindex); Intent.putExtra(StringToJString('slot'), SIMindex); Intent.putExtra(StringToJString('simslot'), SIMindex); Intent.putExtra(StringToJString('sim_slot'), SIMindex); Intent.putExtra(StringToJString('subscription'), SIMindex); Intent.putExtra(StringToJString('Subscription'), SIMindex); Intent.putExtra(StringToJString('phone'), SIMindex); Intent.putExtra(StringToJString('com.android.phone.DialingMode'), SIMindex); Intent.putExtra(StringToJString('simSlot'), SIMindex); Intent.putExtra(StringToJString('slot_id'), SIMindex); Intent.putExtra(StringToJString('simId'), SIMindex); Intent.putExtra(StringToJString('simnum'), SIMindex); Intent.putExtra(StringToJString('phone_type'), SIMindex); Intent.putExtra(StringToJString('slotId'), SIMindex); Intent.putExtra(StringToJString('slotIdx'), SIMindex); Intent.putExtra(StringToJString('simSlotName'), SIMindex); LAccounts := TJTelecomManager.Wrap(TAndroidHelper.JObjectToID(LService)) .getCallCapablePhoneAccounts; if LAccounts <> nil then Intent.putExtra (StringToJString('android.telecom.extra.PHONE_ACCOUNT_HANDLE'), TJPhoneAccountHandle.Wrap(TAndroidHelper.JObjectToID (LAccounts.get(SIMindex)))); TAndroidHelper.Context.startActivity(Intent); end; 3- CallByPhoneNumber(mobilenumber, 0); or CallByPhoneNumber(mobilenumber, 1);
  4. Every request needs evaluation to understand WHY the request is being raised, and if the request actually is what the customer needs - or if he is just attempting to scratch an itch instead of curing the cause of the itch.
  5. David Schwartz

    Overload methods or use unique names?

    You have a TTask object and you are defining different ways of adding it to a TTaskScheduler object and when to start it running. Initially, I thought the examples in the first post are global-scope methods, but there's no queue argument, so I'm going to guess they're members of the TTaskScheduler class. So you have a Task Scheduler object where you want to add tasks with different initial start attributes. The normal (default) case when adding a task to a scheduler is that it's blocked; you'd add the task, set some properties, then start it running. It's an initialization sequence. var t : TTaskID; . . . begin . . . t := q.Add( task1 ); task1.prop1 := xxx; task1.prop2 := yyy; q.Resume( t ); In a situation where the task is fully initialized or can run with default settings, then there's usually a way to add it and start it running in a single call. t := q.AddAndRun( task1 ); // equivalent to this: q.Resume( q.Add( task1 ) ); Both Add cases need to return a handle of sorts that identifies the task in the queue, referred to as TTaskID here. It's an index related to the queue because that's what you're adding it to. (It could also be a TTaskSchduler reference or possibly something else.) Why? Because using a TTask reference forces you to search the queue to find the task in question. It takes O(n/2) time which will vary with the size of the queue, rather than O(1) which is constant. The second option where you're delaying the start to a specified time is like adding a task normally that starts out blocked, but you set its starting time instead of calling Resume. So it's really a variation on Resume, not Add. This is what I'd do: type TTaskID = integer; TTaskScheduler = class . . . public function Add( aTask : TTask ) : TTaskID; // add task to the queue and leave it blocked function AddAndRun( aTask : TTask ) : TTaskID; // add a task to the queue and start it running immediately function Suspend( aTaskID : TTaskID ) : TTaskID; // stops the task function Resume( aTaskID : TTaskID ) : TTaskID; // starts running immediately function ResumeAt( aTaskID : TTaskID; aExecDateTime: TDateTime ) : TTaskID; // resumes the task at the appointed time function ResumeAfter( aTaskID: TTaskID; aMsecDelay : Cardinal ) : TTaskID; // resumes the task after some delay . . . end; So in a way, the question is irrelevant in this case when you get the design right (IMHO) and name things properly. Sorry, but this doesn't really address your question ... and yes, I do run into issues from time to time with too many overloaded methods, but the problem usually resolves itself when I look more closely at the design of the class and what the actual use cases are. Note that you could get fancier with this, allowing expressions using a fluent notation like so: q.Add( task1 ).Resume(); // in place of AddAndRun q.Add( task1 ).Resume().At( dawn_tomorrow ); q.Resume( t ).After( Refresh_delay );
  6. With include files one can change the inline option and skip all those IFNDEFs, tested with Berlin and up. In this case the include file includes a CustomInclude.inc, which is part of the project. This makes it simple to edit in the IDE as required. /// <remarks> /// NOTE: You can override this in CustomInclude.inc, but it requires a Build /// and won't update the Blue Dots /// </remarks> {$IFNDEF RELEASE} {-$INLINE OFF} // un-comment as needed {$ENDIF RELEASE}
  7. Yes. I'm sure we all experienced that a simple, innocent change ends up leading to much more work later one because we introduced a bug or side effects that we didn't think of.
  8. There's no easy answer to this question, and it's one I've battled with for 20+ years. If it's a trivial change (< 10 min to code and test) and I think it's relevant (not all customer feature requests are, we have to evaluate how they apply to all users) I'll often just go ahead and do it immediately after reading the ticket. It's appreciated by customers, but a double edged sword, the more you do it the more they ask 😉
×