ServiceIRCService.java :  » Client » androidchat » net » androidchat » client » Android Open Source

Android Open Source » Client » androidchat 
androidchat » net » androidchat » client » ServiceIRCService.java
package net.androidchat.client;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Parcel;
import android.util.Log;

public class ServiceIRCService extends Service {
  public static Context context;
  private static Thread connection;
  private static Thread updates;
 
  private static Socket socket;
  public static BufferedWriter writer;
  public static BufferedReader reader;
  public static int state;
  private static String server = "irc.freenode.net";// "38.100.42.254"; //
  public static String nick = "AndroidChat";

  public static final int MSG_UPDATECHAN = 0;
  public static final int MSG_CLEARPROGRESS = 1;
  public static final int MSG_CHANGECHAN = 2;
  public static final int MSG_DISCONNECT = 3;
  public static final int MSG_CHANGEWINDOW = 4;

  public static final String AC_VERSION = "1.02b";

  private static boolean is_first_list;

  public static HashMap<String, ClassChannelContainer> channels;
  public static HashMap<String, ClassChannelDescriptor> channel_list;
  public static HashMap<String, Location> temp_user_locs;

  public static Handler ChannelViewHandler;

  public static String lastwindow = "~status";
  public static String curwindow = "~status";
  

  public static Boolean shownChanListConnect = false;
  
  
  public static void SetViewHandler(Handler what)
  {
    ChannelViewHandler = what;
    Message.obtain(ServiceIRCService.ChannelViewHandler,
        ServiceIRCService.MSG_CHANGEWINDOW, ServiceIRCService.curwindow)
        .sendToTarget();
    
  }
  
  // this is epic irc parsing.
  public static void GetLine(String line) {
    // rfc 2812
    // [:prefix] command|numeric [arg1, arg2...] :extargs

    //Log.d("ServiceIRCService", "raw line: " + line);

    String args, prefix, command;
    args = prefix = command = "";

    //System.out.println("debug: " + line);

    boolean flagupdate = false;
    String updatechan = "";

    // pull off extended arguments first
    if (line.indexOf(":", 2) != -1)
      args = line.substring(line.indexOf(":", 2) + 1).trim();

    // if we have extended arguments, remove them from the parsing
    if (args.length() > 0)
      line = line.substring(0, line.length() - args.length());

    String[] toks = line.split(" "); // split by spaces.

    if (toks[0].startsWith(":")) // we have a prefix
    {
      prefix = toks[0].substring(1);
      command = toks[1];
    } else {
      prefix = null;
      command = toks[0];
    }

    if (command.equals("641"))
    // :servername 641 yournick #channel lat long
    {
      ClassChannelContainer temp;
      String chan = toks[3].toLowerCase();
      if (channels.containsKey(chan)) {
        temp = channels.get(chan);
        temp.loc_lat = Float.parseFloat(toks[4]);
        temp.loc_lng = Float.parseFloat(toks[5]);
      }

      if (channel_list.containsKey(chan)) {
        ClassChannelDescriptor t = channel_list.get(chan);
        t.loc_lat = Float.parseFloat(toks[4]);
        t.loc_lng = Float.parseFloat(toks[5]);
      }
    } else if (command.equals("640")) // user location numeric
    {  
      //>> :irc.androidchat.com 640 Kuja poffy -0 -0
      
      //Location l = new Location();
      //l.setLatitude(Float.parseFloat(toks[4]));
      //l.setLongitude(Float.parseFloat(toks[5]));
      
      if(temp_user_locs.containsKey(toks[3].toLowerCase()))
      {
        //temp_user_locs.get(toks[3].toLowerCase()).setLatitude(l.getLatitude());
        //temp_user_locs.get(toks[3].toLowerCase()).setLongitude(l.getLongitude());
      }      
      //else
        //temp_user_locs.put(toks[3].toLowerCase(), l);      
      
    } else if (command.equals("323")) // list end numeric
    {
      is_first_list = true;
    } else if (command.equals("322")) // list numeric
    { // 0 1 2 3 4 args
      // :servername 322 yournick <channel> <#_visible> :<topic>
      // :irc.androidchat.com 322 AndroidChat #hi 3 :[+nt] SVN update for
      // MASSIVE UI DAMAGE. Like, it's actually approaching usable now. I
      // changed a LOT of behavior. I need you to create an options
      // activity, and then I think we're nearly done as far as the client
      // is concerned.

      if (is_first_list) {
        channel_list.clear();
        is_first_list = false;
      }
      /*
       * if (channel_list.containsKey(toks[2])) { ClassChannelDescriptor t =
       * channel_list.get(toks[2]); t.channame = toks[2]; t.chantopic =
       * args; t.chatters = Integer.parseInt(toks[3]);
       * 
       * RequestChannelLocation(toks[2]); } else {
       */
      ClassChannelDescriptor t = new ClassChannelDescriptor();
      try {
      
      t.channame = toks[3];
      t.chantopic = args.substring(args.indexOf("]") + 1).trim();
      t.chatters = Integer.parseInt(toks[4]);
    
      } catch (ArrayIndexOutOfBoundsException aioobe)
      {
        
      } 
      channel_list.put(toks[3], t);
      //RequestChanLocation(toks[3]);
      // }
    } else if (command.equals("TOPIC")) {
      //> :Kuja!Kuja@AFCBE3.FDA6AD.34D090.09AED6 TOPIC #hi :Welcome to AndroidChat!!!
      ClassChannelContainer temp;
      String chan = toks[2].toLowerCase();
      if (channels.containsKey(chan)) {
        temp = channels.get(chan);
        temp.addLine("*** Topic for " + toks[2] + " is now: " + args);
        temp.chantopic = args;
        flagupdate = true;
        updatechan = chan;
      } // ignore topics for channels we aren't in
    } else if (command.equals("331") || command.equals("332")) // topic
    // numeric
    // :servername 331 yournick #channel :no topic
    // :servername 332 yournick #channel :topic here
    {
      ClassChannelContainer temp;
      String chan = toks[3].toLowerCase();
      if (channels.containsKey(chan)) {
        temp = channels.get(chan);
        temp.addLine("*** Topic for " + toks[3] + " is: " + args);
        temp.chantopic = args;
        flagupdate = true;
        updatechan = chan;
      } // ignore topics for channels we aren't in

    } else if (command.equals("372")) {
      if (ChannelViewHandler != null) {
        channels.get("~status").addLine(args);
        Message.obtain(ChannelViewHandler,
            ServiceIRCService.MSG_UPDATECHAN, "~status")
            .sendToTarget();
      }
    } else if (command.equals("353")) {
      // :dexter.chatspike.net 353 yournick = #funfactory :chattie dizz
      // @+takshaka
      // poshgal @LDI Aldebaran Sweet2 James54
      if (channels.containsKey(toks[4].toLowerCase())) {
        String[] incoming = args.split(" ");
        ClassChannelContainer c = channels.get(toks[4].toLowerCase());
        if (c.NAMES_END == true) {
          c.NAMES_END = false;
          c.chanusers.clear();
        }

        for (String s : incoming) {
          c.chanusers.add(s.trim());
        }

      }
    } else if (command.equals("366")) {
      // :dexter.chatspike.net 366 t #testtest :End of /NAMES list.
      String chan = toks[3].toLowerCase();
      if (channels.containsKey(chan)) {
        channels.get(chan).NAMES_END = true;

        StringBuilder sb = new StringBuilder();

        sb.append("*** Users on ").append(toks[3]).append(": ");
        for (String s : channels.get(chan).chanusers) {
          sb.append(s).append(" ");
        }

        channels.get(chan).addLine(sb.toString().trim());

        flagupdate = true;
        updatechan = chan;
      }
    } else if (command.equals("NICK")) {
      // :nick!mask@mask NICK newnick
      // :Testing!AndroidChat@71.61.229.105 NICK Poop

      String oldnick = toks[0].substring(1, toks[0].indexOf("!"));
      if (nick.toLowerCase().equals(oldnick.toLowerCase())) // we
                                  // changed
      // /our/ nickname
      {
        nick = toks[2];
      }

      for (ClassChannelContainer c : channels.values()) {
        for (String s : c.chanusers) {
          if (s.toLowerCase().equals(oldnick.toLowerCase())) {
            c.chanusers.remove(s);
            c.chanusers.add(toks[2]);
            c.addLine("*** " + oldnick + " is now known as "
                + toks[2]);
            if (ChannelViewHandler != null)
              Message.obtain(ChannelViewHandler,
                  ServiceIRCService.MSG_UPDATECHAN,
                  c.channame.toLowerCase()).sendToTarget();
            break;
          }
        }
      }
      // todo: notify of nick renames here
    } else if (command.equals("QUIT")) {
      // :Jeff!Kuja@71.61.229.105 QUIT :
      String whoquit = toks[0].substring(1, toks[0].indexOf("!"));

      for (ClassChannelContainer c : channels.values()) {
        for (String s : c.chanusers) {
          if (s.toLowerCase().equals(whoquit.toLowerCase())) {
            c.chanusers.remove(s);
            c.addLine("*** " + whoquit + " has disconnected ("
                + args + ")");
            if (ChannelViewHandler != null)
              Message.obtain(ChannelViewHandler,
                  ServiceIRCService.MSG_UPDATECHAN,
                  c.channame.toLowerCase()).sendToTarget();
            break;
          }
        }
      }

    } else if (command.equals("KICK")) {
      // :prefix kick #chan who :why
      if (channels.containsKey(toks[2].toLowerCase())) {
        ClassChannelContainer c = channels.get(toks[2].toLowerCase());
        if (c.chanusers.contains(toks[3]))
          c.chanusers.remove(toks[3]);
        c.addLine("*** " + toks[3] + " was kicked (" + args + ")");
        flagupdate = true;
        updatechan = toks[2];
      }
    } else if (command.equals("PART"))
    // User must have left a channel
    {
      // :Kraln!Kraln@71.61.229.105 PART #hi
      String who = toks[0].substring(1, toks[0].indexOf("!"));
      ClassChannelContainer temp;
      if (who.equals(nick)) // if we joined a channel
      {

        if (channels.containsKey(toks[2].toLowerCase())) // existing
        // channel?
        {
          
          temp = channels.get(toks[2].toLowerCase());
          temp.addLine("*** You have left this channel.");

          if (ChannelViewHandler != null) {
            Message.obtain(ChannelViewHandler,
                ServiceIRCService.MSG_UPDATECHAN,
                temp.channame.toLowerCase()).sendToTarget();
            
          
            Message.obtain(ChannelViewHandler,
                ServiceIRCService.MSG_CHANGEWINDOW, lastwindow)
                .sendToTarget();
  
            lastwindow = "~status";
          }
          
          channels.remove(temp.channame.toLowerCase()); // it will now
          flagupdate = false;
          updatechan = "~status";
        }
      } else {
        temp = channels.get(toks[2].toLowerCase());
        temp.chanusers.remove(who);
        temp.addLine("*** " + who + " has left the channel.");
        flagupdate = true;
        updatechan = toks[2].toLowerCase();
      }
      
    } else if (command.equals("JOIN"))
    // User must have joined a channel
    {
      String who = toks[0].substring(1, toks[0].indexOf("!"));
      ClassChannelContainer temp;
      Log.d("IRC - Debug", "******* Nick is " + nick + " *************");
      if (who.equals(nick)) // if we joined a channel
      {

        if (channels.containsKey(args.toLowerCase())) // existing
                                // channel?
        {
          temp = channels.get(args.toLowerCase());
        } else {
          temp = new ClassChannelContainer();
          temp.channame = args.toLowerCase();
          temp.addLine("*** Now talking on " + args + "...");
          channels.put(args.toLowerCase(), temp);
          if (ChannelViewHandler != null)
          {
            Message.obtain(ChannelViewHandler,
                ServiceIRCService.MSG_CHANGEWINDOW,
                args.toLowerCase()).sendToTarget();
            Message.obtain(ChannelViewHandler,
                ServiceIRCService.MSG_UPDATECHAN,
                args.toLowerCase()).sendToTarget();
        
          }
        }
      } else {
        if (args.equals("")) {
          temp = channels.get(toks[2].toLowerCase());
        } else {
          temp = channels.get(args.toLowerCase());
        }
        temp.chanusers.add(who);
        temp.addLine("*** " + who + " has joined the channel.");
      }
      flagupdate = true;
      updatechan = args.toLowerCase();

    } else if (command.equals("PRIVMSG"))
    // to a channel?
    {
      ClassChannelContainer temp;
      String chan = toks[2].toLowerCase();

      if (channels.containsKey(chan)) // existing channel?
      {
        temp = channels.get(chan);
        if (args.trim().startsWith("ACTION")) {
          /* temp.addLine("* "
              + toks[0].substring(1, toks[0].indexOf("!")) + " "
              + args.substring(7));*/
          temp.addLine("***" + toks[0].substring(1, toks[0].indexOf("!")) + "~+" + args);
        } else
          /*temp.addLine("<"
              + toks[0].substring(1, toks[0].indexOf("!")) + "> "
              + args);*/
          temp.addLine(toks[0].substring(1, toks[0].indexOf("!")) + "~+" + args);
        
        flagupdate = true;
        updatechan = chan;
      } else if (chan.equals(nick.toLowerCase())) // crap, it's a private
      // message
      { // :Kraln!Kuja@71.61.229.105 PRIVMSG AndroidChat2 :Hello

        String who = toks[0].substring(1, toks[0].indexOf("!"));
        if (channels.containsKey(who.toLowerCase())) // existing pm
        {
          temp = channels.get(who.toLowerCase());
        } else {
          temp = new ClassChannelContainer();
          temp.channame = who;
          temp.addLine("*** Now talking with " + who + "...");
          temp.IS_PM = true;
          channels.put(who.toLowerCase(), temp);
          if(context.getSharedPreferences("androidChatPrefs", 0).getBoolean("pmAlert", true))
          { if (ChannelViewHandler != null)  {
            Message.obtain(ChannelViewHandler,
                ServiceIRCService.MSG_CHANGEWINDOW,
                who.toLowerCase()).sendToTarget();
            if (ChannelViewHandler != null) 
              Message.obtain(ChannelViewHandler,
                  ServiceIRCService.MSG_UPDATECHAN,
                  who.toLowerCase()).sendToTarget();
            
          } } else 
            if (ChannelViewHandler != null) 
            Message.obtain(ChannelViewHandler,
                ServiceIRCService.MSG_UPDATECHAN,
                who.toLowerCase()).sendToTarget();
        }
        temp.addLine("<" + who + "> " + args);
        /*mNM.notify(R.string.irc_started, new Notification(context,
            R.drawable.mini_icon, context
                .getText(R.string.ui_newpm), System
                .currentTimeMillis(),
            "AndroidChat - Notification", context
                .getText(R.string.ui_newpm), null,
            R.drawable.mini_icon, "Android Chat", null));*/
        
        flagupdate = true;
        updatechan = who.toLowerCase();
      }
    }

    if (flagupdate) {
      if (ChannelViewHandler != null)
        Message.obtain(ChannelViewHandler,
            ServiceIRCService.MSG_UPDATECHAN,
            updatechan.toLowerCase()).sendToTarget();
    }

  }

  public static void JoinChan(String channel) {
    try {
      String temp = "JOIN " + channel + "\n";
      writer.write(temp);
      writer.flush();
    } catch (IOException e) {
      e.printStackTrace();
    } catch (NullPointerException npe) {
      npe.printStackTrace();
    }
  }

  /*public static void AskForChannelList() {

    try {
      String temp = "LIST\n";
      writer.write(temp);
      writer.flush();
    } catch (IOException e) {
      e.printStackTrace();
    } catch (NullPointerException npe) {
      npe.printStackTrace();
    }
  }*/

  public static void QuitServer() {
    try {
      String temp = "QUIT :AndroidChat client has quit\n";
      writer.write(temp);
      writer.flush();
      ServiceIRCService.state = -1;
      ServiceIRCService.reader.close();
      ServiceIRCService.connection.interrupt();
      //mNM.cancel(R.string.irc_started);
      ((Service)context).stopSelf();

    } catch (IOException e) {
      e.printStackTrace();
    } catch (NullPointerException npe) {
      npe.printStackTrace();
    }

  }
  
  public static void OpenPMWindow(String who) {
    ClassChannelContainer temp;

  
    if (channels.containsKey(who.toLowerCase())) // existing pm
    {
      if (ChannelViewHandler != null)  {
        Message.obtain(ChannelViewHandler,
            ServiceIRCService.MSG_CHANGEWINDOW,
            who.toLowerCase()).sendToTarget();
        
        
      }
    } else {
      temp = new ClassChannelContainer();
      temp.channame = who;
      temp.addLine("*** Now talking with " + who + "...");
      temp.IS_PM = true;
      channels.put(who.toLowerCase(), temp);
      if (ChannelViewHandler != null)  {
        Message.obtain(ChannelViewHandler,
            ServiceIRCService.MSG_CHANGEWINDOW,
            who.toLowerCase()).sendToTarget();
        
      
      }
    }
  }

  public static void SendToChan(String chan, String what) {
    if (what.trim().equals(""))
      return;

    if (what.startsWith("/")) {
      // this is a raw command.
      // parse here for intelligent commands, otherwise send it along raw

      if (what.startsWith("/me ")) // special case...
      {
        try {
          String temp = "PRIVMSG " + chan + " :" + '\001' + "ACTION "
              + what.substring(4) + '\001' + "\n";

          writer.write(temp);
          writer.flush();
          GetLine(":" + nick + "! " + temp);

        } catch (IOException e) {
          e.printStackTrace();
        } catch (NullPointerException npe) {
          npe.printStackTrace();
        }
        if (ChannelViewHandler != null)
          Message.obtain(ChannelViewHandler,
              ServiceIRCService.MSG_UPDATECHAN, chan)
              .sendToTarget();
        return;
      }

      if (what.equals("/close")) // special case...
      {

        if (channels.get(chan).IS_PM) {
          if (ChannelViewHandler != null) {
            Message.obtain(ChannelViewHandler,
                ServiceIRCService.MSG_CHANGEWINDOW, lastwindow)
                .sendToTarget();
            lastwindow = "~status";

          }

          channels.remove(chan);

        } else if (channels.get(chan).IS_STATUS) {
          // do nothing
        } else {
          // send part
          try {
            String temp = "PART " + chan + " :User closed window\n";
            writer.write(temp);
            writer.flush();
            if (ChannelViewHandler != null) {
              
              Message.obtain(ChannelViewHandler,
                  ServiceIRCService.MSG_CHANGEWINDOW, lastwindow)
                  .sendToTarget();

              lastwindow = "~status";

            }
            channels.remove(chan);

          } catch (IOException e) {
            e.printStackTrace();
          } catch (NullPointerException npe) {
            npe.printStackTrace();
          }
        }

        return;
      }
      if (what.startsWith("/msg ")) // special case...
      {
        try {
          String blah = what.substring(5);
          String towho = blah.substring(0, blah.indexOf(" ")).trim();
          String args = blah.substring(blah.indexOf(" ")).trim();

          String temp = "PRIVMSG " + towho + " :" + args + "\n";

          writer.write(temp);
          writer.flush();
          GetLine(":" + nick + "! " + temp);

        } catch (IOException e) {
          e.printStackTrace();
        } catch (NullPointerException npe) {
          npe.printStackTrace();
        }
        if (ChannelViewHandler != null)
          Message.obtain(ChannelViewHandler,
              ServiceIRCService.MSG_UPDATECHAN, chan)
              .sendToTarget();
        return;
      }

      try {
        String temp = what.substring(1) + "\n";
        writer.write(temp);
        writer.flush();
      } catch (IOException e) {
        e.printStackTrace();
      } catch (NullPointerException npe) {
        npe.printStackTrace();
      }
      return;

    }

    if ((chan == null) || (channels.get(chan).IS_STATUS)) {
      // error about not being on a channel here
      return;
    }
    
    

    // PRIVMSG <target> :<message>
    try {
      String temp = "PRIVMSG " + chan + " :" + what + "\n";
      GetLine(":" + nick + "! " + temp);
      writer.write(temp);
      writer.flush();
      if (ChannelViewHandler != null)
        Message.obtain(ChannelViewHandler,
            ServiceIRCService.MSG_UPDATECHAN, chan).sendToTarget();

    } catch (IOException e) {
      e.printStackTrace();
    } catch (NullPointerException npe) {
      npe.printStackTrace();
    }
  }

  @Override
  public void onCreate() {
    mNM = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);

    // This is who should be launched if the user selects our persistent
    // notification.
    context = this;
    Intent intent = new Intent();
    intent.setClass(this, ActivityAndroidChatMain.class);

    if (intent.hasExtra("server")) server = intent.getExtras().getString("server");
    if (intent.hasExtra("nick")) nick = intent.getExtras().getString("nick");
     
    SharedPreferences settings = ServiceIRCService.context.getSharedPreferences("androidChatPrefs", Context.MODE_WORLD_READABLE);
    nick = settings.getString("irc_nickname_key", "AndroidChat");
    
    channels = new HashMap<String, ClassChannelContainer>();
    channel_list = new HashMap<String, ClassChannelDescriptor>();
    temp_user_locs = new HashMap<String, Location>();

    is_first_list = true;

    ClassChannelContainer debug = new ClassChannelContainer();
    debug.channame = "Status/Debug Window";
    debug.addLine("AndroidChat v" + AC_VERSION + " started.");
    debug.IS_STATUS = true;
    channels.put("~status", debug);


    
    if (ChannelViewHandler != null) {
      Message.obtain(ChannelViewHandler,
          ServiceIRCService.MSG_CHANGEWINDOW, "~status")
          .sendToTarget();
      
    }

    // Display a notification about us starting. We use both a transient
    // notification and a persistent notification in the status bar.
    /*mNM.notify(R.string.irc_started, new Notification(context,
        R.drawable.mini_icon, getText(R.string.irc_started), System
            .currentTimeMillis(), "AndroidChat - Notification",
        getText(R.string.irc_started), intent, R.drawable.mini_icon,
        "Android Chat", intent));*/

    connection = new Thread(new ThreadConnThread(server, nick, socket));
    connection.start();

    if(getSharedPreferences("androidChatPrefs", 0).getBoolean("sendLoc", true))
    {
      updates = new Thread(new ThreadUpdateLocThread(context));
      updates.start();
    }
    /*mNM.notify(R.string.irc_started, new Notification(context,
        R.drawable.mini_icon, getText(R.string.irc_connected), System
            .currentTimeMillis(), "AndroidChat - Notification",
        getText(R.string.irc_connected), null, R.drawable.mini_icon,
        "Android Chat", null));*/

  }
  
  public void disconnect() {
    this.stopSelf();
  }

  @Override
  public void onDestroy() {
    // Cancel the persistent notification.
    QuitServer();
    state = 0;
    if (ChannelViewHandler != null) {
      channels.get("~status").addLine("*** Disconnected");
      Message.obtain(ChannelViewHandler,
          ServiceIRCService.MSG_CHANGEWINDOW, "~status")
          .sendToTarget();
      
    }

    // Tell the user we stopped.
    /*mNM.notify(R.string.irc_started, new Notification(context,
        R.drawable.mini_icon, getText(R.string.irc_stopped), System
            .currentTimeMillis(), "AndroidChat - Notification",
        getText(R.string.irc_stopped), null, R.drawable.mini_icon,
        "Android Chat", null));*/
    
    //mNM.cancel(R.string.irc_started);
    
  }

  public IBinder onBind(Intent intent) {
    return getBinder();

  }

  public IBinder getBinder() {
    return mBinder;
  }

  // This is the object that receives interactions from clients. See
  // RemoteService for a more complete example.
  private final IBinder mBinder = new Binder() {
    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply,
        int flags) {
      try {
      return super.onTransact(code, data, reply, flags);
      } catch (Exception e) {
        return false;
      }
    }
  };

  public static NotificationManager mNM;
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.