Android Open Source - smsgateway-android B O S H Connection






From Project

Back to project page smsgateway-android.

License

The source code is released under:

GNU General Public License

If you think the Android project smsgateway-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.nubgames.smsgateway;
//w  w  w. ja  v a  2s .c  o  m
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.telephony.TelephonyManager;
import android.telephony.gsm.SmsManager;
import android.util.Log;

import com.calclab.emite.core.client.EmiteCoreModule;
import com.calclab.emite.core.client.bosh.BoshSettings;
import com.calclab.emite.core.client.bosh.Connection;
import com.calclab.emite.core.client.packet.IPacket;
import com.calclab.emite.core.client.xmpp.session.Session;
import com.calclab.emite.core.client.xmpp.session.Session.State;
import com.calclab.emite.core.client.xmpp.stanzas.IQ;
import com.calclab.emite.core.client.xmpp.stanzas.Message;
import com.calclab.emite.core.client.xmpp.stanzas.XmppURI;
import com.calclab.emite.im.client.InstantMessagingModule;
import com.calclab.emite.im.client.chat.Chat;
import com.calclab.emite.im.client.chat.ChatManager;
import com.calclab.suco.client.Suco;
import com.calclab.suco.client.events.Listener;

public class BOSHConnection extends Service {
    {
      if (! Suco.getComponents().hasProvider(Connection.class)) {
        Suco.install(new EmiteCoreModule());
        Suco.install(new InstantMessagingModule());
      }
    }

    /** Public interface. */
    public class LocalBinder extends Binder {
        /** Enqueue an SMS message to send to the server. */
        public void enqueue(String from, String body) {
          BOSHConnection.this.enqueue(from, body);
        }

        public int getStatus() {
          return BOSHConnection.this.getStatus();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
      Log.i("gw", "onBind()");
        return binder;
    }

    @Override
    public void onCreate() {
      Log.i("gw", "onCreate()");
      super.onCreate();
        // Keep the CPU from going to sleep.  OK to turn off the screen.
        wakelock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SMSGateway");
        wakelock.acquire();
        // And keep the network running!
        wifilock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)).createWifiLock(WifiManager.WIFI_MODE_FULL, "libraryh3lp");
        wifilock.acquire();
    }

    @Override
    public void onDestroy() {
      Log.i("gw", "onDestroy()");
      super.onDestroy();
      if (session.isLoggedIn()) {
        session.logout();
      }
      if (connection.isConnected()) {
        connection.disconnect();
      }
      if (wifilock != null && wifilock.isHeld()) {
        wifilock.release();
      }
      if (wakelock != null && wakelock.isHeld()) {
        wakelock.release();
      }
    }

    private boolean started = false;

    @Override
    public void onStart(Intent intent, int startId) {
      Log.i("gw", "onStart()");
        super.onStart(intent, startId);
        started = true;
        connect();
    }

    public BOSHConnection() {
      Log.i("gw", "BoshConnection()");
      initConnection();
    }

    private int getStatus() {
      if (! started) {
        return Status.NOT_RUNNING;
      }
      if (authFailed) {
        return Status.FAILED_AUTH;
      }

      switch (session.getState()) {
      case error:
        return Status.FAILED_CONNECT;
      case notAuthorized:
        return Status.FAILED_AUTH;
      case connecting:
        return Status.CONNECTING;
      case authorized:
        return Status.CONNECTING;
      case loggedIn:
        return Status.AUTHORIZING;
      case ready:
        return Status.CONNECTED;
      }

      return delay > 0 ? Status.RETRYING : Status.DISCONNECTED;
    }

    private void updateStatus() {
      Uri uri = Uri.fromParts("libraryh3lp", ""+getStatus(), null);
      Intent update = new Intent(Intent.ACTION_VIEW, uri);
      sendBroadcast(update);
    }

    private void initConnection() {
      Log.i("gw", "initConnection()");
        session.onStateChanged(new Listener<Session.State>() {
            public void onEvent(Session.State state) {
                switch (state) {
                case notAuthorized:
                  Log.i("gw", "notAuthorized");
                  authFailed = true;
                    break;
                case loggedIn:
                  Log.i("gw", "loggedIn");
                  authFailed = false;
                  break;
                case ready:
                  Log.i("gw", "ready");
                    handleReady();
                    break;
                case disconnected:
                  Log.i("gw", "disconnected");
                  break;
                }
                updateStatus();
            }
        });

        session.onIQ(new Listener<IQ>() {
          public void onEvent(IQ iq) {
            handleIQ(iq);
          }
        });

        chatManager.onChatCreated(new Listener<Chat>() {
            public void onEvent(Chat chat) {
                handleChatCreated(chat);
            }
        });

        connection.setSettings(new BoshSettings("http://"+Settings.getServer(this)+"/http-bind/", Settings.getServer(this), "1.6", 300, 1, 2));
        connection.onError(new Listener<String> () {
            public void onEvent(String msg) {
              handleError();
              updateStatus();
            }
        });
    }

    /** Deal with errors using progressively-delayed reconnection attempts. */
    private void handleError() {
      Log.i("gw", "handleError()");
      // Don't continue trying to log in with bad credentials.
      if (authFailed) {
        Log.i("gw", "auth failed error");
        return;
      }

      Log.i("gw", "schedling retry in " + delays[delay] + " seconds");
      TimerTask task = new TimerTask() {
        public void run() {
          Log.i("gw", "retrying");
          connect();
        }
      };
      new Timer().schedule(task, delays[delay]*1000);
      delay = Math.min(delays.length-1, delay+1);
    }

    private void handleChatCreated(Chat chat) {
      Log.i("gw", "handleChatCreated()");
      chat.onMessageReceived(new Listener<Message>() {
        public void onEvent(Message message) {
          handleMessage(message);
        }
      });
    }

    /** Handle an outgoing SMS message. */
    private void handleMessage(Message message) {
      try {
          Chat chat = chatManager.open(XmppURI.uri("android-sms."+Settings.getServer(this)));
          Message receipts = new Message(null, chat.getURI(), null);
        List<? extends IPacket> messages = message.getChildren("sms");
        for (IPacket sms : messages) {
          String id = sms.getAttribute("id");
          String phone = sms.getAttribute("to");
          String text = sms.getText();
          Log.i("gw", "got message: " + phone + " " + text);
              if (phone.matches(".*\\d{9,}") && ! outgoing.contains(id)) {
                try {
                  SmsManager manager = SmsManager.getDefault();
                  manager.sendMultipartTextMessage(phone, null, manager.divideMessage(text), null, null);
                } catch (Exception e) {
                }
                outgoing.add(id);
              }
            IPacket receipt = receipts.addChild("receipt", null);
            receipt.setAttribute("id", id);
            
            while (outgoing.size() > 10) {
              outgoing.remove(0);
            }
        }
        if (receipts.getChildrenCount() > 0) {
          chat.send(receipts);
          Log.i("gw", "sent receipts");
        }

        messages = message.getChildren("receipt");
        for (IPacket receipt : messages) {
          Log.i("gw", "got receipt");
          String id = receipt.getAttribute("id");
              Queue<QMsg> unackd = new LinkedList<QMsg>();
              while (! incoming.isEmpty()) {
                QMsg msg = incoming.remove();
                if (! msg.id.equals(id)) {
                  unackd.add(msg);
                }
              }
              incoming = unackd;
        }
        if (! incoming.isEmpty()) {
          handleReady();
        }
      } catch (Exception e) {
      }
    }

    /** Send any queued messages. */
    private void handleReady() {
      delay = 0;
      Chat chat = chatManager.open(XmppURI.uri("android-sms."+Settings.getServer(this)));
      Message message = new Message(null, chat.getURI(), null);
      for (QMsg msg : incoming) {
        IPacket sms = message.addChild("sms", null);
        sms.setAttribute("id", msg.id);
        sms.setAttribute("from", msg.phone);
        sms.setText(msg.text);
      }
      if (message.getChildrenCount() > 0) {
        chat.send(message);
        Log.i("gw", "sent messages");
      }
    }

    private void connect() {
      if (connection.isConnected()) {
        return;
      }

      String queue = Settings.getQueueName(this);
      String password = Settings.getPhoneID(this.getContentResolver());
      if (queue == null || password == null || queue.length() == 0) {
        authFailed = true;
        return;
      }

      session.login(XmppURI.uri(queue, Settings.getServer(this), "android"), password);
    }

    private void enqueue(String phone, String text) {
        // Only enqueue messages from other phones, so that we can use email as a "wake-up".
        if (phone.matches(".*\\d{9,}")) {
            incoming.add(new QMsg(phone, text));
        }

        if (session.isLoggedIn()) {
          handleReady();
        }
        if (! connection.isConnected()) {
          connect();
        }
    }

    private static final int[] delays = new int[]{5, 10, 15, 30, 60, 120, 300, 900};

    private LocalBinder binder      = new LocalBinder();
    private Connection  connection  = Suco.get(Connection.class);
    private Session     session     = Suco.get(Session.class);
    private ChatManager chatManager = Suco.get(ChatManager.class);

    private PowerManager.WakeLock wakelock;
    private WifiManager.WifiLock wifilock;
    private int delay = 0;
    private boolean authFailed = false;

    private class QMsg {
        public QMsg(String phone, String text) {
          this.id = BOSHConnection.messageId(phone, text);
            this.phone = phone;
            this.text = text;
        }

        public final String id;
        public final String phone;
        public final String text;
    };

    private Queue<QMsg> incoming = new LinkedList<QMsg>();
    private ArrayList<String> outgoing = new ArrayList<String>();

    private static int serial = 0;
    private static MessageDigest digest = null;

    private static String messageId(String phone, String text) {
        if (digest == null) {
            try {
                digest = MessageDigest.getInstance("SHA-1");
            }
            catch (NoSuchAlgorithmException nsae) {
            }
        }
        try {
          String data = ++serial + phone + text;
            digest.update(data.getBytes("UTF-8"));
        }
        catch (UnsupportedEncodingException e) {
        }
        return encodeHex(digest.digest());
    }

    private static String encodeHex(byte[] bytes) {
        StringBuilder hex = new StringBuilder(bytes.length * 2);
        for (byte aByte : bytes) {
            if (((int) aByte & 0xff) < 0x10) {
                hex.append("0");
            }
            hex.append(Integer.toString((int) aByte & 0xff, 16));
        }
        return hex.toString();
    }

    private void handleIQ(IQ iq) {
      if (iq.getType() != IQ.Type.get) {
        return;
      }

      IPacket query = iq.getFirstChild("query");
      String xmlns = query.getAttribute("xmlns");

      String result = null;
      if (xmlns.equals("libraryh3lp:iq:line1-number")) {
        result = getIQLine1Number();
      }
      if (xmlns.equals("libraryh3lp:iq:network-operator")) {
        result = getIQNetworkOperator();
      }
      if (xmlns.equals("libraryh3lp:iq:network-type")) {
        result = getIQNetworkType();
      }
      if (xmlns.equals("libraryh3lp:iq:software-version")) {
        result = getIQSoftwareVersion();
      }
      if (xmlns.equals("libraryh3lp:iq:version")) {
        result = getIQVersion();
      }

      if (result != null) {
        IQ reply = new IQ(IQ.Type.result);
        reply.setAttribute("id", iq.getAttribute("id"));
        reply.setAttribute("to", iq.getAttribute("from"));
        reply.addQuery(xmlns).setText(result);
        session.send(reply);
      }
    }

    private String getIQLine1Number() {
      TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
      return mgr.getLine1Number();
    }

    private String getIQNetworkOperator() {
      TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
      return mgr.getNetworkOperator() + "/" + mgr.getNetworkOperatorName();
    }

    private String getIQNetworkType() {
      ConnectivityManager mgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
      NetworkInfo info = mgr.getActiveNetworkInfo();
      return info.getTypeName() + "/" + info.getSubtypeName() + "/" + info.getExtraInfo();
    }

    private String getIQSoftwareVersion() {
      TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
      return mgr.getDeviceSoftwareVersion();
    }

    private String getIQVersion() {
      return "1.0.1";
    }
}




Java Source Code List

com.calclab.emite.core.client.EmiteCoreModule.java
com.calclab.emite.core.client.bosh.BoshConnection.java
com.calclab.emite.core.client.bosh.BoshSettings.java
com.calclab.emite.core.client.bosh.Connection.java
com.calclab.emite.core.client.bosh.StreamSettings.java
com.calclab.emite.core.client.packet.AbstractPacket.java
com.calclab.emite.core.client.packet.DelegatedPacket.java
com.calclab.emite.core.client.packet.IPacket.java
com.calclab.emite.core.client.packet.MatcherFactory.java
com.calclab.emite.core.client.packet.NoPacket.java
com.calclab.emite.core.client.packet.PacketMatcher.java
com.calclab.emite.core.client.packet.PacketRenderer.java
com.calclab.emite.core.client.packet.PacketTestSuite.java
com.calclab.emite.core.client.packet.Packet.java
com.calclab.emite.core.client.packet.TextPacket.java
com.calclab.emite.core.client.packet.TextUtils.java
com.calclab.emite.core.client.packet.android.AndroidPacket.java
com.calclab.emite.core.client.services.ConnectorCallback.java
com.calclab.emite.core.client.services.ConnectorException.java
com.calclab.emite.core.client.services.ScheduledAction.java
com.calclab.emite.core.client.services.Services.java
com.calclab.emite.core.client.services.android.AndroidConnector.java
com.calclab.emite.core.client.services.android.AndroidScheduler.java
com.calclab.emite.core.client.services.android.AndroidServices.java
com.calclab.emite.core.client.services.android.AndroidXMLService.java
com.calclab.emite.core.client.xmpp.resource.ResourceBindingManager.java
com.calclab.emite.core.client.xmpp.sasl.AuthorizationTransaction.java
com.calclab.emite.core.client.xmpp.sasl.Base64Coder.java
com.calclab.emite.core.client.xmpp.sasl.SASLManager.java
com.calclab.emite.core.client.xmpp.session.AbstractSession.java
com.calclab.emite.core.client.xmpp.session.IMSessionManager.java
com.calclab.emite.core.client.xmpp.session.IQManager.java
com.calclab.emite.core.client.xmpp.session.SessionComponent.java
com.calclab.emite.core.client.xmpp.session.SessionImpl.java
com.calclab.emite.core.client.xmpp.session.SessionReady.java
com.calclab.emite.core.client.xmpp.session.Session.java
com.calclab.emite.core.client.xmpp.stanzas.BasicStanza.java
com.calclab.emite.core.client.xmpp.stanzas.IQ.java
com.calclab.emite.core.client.xmpp.stanzas.Message.java
com.calclab.emite.core.client.xmpp.stanzas.Presence.java
com.calclab.emite.core.client.xmpp.stanzas.Stanza.java
com.calclab.emite.core.client.xmpp.stanzas.XmppURICache.java
com.calclab.emite.core.client.xmpp.stanzas.XmppURI.java
com.calclab.emite.im.client.InstantMessagingModule.java
com.calclab.emite.im.client.chat.AbstractChat.java
com.calclab.emite.im.client.chat.ChatManager.java
com.calclab.emite.im.client.chat.Chat.java
com.calclab.emite.im.client.chat.PairChatManager.java
com.calclab.emite.im.client.chat.PairChat.java
com.calclab.emite.im.client.presence.PresenceManagerImpl.java
com.calclab.emite.im.client.presence.PresenceManager.java
com.calclab.emite.im.client.roster.RosterImpl.java
com.calclab.emite.im.client.roster.RosterItem.java
com.calclab.emite.im.client.roster.Roster.java
com.calclab.emite.im.client.roster.SubscriptionManagerImpl.java
com.calclab.emite.im.client.roster.SubscriptionManager.java
com.calclab.emite.im.client.roster.SubscriptionState.java
com.calclab.suco.client.SucoCoreModule.java
com.calclab.suco.client.SucoFactory.java
com.calclab.suco.client.Suco.java
com.calclab.suco.client.events.Event0.java
com.calclab.suco.client.events.Event2.java
com.calclab.suco.client.events.Event.java
com.calclab.suco.client.events.Listener0.java
com.calclab.suco.client.events.Listener2.java
com.calclab.suco.client.events.Listener.java
com.calclab.suco.client.ioc.Container.java
com.calclab.suco.client.ioc.Decorator.java
com.calclab.suco.client.ioc.HashMapContainer.java
com.calclab.suco.client.ioc.Provider.java
com.calclab.suco.client.ioc.decorator.Chain.java
com.calclab.suco.client.ioc.decorator.GroupedSingleton.java
com.calclab.suco.client.ioc.decorator.NoDecoration.java
com.calclab.suco.client.ioc.decorator.ProviderCollection.java
com.calclab.suco.client.ioc.decorator.Singleton.java
com.calclab.suco.client.ioc.module.AbstractModule.java
com.calclab.suco.client.ioc.module.Factory.java
com.calclab.suco.client.ioc.module.ModuleBuilderImpl.java
com.calclab.suco.client.ioc.module.ModuleBuilder.java
com.calclab.suco.client.ioc.module.SucoModule.java
com.calclab.suco.client.log.Logger.java
com.calclab.suco.client.signal.Signal0.java
com.calclab.suco.client.signal.Signal2.java
com.calclab.suco.client.signal.Signal.java
com.calclab.suco.client.signal.Slot0.java
com.calclab.suco.client.signal.Slot2.java
com.calclab.suco.client.signal.Slot.java
com.nubgames.smsgateway.BOSHConnection.java
com.nubgames.smsgateway.BootCompleted.java
com.nubgames.smsgateway.Password.java
com.nubgames.smsgateway.SMSGateway.java
com.nubgames.smsgateway.SMSReceiver.java
com.nubgames.smsgateway.Settings.java
com.nubgames.smsgateway.StatusTextView.java
com.nubgames.smsgateway.Status.java
com.nubgames.smsgateway.TextRouter.java