Jumping Jack Flash weblog

Rilevare una chiamata in Jython con le Javaphone API

Posted in Java, Javaphone API, jython, Motorola a1000, Symbian, Symbian UIQ by jumpjack on 13 febbraio 2007

Ho “esteso” lo script jython di un precedente post: adesso il programma è in grado di accrogersi di una chiamata in arrivo, di leggere il numero del chiamante, e di scegliere di conseguenza se accettare la chiamata o rifiutarla.

Purtroppo sull’a1000 non è possibile nè rispondere alla chiamata nè rifiutarla: in entrambi i casi, infatti, il programma funziona, cioè accetta o rifiuta la chiamata… ma l’applicazione Phone non se ne accorge, e resta ad aspettare all’infinito che l’utente risponda o riagganci… anche se la telefonata in realtà è già stata accettata o rifiutata dallo script Jython!

Un’alternativa sarebbe far inviare dallo scipt Jython una “simulazione di tasto premuto” all’applicazione Phone, in modo da “premere” il tasto “occupato” o “rispondi” nel dialog che appare all’arrivo di una chiamata. Ma bisogna vedere se è tecnicamente possibile.
import javax.telephony.events
import os
import java.lang
import com.symbian.javax.telephony.mobile
import com.symbian.javax.telephony
import com.symbian.epoc.etel
import java.lang.Integer
import java.lang.String
import javax.net.datagram
import com.symbian.javax.net.datagram
from java.awt import Frame,MenuBar,Menu,MenuItem,TextArea,FileDialog
from java.awt.event import ActionEvent

class test(java.awt.Frame, com.symbian.epoc.etel.EtelLineListener):
def __init__(self):
self.size=(208,276)
self.myOutput=java.awt.TextArea(“Hello UIQ from Jython!!!\n”)
self.add(“Center”,self.myOutput)
self.myMenuBar=java.awt.MenuBar()
self.myMenu=java.awt.Menu(“Menu”)
self.myReadFile=java.awt.MenuItem(“Start”,actionPerformed=self.doStart) # Avvio routine principale da menu
self.myMenuExit=java.awt.MenuItem(“Exit”,actionPerformed=self.doExit)
self.myMenuBar.add(self.myMenu)
self.myMenu.add(self.myReadFile)
self.myMenu.add(self.myMenuExit)
self.setMenuBar(self.myMenuBar)
self.setVisible(1)

def doStart(self,event):
p=com.symbian.javax.telephony.mobile.EpocGsmMobileProvider()
ts=p.getTerminals()
t=ts[0]
tads=t.getAddresses()
tad=tads[0]
m=com.symbian.javax.telephony.mobile.EpocGsmMobileTerminal(tad,p)
mads=m.getAddresses()
m=mads[0]
print “Numero SIM:”,m.getSubscriptionId()
IMSIFile=open(“c:\\system\\data\\e32user.bin”,’r’)
IMSI=IMSIFile.read()
print “Numero registrato: \n”,IMSI
if java.lang.Integer.toString(m.getSubscriptionId()) != IMSI:
print “BRUTTO LADRONE!!!\n”
jnd=javax.net.datagram
dns=jnd.DatagramNameService
addr=com.symbian.javax.net.datagram.SMSAddress(“xxxxx”)
ds=jnd.DatagramService
serv=ds.getService(addr)
mex=java.lang.String(“ti hanno fregato il cellulare!!!”).getBytes()
d=jnd.Datagram(mex,addr)
serv.send(d)

def doExit(self,event):
java.lang.System.exit(0)

def callActive(self,event): #callListener (mai rilevato???)
print “callActive (callListener)\n”

def callInvalid(self,event): #callListener (mai rilevato???)
print “callInvalid (callListener)”

def callEventTransmissionEnded(self,event): #callListener
print “eventocallEventTransmissionEnded: ( callListener)”, event

def statusChange(self, line, num): # etelline, status (da EtelLineListener)
print “*********STATUSCHANGE*********”
print “Stato attuale: “, num , “\n”
self.myOutput.appendText(“Current call status: ” + java.lang.Integer.toString(num)+ “\n”)

def incomingCall(self, line, call): # etelline, etelcall (da EtelLineListener)
print ” —– INCOMING CALL —–”
self.myOutput.appendText(“INCOMING ” + call.getCallerId() + “…\n”)
print “->incoming call ‘” + call.getCallerId()
# print “prima rispondo,…”
# call.answer() # applicazione Phone si blocca!!
# print “…poi riattacco!”
# call.hangup() # applicazione Phone si blocca!!

def connectionAlerting(self,event):
print “Chiamata in arrivo da numero ”
incomingCall=event.getCall()
conns=incomingCall.getConnections()
# print “Numero connessioni ALERTING: “,len(conns)
addr1=conns[0].getAddress()
addr2=conns[1].getAddress()
numero1=addr1.getName() # Probabilmente numero LOCALE.
numero2=addr2.getName()
# print “1: ” + numero1 + “\n”
self.myOutput.appendText(“Chiamata in arrivo da ” + numero2 + “…”)
print numero2 + “\n”
#da qui non si puo’ riagganciare: solo da metodo incomingCall().

“””
def connectionConnected(self,event):
print “connectionConnected”
def connectionCreated(self,event):
print “connectionCreated: “, event
def connectionDisconnected(self,event):
print “connectionDisconnected”
def connectionFailed(self,event):
print “connectionFailed”
def connectionInProgress(self,event):
print “connectionInProgress”
def connectionUnknown(self,event):
print “connectionUnknown”
“””

if __name__==”__main__”:
myApp=test()

peer=com.symbian.javax.telephony.EpocJtapiPeer()
p=peer.getProvider(“EpocGsmMobileProvider”)
terms=p.getTerminals()
term=terms[0]
addrs=p.getAddresses()
addr=addrs[0]
lines1 = p.getPhone().getVoiceLines()
line1 = lines1[0]
lines2 = p.getVoiceLines()
line2 = lines2[0]
#addr.addCallListener(test()) # aggancia Listener all’Address
term=com.symbian.javax.telephony.mobile.EpocGsmMobileTerminal(addr,p)
#term.addCallListener(test())
line1.addLineListener(test())

print “READY.”

“””
ETEL CALL
public static final int STATUS_UNKNOWN = 0;
public static final int STATUS_IDLE = 1;
public static final int STATUS_DIALLING = 2;
public static final int STATUS_RINGING = 3;
public static final int STATUS_ANSWERING = 4;
public static final int STATUS_CONNECTING = 5;
public static final int STATUS_CONNECTED = 6;
public static final int STATUS_HANGING_UP = 7;

CONNECTION
public static final int IDLE = 48;
public static final int INPROGRESS = 49;
public static final int ALERTING = 50;
public static final int CONNECTED = 51;
public static final int DISCONNECTED = 52;
public static final int FAILED = 53;
public static final int UNKNOWN = 54;

TERMINAL CONNECTION
public static final int IDLE = 64;
public static final int RINGING = 65;
public static final int PASSIVE = 66;
public static final int ACTIVE = 67;
public static final int DROPPED = 68;
public static final int UNKNOWN = 69;

TERMINAL CONNECTION EVENT
public static final int TERMINAL_CONNECTION_ACTIVE = 115;
public static final int TERMINAL_CONNECTION_CREATED = 116;
public static final int TERMINAL_CONNECTION_DROPPED = 117;
public static final int TERMINAL_CONNECTION_PASSIVE = 118;
public static final int TERMINAL_CONNECTION_RINGING = 119;
public static final int TERMINAL_CONNECTION_UNKNOWN = 120;

CALL
public static final int IDLE = 32;
public static final int ACTIVE = 33;
public static final int INVALID = 34;

CALL EVENT
public static final int CALL_ACTIVE = 101;
public static final int CALL_INVALID = 102;
public static final int CALL_EVENT_TRANSMISSION_ENDED = 103;

CONNECTION EVENT
public static final int CONNECTION_ALERTING = 104;
public static final int CONNECTION_CONNECTED = 105;
public static final int CONNECTION_CREATED = 106;
public static final int CONNECTION_DISCONNECTED = 107;
public static final int CONNECTION_FAILED = 108;
public static final int CONNECTION_IN_PROGRESS = 109;
public static final int CONNECTION_UNKNOWN = 110;

SINGLE CALL META EVENT
public static final int SINGLECALL_META_PROGRESS_STARTED = 210;
public static final int SINGLECALL_META_PROGRESS_ENDED = 211;
public static final int SINGLECALL_META_SNAPSHOT_STARTED = 212;
public static final int SINGLECALL_META_SNAPSHOT_ENDED = 213;

ADDRESS_EVENT_TRANSMISSION_ENDED = 100

“””

Rilevare una chiamata in Jython – vecchio post

Posted in Java, Javaphone API, jython, Motorola a1000, Symbian, Symbian UIQ by jumpjack on 9 febbraio 2007

Questo post si è evoluto in quest’altro più completo

Per intercettare una chiamata usando Jython e Javaphone API bisogna usare listener ed eventi di Java.

Quando una classe Java implementa un listener, ogni volta che si verifica un evento gestito da quel listener esso verrà “inoltrato” alla classe; questa lo potrà gestire se contiene un metodo che ha lo stesso nome dell’evento.

Una chiamata è gestita dal listener CallListener. L’arrivo di una chiamata causa un evento callActive(CallEvent event). Il metodo Event.getID() restituisce il tipo di evento: CALL_ACTIVE, CALL_INVALID, CALL_EVENT_TRANSMISSION_ENDED.

Partendo da questo sorgente di esempio:

class action(awt.event.ActionListener):
def actionPerformed(self,event):
java.lang.System.exit(0)

button = awt.Button(“Close Me!”) button.addActionListener(action())

che equivale a questo:

def exit(event):
java.lang.System.exit(0)

button = awt.Button(“Close Me!”, actionPerformed=exit)

si può provare a dedurre il codice Jython necessario a rilevare una chiamata in arrivo:

class gestisciChiamate(java.awt.Frame, javax.telephony.CallListener):
def callActive(self,event):
print “E’ arrivata una chiamata!”

Bisogna però “agganciare” le chiamate alla classe. Se aver definito la classe non è sufficiente, forse bisogna aggiungere un listener all’address del telefono:

“In order to register as a listener for events reported for all calls involving a specific Address, as soon as the Calls are created, an application may implement the CallListener interface and then register with the Address, via the Address.addCallListener method.”

Bisogna quindi “prendere” un Address dal Provider, e applicargli il metodo addListener; tutto questo dovrà essere fatto FUORI dalla classe, nell’inizializzazione del programma (o nel metodo __init__):

[…]
import com.symbian.javax.telephony
peer = com.symbian.javax.telephony.EpocJtapiPeer()
myprovider = peer.getProvider(“EpocGsmMobileProvider”)
terms = myprovider.getTerminals
term = terms[0]
term.addCallListener(gestisciChiamate())

Realizzare un “antifurto” per cellulari in Jython

Posted in jython, Motorola a1000, Programmazione, Symbian, Symbian UIQ by jumpjack on 9 febbraio 2007

In Jython è possibile leggere il numero della carta SIM (IMSI), leggere dati da file e inviare messaggi di nascosto dall’utente, senza che vengano nemmeno salvati in OUTBOX.

Combinando le tre cose, è possibile scrivere un programma che rileva se nel cellulare viene inserita una SIM diversa da quella originale, e in quel caso inviare un messaggio a un numero predefinito.

Ecco una bozza di possibile programma, che però effettua il controllo alla scelta della prima voce di menu: il vero “antifurto” dovrà invece ovviamente fare il controllo appena il programma parte, e tale programma dovrà essere messo in autoavvio.

import os
import java.lang
import com.symbian.javax.telephony.mobile
import java.lang.Integer
import java.lang.String
import javax.net.datagram
import com.symbian.javax.net.datagram
from java.awt import Frame,MenuBar,Menu,MenuItem,TextArea,FileDialog
from java.awt.event import ActionEvent
class test(java.awt.Frame):
-á -á def __init__(self):
-á -á -á -á self.size=(208,276)
-á -á -á -á self.myOutput=java.awt.TextArea(“Selezionare il menu ‘Verifica’.”)
-á -á -á -á self.add(“Center”,self.myOutput)
-á -á -á -á self.myMenuBar=java.awt.MenuBar()
-á -á -á -á self.myMenu=java.awt.Menu(“Menu”)
-á -á -á-áself.myReadFile=java.awt.MenuItem(“Verifica”,actionPerformed=self.doRead)
-á -á -á-áself.myMenuExit=java.awt.MenuItem(“Exit”,actionPerformed=self.doExit)
-á -á -á -á self.myMenuBar.add(self.myMenu)
-á -á -á -á self.myMenu.add(self.myReadFile)
-á -á -á -á self.myMenu.add(self.myMenuExit)
-á -á -á -á self.setMenuBar(self.myMenuBar)
-á -á -á -á self.setVisible(1)
-á -á def doRead(self,event):
-á -á -á -á p=com.symbian.javax.telephony.mobile.EpocGsmMobileProvider()
-á -á -á -á ts=p.getTerminals()
-á -á -á -á t=ts[0]
-á -á -á -á tads=t.getAddresses()
-á -á -á -á tad=tads[0]
-á -á -á -á m=com.symbian.javax.telephony.mobile.EpocGsmMobileTerminal(tad,p)
-á -á -á -á mads=m.getAddresses()
-á -á -á -á m=mads[0]
-á -á -á -á print “Numero SIM:”,m.getSubscriptionId()
-á -á -á -á IMSIFile=open(“c:\\system\\data\\e32user.bin”,’r’)
-á -á -á -á IMSI=IMSIFile.read()
-á -á -á -á print “Numero registrato: “,IMSI
-á -á -á -á if java.lang.Integer.toString(m.getSubscriptionId()) != IMSI:
-á -á -á -á -á -á print “BRUTTO LADRONE!!!”
-á -á -á -á -á -á jnd=javax.net.datagram
-á -á -á -á -á -á dns=jnd.DatagramNameService
-á -á -á -á -á -á addr=com.symbian.javax.net.datagram.SMSAddress(“NUMERO DESTINATARIO”)
-á -á -á -á -á -á ds=jnd.DatagramService
-á -á -á -á -á -á serv=ds.getService(addr)
-á -á -á -á -á -á mex=java.lang.String(“ti hanno fregato il cellulare!!!”).getBytes()
-á -á -á -á -á -á d=jnd.Datagram(mex,addr)
-á -á -á -á -á -á serv.send(d)
-á -á def doExit(self,event):
-á -á -á -á java.lang.System.exit(0)
if __name__==”__main__”:
-á -á myApp=test()

Javaphone API e Motorola a1000 (Symbian UIQ)

Posted in Java, Javaphone API, jython, Motorola a1000, Symbian, Symbian UIQ by jumpjack on 1 febbraio 2007

Il motorola a1000 supporta il Personal Java, il predecessore del “Personal Profile” della piattaforma J2ME. Inoltre, nell’a1000 sono presenti le Javaphone API, librerie java che permettono di accedere a funzioni tipiche del cellulare come rubrica, agenda, SMS… Accedere alle javaphone API tramite Java è piuttosto complicato, essendo piuttosto complicato il java in sè. Ma fortunatamente ci viene in aiuto Python, un linguaggio di scripting, molto piu’ semplice e intuitivo del java, e che permette di “lanciare comandi” anche senza scrivere nessun programma, semplicemente usando una “console”. Il Python supportato dall’a1000 si chiama Jython, che sta per “Python su Java”: in pratica, voi scrivete in Python, e il vostro programma viene interpretato e tradotto in Java, in tempo reale. Questo rende possibili fare cose molto interessanti, come leggere l’IMEI del cellulare, l’IMSI (=numero della carta SIM), effettuare chiamate, inviare SMS. Qui di seguito riporterò man mano le mie scoperte riguardo l’uso delle Javaphone API tramite Jython. Naturalmente ogni commento/suggerimento è benvenuto. Per esempio: è possibile accedere alle “informazioni di cella” con le javaphone API? Da questo link è possibile scaricare JythonQ , il porting di Jython per UIQ: DOWNLOAD JythonQ

Thread di riferimento su Forum Nokia

Programmi di esempio in Jython

Linea di comando per jRun.txt per lanciare script python: -cp D:’jython’awtcons.jar;D:’jython -Dpython.home=d:’jython org.python.util.jython d:’jython’NOMEFILE.py

Leggere livello sel segnale:

>>> import com.symbian.javax.telephony.mobile
>>> mp = com.symbian.javax.telephony.mobile.EpocGsmMobileProvider()
>>> print mp.getSignalLevel

Effettuare una chiamata “di nascosto”, senza che sia possibile riagganciare!
>>> import com.symbian.javax.telephony.mobile
>>> p = com.symbian.javax.telephony.mobile.EpocGsmMobileProvider()
>>> ts = p.getTerminals()
>>> t = ts[0]
>>> tads = t.getAddresses()
>>> tad = tads[0]
>>> mc = p.createCall()
>>> call = mc.connect(t,tad,”numero”)

Leggere il “subscriber ID” (IMSI), ovvero il codice univoco associato dalla rete alla propria USIM:
>>> import com.symbian.javax.telephony.mobile
>>> p = com.symbian.javax.telephony.mobile.EpocGsmMobileProvider()
>>> ts = p.getTerminals()
>>> t = ts[0]
>>> tads = t.getAddresses()
>>> tad = tads[0]
>>> m = com.symbian.javax.telephony.mobile.EpocGsmMobileTerminal(tad,p)
>>> mads = m.getAddresses()
>>> m = mads[0]
>>> print m.getSubscriptionId()

Metodo breve per ottenere l’IMSI:
>>> import com.symbian.javax.telephony.mobile
>>> p = com.symbian.javax.telephony.mobile.EpocGsmMobileProvider()
>>> print com.symbian.javax.telephony.mobile.EpocMobileAddress(p).getSubscriptionId()

Leggere IMEI:
>>> import com.symbian.epoc.etel
>>> a = com.symbian.epoc.etel.Etel
>>> b= a.getPhone()
>>> print b.getPhoneId().serialNumber

Leggere lo stato della batteria in pecentuale. Purtroppo non funziona: restituisce sempre il valore di default 0x7fff.ffff , come se il cell fosse sempre in carica!
>>> import javax.power.monitor
>>> pm = javax.power.monitor
>>> pmi = pm.PowerMonitor.getInstance()
>>> print pmi.getBatteryLevel()
>>> print pmi.getEstimatedSecondsRemaining()
>>> print pmi.usingExternalPowerSource()

Mandare un SMS a un contatto della rubrica:
>>> import java.lang.String
>>> import javax.net.datagram
>>> jnd = javax.net.datagram
>>> dns = jnd.DatagramNameService
>>> addr = dns.lookupAll(nomedeltizio,”SMS”) (trova tutti i numeri a cui è possibile inviare un SMS, e li mette nell’array addr[] , i cui elementi saranno addr[0], addr[1] ecc…
>>> ds = jnd.DatagramService
>>> serv = ds.getService(addr[0])
>>> mex = java.lang.String(“questo è il messaggio”).getBytes()
>>> d = jnd.Datagram(mex,addr[0])
>>> serv.send(d)

Mandare un SMS a un numero qualunque:
>>> import java.lang.String
>>> import javax.net.datagram
>>> import com.symbian.javax.net.datagram Per poter creare un oggetto Address a partire da una stringa-numero.
>>> jnd = javax.net.datagram
>>> dns = jnd.DatagramNameService
>>> addr = com.symbian.javax.net.datagram.SMSAddress(“+393490000000”)
>>> ds = jnd.DatagramService
>>> serv = ds.getService(addr)
>>> mex = java.lang.String(“questo è il messaggio”).getBytes()
>>> d = jnd.Datagram(mex,addr)
>>> serv.send(d)

Come accedere ai metodi di EtelGsmPhone:
>>> import com.symbian.javax.telephony.mobile
>>> p = com.symbian.javax.telephony.mobile.EpocGsmMobileProvider()
>>> ph = p.getPhone()

Adesso “ph” è di tipo EtelGsmPhone. Si possono quindi usare metodi come:

– getDetectedNetworks() (restituisce array di EtelGsmNetworkInfo, che contiene .status, .code, .shortName, .longName ; sull’a1000 dà “none”: bisogna usare il metodo getAvailableNetowrks di EpocGsmMobileProvider, ma comunque i risultati non sono leggibili (???). Usando invece getCurrentNetwork() di EpocGsmMobileProvider è possibile conoscere la rete attualmente in uso.

getOwnNumbers() (restituisce array di stringhe; dà “-5” (=NOT SUPPORTED) sull’a1000 😦 )

getSubscriptionId() (=IMSI)

getPhoneId() (restituisce tipo EtelGsmPhoneId, che contiene .manufacturerId, .modelId, .revisionId, .serialNumber (=IMEI)

getVoiceLines() (restituisce array di EtelGsmLine

Chiamate telefoniche
Per gli esempi che seguono, premettere sempre queste istruzioni:

>>> import com.symbian.javax.telephony

>>> jtp = javax.telephony.JtapiPeerFactory.getJtapiPeer(“”)

>>> p = jtp.getProvider(“EpocGsmMobileProvider”)

– Effettuare una chiamata:

>>> lines = p.getPhone().getVoiceLines()

>>> call = lines[0].newCall()

>>> call.dial(“numero”)

>>> cal.hangup()          per riagganciare 

– Rispondere a una chiamata:

>>> calls = p.getCalls()

>>> call=calls[0]

>>> call.answer()

– Riagganciare (rifiutare?)

>>> call.hangup()

– Leggere il numero del chiamante

>>> print call.getCallerId()