import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.ServerSocket; import java.util.ArrayList; import java.util.List; import javax.media.MediaLocator; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smackx.jingle.IncomingJingleSession; import org.jivesoftware.smackx.jingle.JingleManager; import org.jivesoftware.smackx.jingle.JingleSession; import org.jivesoftware.smackx.jingle.JingleSessionRequest; import org.jivesoftware.smackx.jingle.OutgoingJingleSession; import org.jivesoftware.smackx.jingle.listeners.JingleSessionRequestListener; import org.jivesoftware.smackx.jingle.listeners.JingleTransportListener; import org.jivesoftware.smackx.jingle.media.JingleMediaManager; import org.jivesoftware.smackx.jingle.media.JingleMediaSession; import org.jivesoftware.smackx.jingle.media.PayloadType; import org.jivesoftware.smackx.jingle.mediaimpl.jmf.AudioChannel; import org.jivesoftware.smackx.jingle.mediaimpl.jmf.AudioFormatUtils; import org.jivesoftware.smackx.jingle.nat.ICETransportManager; import org.jivesoftware.smackx.jingle.nat.TransportCandidate; public class JingleAllTheWay extends JPanel { private static final long serialVersionUID = 1L; private static XMPPConnection xmppConnection; private static final String server = "******"; private static String jid = "155******0097@******/spark"; private static JingleManager jm = null; private static IncomingJingleSession incoming = null; private static OutgoingJingleSession outgoing = null; private static JButton admin, call, hangup; // just a simple frame public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(new Dimension(300, 100)); frame.setLocation(new Point(100, 100)); frame.setTitle("Jingle All The Way"); frame.getContentPane().add(new JingleAllTheWay(), BorderLayout.CENTER); frame.setVisible(true); } public JingleAllTheWay() { // button to log in as sue and set up to call bob admin = new JButton("155******97"); admin.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { login("1552******097", "8525330"); jid = "1366******872@******/spark"; } }); add(admin); // // button to login as bob and set up to call sue // seven = new JButton("seven"); // seven.addActionListener(new ActionListener(){ // public void actionPerformed(ActionEvent e) // { // login("155******097", "1"); // jid="admin@******/Smack"; // } // }); // add(seven); // button to call other person call = new JButton("Call to 136******872"); call.setEnabled(false); call.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (outgoing != null) return; try { System.out.print("被叫JID" + jid); outgoing = jm.createOutgoingJingleSession(jid); outgoing.addTransportListener(new TransportManager()); outgoing.start(); } catch (XMPPException e1) { e1.printStackTrace(); } } }); add(call); // button to hangup the call hangup = new JButton("Hangup"); hangup.setEnabled(false); hangup.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (outgoing != null) { try { outgoing.terminate(); } catch (XMPPException e1) { e1.printStackTrace(); } } if (incoming != null) { try { incoming.terminate(); } catch (XMPPException e1) { e1.printStackTrace(); } } } }); add(hangup); } // login to the server and enable/disable buttons public void login(String username, String password) { // XMPPConnection.DEBUG_ENABLED = true; xmppConnection = new XMPPConnection(server); try { xmppConnection.connect(); xmppConnection.login(username, password); ICETransportManager icetm0 = new ICETransportManager(xmppConnection, "jivesoftware.com", 3478); jm = new JingleManager(xmppConnection, icetm0, new JmfMediaManager()); jm.addCreationListener(icetm0); jm.addJingleSessionRequestListener(new JingleSessionRequestListener() { public void sessionRequested(JingleSessionRequest request) { if (incoming != null) { System.out.println("incoming open"); return; } try { // Accept the call incoming = request.accept(); incoming.addTransportListener(new TransportManager()); // Start the call incoming.start(); } catch (XMPPException e) { e.printStackTrace(); } } }); // make the logins unlogginable and allow user to place a call call.setEnabled(true); admin.setEnabled(false); // seven.setEnabled(false); } catch (XMPPException e) { e.printStackTrace(); } } // handle the jingle calls being connected and disconnected // disabling/enabling buttons private static class TransportManager implements JingleTransportListener { public void transportClosed(TransportCandidate cand) { System.out.println("session closed"); hangup.setEnabled(false); call.setEnabled(true); incoming = null; outgoing = null; } public void transportClosedOnError(XMPPException e) { System.out.println("session closed on error"); hangup.setEnabled(false); call.setEnabled(true); incoming = null; outgoing = null; } public void transportEstablished(TransportCandidate local, TransportCandidate remote) { System.out.println("session created"); hangup.setEnabled(true); call.setEnabled(false); } } // class that returns an instance of another class public static class JmfMediaManager extends JingleMediaManager { private static List<PayloadType> payloads = new ArrayList<PayloadType>(); static { payloads.add(new PayloadType.Audio(0, "PCMU", 16000)); payloads.add(new PayloadType.Audio(3, "gsm")); payloads.add(new PayloadType.Audio(4, "g723")); } @Override public JingleMediaSession createMediaSession(PayloadType payloadType, TransportCandidate remote, TransportCandidate local, JingleSession jingleSession) { return new MediaSession(payloadType, remote, local, null, jingleSession); } @Override public List<PayloadType> getPayloads() { return payloads; } } // not quite sure what this does public static class MediaSession extends JingleMediaSession { private AudioChannel audioChannel; public MediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, String locator, JingleSession jingleSession) { super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession); initialize(); } @Override public void initialize() { String ip; String localIp; int localPort; int remotePort; if (this.getLocal().getSymmetric() != null) { ip = this.getLocal().getIp(); localIp = this.getLocal().getLocalIp(); localPort = getFreePort(); remotePort = this.getLocal().getSymmetric().getPort(); System.out.println("Initialising: " + this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort); } else { ip = this.getRemote().getIp(); localIp = this.getLocal().getLocalIp(); localPort = this.getLocal().getPort(); remotePort = this.getRemote().getPort(); } audioChannel = new AudioChannel(new MediaLocator(this.getMediaLocator()), localIp, ip, localPort, remotePort, AudioFormatUtils.getAudioFormat(this.getPayloadType()), this); } @Override public void setTrasmit(boolean active) { audioChannel.setTrasmit(active); } @Override public void startReceive() { // if this is empty will i not receive audio? } @Override public void startTrasmit() { audioChannel.start(); } @Override public void stopReceive() { } @Override public void stopTrasmit() { if (audioChannel != null) audioChannel.stop(); } protected int getFreePort() { ServerSocket ss; int freePort = 0; for (int i = 0; i < 10; i++) { freePort = (int) (10000 + Math.round(Math.random() * 10000)); freePort = freePort % 2 == 0 ? freePort : freePort + 1; try { ss = new ServerSocket(freePort); freePort = ss.getLocalPort(); ss.close(); return freePort; } catch (IOException e) { e.printStackTrace(); } } try { ss = new ServerSocket(0); freePort = ss.getLocalPort(); ss.close(); } catch (IOException e) { e.printStackTrace(); } return freePort; } } } 参考:http://www.igniterealtime.org/community/message/185575#185575