Italian Inviare un sms con una delle due SIM

simpep

Member
Licensed User
Longtime User
Ciao ragazzi.
Avevo scritto una applicazione che invia degli SMS ad un sistema di antifurto.
Avevo avuto qualche problema con l'invio delle notifiche da parte del gestore che avevo superato usando per l'invio del sms la libreria "Reflection" al posto della "Phone" come consigliato da Erel qualche tempo fa.
Il tutto funzionava correttamente su un Samsung S Duos S7562.
Recentemente ho installato l'applicazione su un Samsung S5 dual sim e l'applicazione invia gli sms in modo apparentemente random usando a volte la sim1 e altre la sim2.
Conoscete un modo per forzare l'utilizzo di una delle due sim ?
Vorrei comunque lasciare questo codice (proposto da Erel) che risolveva il problema delle notifiche indebite

Sub SendSms(PhoneNumber AsString, Text AsString)
Dim r AsReflector
r.Target = r.RunStaticMethod("android.telephony.SmsManager", "getDefault", Null, Null)
r.RunMethod4("sendTextMessage", ArrayAs Object(PhoneNumber, Null, Text, Null, Null), _ArrayAsString("java.lang.String", "java.lang.String", "java.lang.String", _"android.app.PendingIntent", "android.app.PendingIntent"))
End Sub

grazie >simone
 
Last edited:

udg

Expert
Licensed User
Longtime User
Invece di "getDefault" potresti provare "getSmsManagerForSubscriptionId" e passare 0 (zero) come parametro.
Il fatto è che getDefault con un multi-SIM può ritornare SMSManager diversi nel tempo (v. getSubscriptionID) dove si legge:
"Get the associated subscription id. If the instance was returned by getDefault(), then this method may return different values at different points in time (if the user changes the default subscription id). It will return < 0 if the default subscription id cannot be determined. Additionally, to support legacy applications that are not multi-SIM aware, if the following are true: - We are using a multi-SIM device - A default SMS SIM has not been selected - At least one SIM subscription is available then ask the user to set the default SMS SIM."
 

simpep

Member
Licensed User
Longtime User
@udg
Però dovresti essere ancora gentile e dirmi come, facendo la sostituzione che proponi, si passa formalmente il parametro "0" (zero) alla "getSmsManagerForSubscriptionId".
Chiedo venia per la mia ignoranza.
grazie again
>simone
 

udg

Expert
Licensed User
Longtime User
Ciao Simone,
non ho con me B4A, ma penso che potresti provare qualcosa tipo:
B4X:
r.Target = r.RunStaticMethod("android.telephony.SmsManager", "getSmsManagerForSubscriptionId", ArrayAs Object(0), ArrayAsString("java.lang.Integer"))
Tieni presente che il valore zero (0) proposto è solo perché immagino sia quello che fa riferimento alla SIM1 (o cmq a quella di default); non ne sono affatto certo né ho effettuato alcuna ricerca in merito.
 

simpep

Member
Licensed User
Longtime User
Ho provato.
In fase di run dell'applicazione viene generato questo errore:

java.lang.NoSuchMethodException: getSmsManagerForSubscriptionId[class.java.lang.Intereger]

Comunque grazie
>sim
 

udg

Expert
Licensed User
Longtime User
[class.java.lang.Intereger]
Possibile che l'errore dipenda solo dall'aver scritto male Integer?

Ho trovato questo utile riferimento; vedi se ti può essere di aiuto o ispirazione.
 

simpep

Member
Licensed User
Longtime User
@udg
No "Integer" era scritto correttamente è solo il mio riporto sul post sbagliato.
Allora il problema della libreria Phone, che è all'origine del tribolamento, è che la SMSManager, che avevo utilizzato all'inizio, per ogni SMS inviato chiedeva al gestore l'invio di un SMS di notifica (a prescindere che nel cell fosse settata o meno la funzione).
Ho scoperto con sommo dispiacere che questi SMS di notifica non rientrano nel blocco a forfait degli SMS mensili,ma vengono calcolati a parte.
Se non ricordo male Wind li caricava a 0,15 € cad..
In questo modo per ogni SMS inviato al sistema di antifurto all'interno del pacchetto a forfait mensile si aveva una aggiunta di costo di 0,15 euro.
Quindi ho sostituito la chiamata alla "SMSManager" con il blocchetto consigliato da Erel che ho riportato nel mio primo post.
Tutto ha funzionato alla grande fino a quando è stato sostituito il cellulare sul quale è installata l'applicazione con un dual sim Samsung S5.
L'unico modo per garantire l'uso di una delle due SIM per l'invio degli SMS e quello di disattivare temporaneamente l'altra.
Il tutto funziona, ma diciamo che infastidisce un po.
Ha l'aria di una applicazione non proprio . . . . professionale.
ciao >sim
 

sirjo66

Well-Known Member
Licensed User
Longtime User
So che non servirà a nulla, ma prova anche questa routine che utilizzo io per inviare gli SMS:
B4X:
Sub SendLargeSms(Destination As String, Message As String)

  Dim r As Reflector
  r.Target = r.RunStaticMethod("android.telephony.SmsManager", "getDefault", Null, Null)
  Dim parts As Object
  parts = r.RunMethod2("divideMessage", Message, "java.lang.String")
  r.RunMethod4("sendMultipartTextMessage", _
  Array As Object(Destination, Null, parts, Null, Null), _
  Array As String("java.lang.String", "java.lang.String", _
  "java.util.ArrayList", "java.util.ArrayList", "java.util.ArrayList"))

End Sub
 

udg

Expert
Licensed User
Longtime User
Sono sempre senza B4A, ma ormai mi sono appasionato al problema. Prova:
B4X:
Sub SendSms(PhoneNumber AsString, Text AsString)
    Dim manager As JavaObject
    Dim context As JavaObject
    context.InitializeContext
    manager = manager.InitializeStatic("android.telephony.SubscriptionManager").RunMethod("from", Array(context))
    Dim infos As List = manager.RunMethod("getActiveSubscriptionInfoList", Null)
    dim sl, slot as int
    slot =100
    For Each info As JavaObject In infos
       sl = info.RunMethod("getSimSlotIndex",Null)
       if sl < slot then slot = sl
    Next
    'ora slot rappresenta lo slot della SIM principale
    Dim r As Reflector
    r.Target = r.RunStaticMethod("android.telephony.SmsManager", "getSmsManagerForSubscriptionId", Array As Object(slot), Array As String("java.lang.Integer"))
    r.RunMethod4("sendTextMessage", Array As Object(PhoneNumber, Null, Text, Null, Null), _
           ArrayAsString("java.lang.String", "java.lang.String", "java.lang.String", "android.app.PendingIntent", "android.app.PendingIntent"))
End Sub
L'idea è quella PRIMA di scoprire quale sia lo slot della SIM1 (confidando che sia quello con l'id minore) POI ottenere lo SmsManager corrispondente ed INFINE chiamare la funzione sendTextmessage di tale SmsManager.

Umberto
 
Last edited:

simpep

Member
Licensed User
Longtime User
Non riuscendo a cavare un ragno dal buco, ho fatto qualche prova anche io ... un po a ..... caso.
Una di queste sembra funzionare.
In pratica ho spostato la definizione dell'oggetto "r" --->Dim r_obj As Reflector <--- nella sub "Process_Globals" del modulo.

Poi nella sub "Activity_Create" ho richiamato il metodo "Target" dell'oggetto all'interno di una condizione "FirstTime"
---> r_obj.Target = r_obj.RunStaticMethod("android.telephony.SmsManager", "getDefault", Null, Null)

Nella sub di invio del SMS è rimasta invece la chiamata a RunMethod4(""sendTextMessage", Array As Object ...etc...etc)
Beh non ci crederete
Per qualche magia i messaggi vengono inviati sempre sulla SIM1

./ ./ ./ ./ ./ ./ ./ ./ ./ ./

Umberto, adesso provo il tuo blocco:

Però mi suona male quell'assegnazione -----> slot=100 < ----
e poi subito dopo ----- > dim sl, slot as int <---- posto all'interno del loop For-Next

saluti >sim
././

./ ./ ./ ./ ./ ./ ./
 

udg

Expert
Licensed User
Longtime User
hai ragione, le dim vanno prima.. :oops: .. ho corretto, giusto per non lasciare "schifezze" in giro!

Credo che hai risolto con la questione del FirstTime. In pratica "fissi" nel tempo la SIM trovata in quell'occasione e la utilizzi di continuo con i successivi sendmessage.

Il problema lo potrai avere nuovamente quando la condizione FirstTime non sia più vera e quindi potrebbe essere selzionata una diversa SIM.
 

LucaMs

Expert
Licensed User
Longtime User
Non c'ho capito granché (dato che più che leggere ho "scorso"); mi pare di aver capito che il grande Umberto abbia trovato una funzione utile, da utilizzare sfruttando la Reflection.

Per il problema FirstTime probabilmente potreste risolvere usando il servizio Starter (dovrei rileggere ma sono pigro :p)


P.S.
dimenticavo...
HHHUUUHHH
:)
 

simpep

Member
Licensed User
Longtime User
. . . Il problema lo potrai avere nuovamente quando la condizione FirstTime non sia più vera e quindi potrebbe essere selzionata una diversa SIM.

Credo non sia così perché per definizione la condizione "FirstTime" nella sub "Activity_Create" dovrebbe essere vera solo una volta, all'attivazione del modulo, per cui l'oggetto carica il "Target" con "getDefault" solo in quella unica occasione.
---> r_obj.Target = r_obj.RunStaticMethod("android.telephony.SmsManager", "getDefault", Null, Null)

Quello che non capisco è come mai in questa unica occasione tutte le volte che lancio l'applicazione il "Target" sia sempre sulla SIM1, mentre se il "Target" viene caricato ogni volta che si invia un SMS (come era prima) allora ogni tanto questi punta anche alla SIM2.
Però adesso va benissimo così.
Un giorno o l'altro lo capirò

grazie per l'aiuto > sim
 
Top