Maher Tannous 3 Posted December 26, 2019 hello please i need help i want to call a number from sim2 card I want to request USSD code from sim2 slot without change any thing in android settings any help to do that in delphi fmx android some one send me this Intent intent = new Intent(Intent.ACTION_CALL); intent.putExtra("com.android.phone.extra.slot", 1); //For sim 2 intent.putExtra("simSlot", 1); //For sim 2 intent.setData(Uri.parse("tel:" + "**********")); I tried this without success I replaced "com.android.phone.extra.slot" with TJIntent.JavaClass.EXTRA_PHONE_NUMBER but I can't find any thing to replace with "simSlot" ???? My code : usesAndroidapi.JNI.GraphicsContentViewText,Androidapi.JNI.Net,varmobilenumber : string;Intent : JIntent;Beginmobilenumber:='*155#';Intent := TJIntent.Create;Intent.setAction(TJIntent.JavaClass.ACTION_CALL); Intent.putExtra(TJIntent.JavaClass.EXTRA_PHONE_NUMBER, 1);Intent.putExtra(TJIntent.JavaClass.EXTRA_INDEX, 1);Intent.setData(TJnet_Uri.JavaClass.parse(StringtoJString(mobilenumber)));TAndroidHelper.Context.startActivity(Intent);End; Share this post Link to post
Dave Nottage 557 Posted December 26, 2019 Your code does not match the Java equivalent that has been sent to you. This is the equivalent: uses Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Net, Androidapi.Helpers; procedure TForm1.Button1Click(Sender: TObject); var MobileNumber: string; Intent: JIntent; begin MobileNumber := '*155#'; Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_CALL); Intent.putExtra(StringToJString('com.android.phone.extra.slot'), 1); Intent.putExtra(StringToJString('simSlot'), 1); Intent.setData(TJnet_Uri.JavaClass.parse(StringtoJString('tel:' + MobileNumber))); TAndroidHelper.Context.startActivity(Intent); end; I don't have a dual SIM device to test this. 21 minutes ago, Maher Tannous said: I replaced "com.android.phone.extra.slot" with TJIntent.JavaClass.EXTRA_PHONE_NUMBER Those are not equivalent. TJIntent.JavaClass.EXTRA_PHONE_NUMBER is "android.intent.extra.PHONE_NUMBER", not "com.android.phone.extra.slot" 1 Share this post Link to post
Guest Posted December 26, 2019 @Dave Nottage I confirm that your code works on second SIM. Share this post Link to post
Maher Tannous 3 Posted December 26, 2019 34 minutes ago, Dave Nottage said: Your code does not match the Java equivalent that has been sent to you. This is the equivalent: uses Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Net, Androidapi.Helpers; procedure TForm1.Button1Click(Sender: TObject); var MobileNumber: string; Intent: JIntent; begin MobileNumber := '*155#'; Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_CALL); Intent.putExtra(StringToJString('com.android.phone.extra.slot'), 1); Intent.putExtra(StringToJString('simSlot'), 1); Intent.setData(TJnet_Uri.JavaClass.parse(StringtoJString('tel:' + MobileNumber))); TAndroidHelper.Context.startActivity(Intent); end; I don't have a dual SIM device to test this. Those are not equivalent. TJIntent.JavaClass.EXTRA_PHONE_NUMBER is "android.intent.extra.PHONE_NUMBER", not "com.android.phone.extra.slot" sorry for that but it does not work your code is asking me to choose between sim card and if I choose sim 2 it calling the number *155 it does not run ussd code for *155# it removes # and call *155 may be some one can test the code and tell me what happining Thanks Share this post Link to post
Guest Posted December 26, 2019 @Maher Tannous In my case it didn't ask to select between sims, and for the # it should be replaced with %23 so phone number should be: Quote MobileNumber := '*155%23'; Share this post Link to post
Maher Tannous 3 Posted December 26, 2019 30 minutes ago, Kas Ob. said: @Maher Tannous In my case it didn't ask to select between sims, and for the # it should be replaced with %23 so phone number should be: have you tried to call from sim 2 ? Share this post Link to post
Guest Posted December 26, 2019 Dave's code automatically made a call directly using SIM 2, the phone did not ask me to choose a sim. Share this post Link to post
Guest Posted December 26, 2019 My 4.4.2 Android is configured to ask me on each call i make to choose a sim to be used, with that code it i didn't even ask me. Share this post Link to post
Maher Tannous 3 Posted December 26, 2019 my android version is 9 samsung j7 pro and I configured to ask me on each call i make to choose a sim to be used and it always show me dialog to choose sim to call from maybe the problem in android version Share this post Link to post
Guest Posted December 26, 2019 May be it is a system feature,bug, changes , security thing .... , i suggest consulting with Google on that matter, you might find some answers, Good luck. Share this post Link to post
Guest Posted December 27, 2019 @Maher Tannous Try this code as it solved similar behaviour like yours on Android 6, and i think this is the right way to format phone numbers with # procedure CallByPhoneNumber(const PhoneNumber: string; SIMindex: Integer); var Intent: JIntent; begin Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_CALL); //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.setData(TJnet_Uri.JavaClass.parse(StringToJString('tel:' + JStringToString(TJnet_Uri.JavaClass.encode(StringToJString(PhoneNumber)))))); TAndroidHelper.Context.startActivity(Intent); end; procedure TForm1.Button1Click(Sender: TObject); begin CallByPhoneNumber('*111#', 0); // 0 for SIM1 end; procedure TForm1.Button2Click(Sender: TObject); begin CallByPhoneNumber('*111#', 1); // 1 for SIM2 end; Share this post Link to post
Guest Posted December 27, 2019 The is from here https://stackoverflow.com/questions/44247691/how-to-make-call-using-specified-sim-in-android-like-true-caller i have no idea how to import TelecomManager Share this post Link to post
Maher Tannous 3 Posted December 27, 2019 This to call TelecomManager var telService: JObject; telService := TAndroidHelper.Activity.getSystemService (TJContext.JavaClass.TELECOM_SERVICE); But the problem is how to call : getCallCapablePhoneAccounts Share this post Link to post
Dave Nottage 557 Posted December 28, 2019 3 hours ago, Maher Tannous said: But the problem is how to call : getCallCapablePhoneAccounts There's an import for TelecomManager, here: https://github.com/FMXExpress/android-object-pascal-wrapper/blob/master/android-28/android.telecom.TelecomManager.pas Be aware that Java2Pas (which was used for the import) sometimes puts instance methods where the class methods are, so they should be removed from there in the import. getCallCapablePhoneAccounts is an instance method that returns a JList, containing instances of JPhoneAccountHandle, so one way to access them is to do this: var LService: JObject; LAccounts: JList; LPhoneAccountHandle: JPhoneAccountHandle; I: Integer; begin Result := False; LService := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.TELECOM_SERVICE); LAccounts := TJTelecomManager.Wrap(TAndroidHelper.JObjectToID(LService)).getCallCapablePhoneAccounts; for I := 0 to LAccounts.size - 1 do begin LPhoneAccountHandle := TJPhoneAccountHandle.Wrap(TAndroidHelper.JObjectToID(LAccounts.get(I))); // Do whatever with the LPhoneAccountHandle here end; end; An import for PhoneAccountHandle is here: https://github.com/FMXExpress/android-object-pascal-wrapper/blob/master/android-28/android.telecom.PhoneAccountHandle.pas Note that getCallCapablePhoneAccounts was introduced in API level 23. Share this post Link to post
Guest Posted December 28, 2019 @Dave Nottage Thank you . This raise a question about raised exception and i know you are the right person to ask Quote Invoke error: method not found raised on LService := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.TELECOM_SERVICE); The question is : Is there right way to handle this ? i mean my phone API level is 19 and TELECOM_SERVICE is not there, should i use try..except or there is a method to check class existence without raising an exception ? Share this post Link to post
Dave Nottage 557 Posted December 28, 2019 12 hours ago, Kas Ob. said: The question is : Is there right way to handle this ? This is one way: if TOSVersion.Check(21) then begin // Do the TELECOM_SERVICE stuff end; TELECOM_SERVICE was introduced in API level 21. Another way is: if TJBuild_VERSION.JavaClass.SDK_INT >= 21 then begin // Do the TELECOM_SERVICE stuff end; Share this post Link to post
Maher Tannous 3 Posted December 31, 2019 On 12/28/2019 at 3:15 AM, Dave Nottage said: There's an import for TelecomManager, here: https://github.com/FMXExpress/android-object-pascal-wrapper/blob/master/android-28/android.telecom.TelecomManager.pas Be aware that Java2Pas (which was used for the import) sometimes puts instance methods where the class methods are, so they should be removed from there in the import. getCallCapablePhoneAccounts is an instance method that returns a JList, containing instances of JPhoneAccountHandle, so one way to access them is to do this: var LService: JObject; LAccounts: JList; LPhoneAccountHandle: JPhoneAccountHandle; I: Integer; begin Result := False; LService := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.TELECOM_SERVICE); LAccounts := TJTelecomManager.Wrap(TAndroidHelper.JObjectToID(LService)).getCallCapablePhoneAccounts; for I := 0 to LAccounts.size - 1 do begin LPhoneAccountHandle := TJPhoneAccountHandle.Wrap(TAndroidHelper.JObjectToID(LAccounts.get(I))); // Do whatever with the LPhoneAccountHandle here end; end; An import for PhoneAccountHandle is here: https://github.com/FMXExpress/android-object-pascal-wrapper/blob/master/android-28/android.telecom.PhoneAccountHandle.pas Note that getCallCapablePhoneAccounts was introduced in API level 23. Thank you but I have to put all files from this page https://github.com/FMXExpress/android-object-pascal-wrapper/tree/master/android-28 in my project folder !!! Share this post Link to post
Maher Tannous 3 Posted December 31, 2019 can any one make an example working project for me ? thanks a lot Share this post Link to post
Dave Nottage 557 Posted January 1, 2020 On 12/31/2019 at 6:30 PM, Maher Tannous said: can any one make an example working project for me ? I've created a more compatible (with the other Delphi units) import for the Telecom classes, here: https://github.com/DelphiWorlds/KastriFree/blob/master/API/DW.Androidapi.JNI.Telecom.pas Which should at least make it a bit easier Share this post Link to post
Maher Tannous 3 Posted January 1, 2020 3 hours ago, Dave Nottage said: I've created a more compatible (with the other Delphi units) import for the Telecom classes, here: https://github.com/DelphiWorlds/KastriFree/blob/master/API/DW.Androidapi.JNI.Telecom.pas Which should at least make it a bit easier Thank you procedure CallByPhoneNumber(const PhoneNumber: string; SIMindex: Integer); var Intent: JIntent; LService: JObject; LAccounts: JList; LPhoneAccountHandle: JPhoneAccountHandle; I: Integer; 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); LAccounts := TJTelecomManager.Wrap(TAndroidHelper.JObjectToID(LService)) .getCallCapablePhoneAccounts; for I := 0 to LAccounts.size - 1 do begin LPhoneAccountHandle := TJPhoneAccountHandle.Wrap (TAndroidHelper.JObjectToID(LAccounts.get(I))); if (LAccounts <> null) AND (LAccounts.size() > 0) then Begin Intent.putExtra('Android.telecom.extra.PHONE_ACCOUNT_HANDLE', LAccounts.get(0)); End else if (LAccounts <> null) AND (LAccounts.size() > 1) then Begin Intent.putExtra('Android.telecom.extra.PHONE_ACCOUNT_HANDLE', LAccounts.get(1)); End; end; TAndroidHelper.Context.startActivity(Intent); End; I got an error here ( LAccounts.get(0) ) it returns an TJObject but Intent.putExtra reqired a Byte Share this post Link to post
Dave Nottage 557 Posted January 1, 2020 7 hours ago, Maher Tannous said: I got an error here ( LAccounts.get(0) ) That part should be more like this: LAccounts := TJTelecomManager.Wrap(TAndroidHelper.JObjectToID(LService)).getCallCapablePhoneAccounts; if LAccounts <> nil then begin for I := 0 to 1 do begin if LAccounts.size > I then begin LPhoneAccountHandle := TJPhoneAccountHandle.Wrap(TAndroidHelper.JObjectToID(LAccounts.get(I))); Intent.putExtra(StringToJString('android.telecom.extra.PHONE_ACCOUNT_HANDLE'), LPhoneAccountHandle); end; end; end; Share this post Link to post
Maher Tannous 3 Posted January 2, 2020 22 hours ago, Dave Nottage said: That part should be more like this: LAccounts := TJTelecomManager.Wrap(TAndroidHelper.JObjectToID(LService)).getCallCapablePhoneAccounts; if LAccounts <> nil then begin for I := 0 to 1 do begin if LAccounts.size > I then begin LPhoneAccountHandle := TJPhoneAccountHandle.Wrap(TAndroidHelper.JObjectToID(LAccounts.get(I))); Intent.putExtra(StringToJString('android.telecom.extra.PHONE_ACCOUNT_HANDLE'), LPhoneAccountHandle); end; end; end; Intent.putExtra(StringToJString('android.telecom.extra.PHONE_ACCOUNT_HANDLE'), LPhoneAccountHandle); does not accept LPhoneAccountHandle I must use JString or integer value Share this post Link to post
Dave Nottage 557 Posted January 2, 2020 Actually putExtra takes a number of different types, including JParcelable. I've modified the Telecom import unit: https://github.com/DelphiWorlds/KastriFree/blob/master/API/DW.Androidapi.JNI.Telecom.pas So if you update that, it should now accept LAccountHandle Share this post Link to post
Maher Tannous 3 Posted January 3, 2020 (edited) 17 hours ago, Dave Nottage said: Actually putExtra takes a number of different types, including JParcelable. I've modified the Telecom import unit: https://github.com/DelphiWorlds/KastriFree/blob/master/API/DW.Androidapi.JNI.Telecom.pas So if you update that, it should now accept LAccountHandle 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); Edited January 3, 2020 by Maher Tannous 2 Share this post Link to post