]> Pileus Git - ~andy/spades/blob - src/Task.java
26e0bd872343b7ce1a09c78755970ff5920d9ca6
[~andy/spades] / src / Task.java
1 package org.pileus.spades;
2
3 import java.util.List;
4 import java.util.LinkedList;
5 import java.util.concurrent.locks.Lock;
6 import java.util.concurrent.locks.ReentrantLock;
7
8 import android.app.Notification;
9 import android.app.PendingIntent;
10 import android.app.Service;
11 import android.content.Context;
12 import android.content.Intent;
13 import android.content.SharedPreferences;
14 import android.os.IBinder;
15 import android.os.Looper;
16 import android.os.Messenger;
17 import android.preference.PreferenceManager;
18
19 public class Task extends Service implements Runnable
20 {
21         /* Commands */
22         public static final int REGISTER   = 0;
23         public static final int MESSAGE    = 1;
24         public static final int CONNECT    = 2;
25         public static final int DISCONNECT = 3;
26         public static final int NOTIFY     = 4;
27
28         /* Private data */
29         private SharedPreferences prefs;
30         private Messenger         messenger;
31         private Thread            thread;
32         private Client            client;
33         private List<Object>      log;
34         private Lock              lock;
35
36         /* Private methods */
37         private void command(int cmd, Object value)
38         {
39                 if (cmd == MESSAGE || cmd == NOTIFY) {
40                         this.lock.lock();
41                         this.log.add(value);
42                         this.lock.unlock();
43                 }
44                 try {
45                         android.os.Message msg = android.os.Message.obtain();
46                         msg.what = cmd;
47                         msg.obj  = value;
48                         this.messenger.send(msg);
49                 } catch (Exception e) {
50                         Os.debug("Task: error sending message", e);
51                 }
52         }
53
54         @SuppressWarnings("deprecation")
55         private void notify(String text, int icon)
56         {
57                 // Notify Main
58                 this.command(NOTIFY, text);
59
60                 // Notification bar
61                 Notification  note   = new Notification(icon, null, 0);
62                 Intent        intent = new Intent(this, Main.class);
63                 PendingIntent pend   = PendingIntent.getActivity(this, 0, intent, 0);
64
65                 note.setLatestEventInfo(this, "Spades!", text, pend);
66                 this.startForeground(1, note);
67         }
68
69         private void handle(int cmd, Messenger mgr)
70         {
71                 // Validate messenger
72                 if (cmd != REGISTER && mgr != null && mgr != this.messenger) {
73                         Os.debug("Task: handle - invalid messenger");
74                 }
75
76                 // Setup communication with Main
77                 if (cmd == REGISTER) {
78                         Os.debug("Task: handle - register");
79                         this.messenger = mgr;
80                         this.command(REGISTER, this);
81                 }
82
83                 // Create client thread
84                 if (cmd == CONNECT && this.thread == null) {
85                         Os.debug("Task: handle - connect");
86                         this.thread = new Thread(this);
87                         this.thread.start();
88                 }
89
90                 // Stop client thread
91                 if (cmd == DISCONNECT && this.thread != null) {
92                         Os.debug("Task: handle - register");
93                         try {
94                                 this.client.abort();
95                                 this.thread.join();
96                         } catch (Exception e) {
97                                 Os.debug("Task: error stopping service", e);
98                         }
99                 }
100         }
101
102         /* Public methods */
103         public Message send(String dst, String txt)
104         {
105                 if (this.client == null)
106                         return null;
107                 Message msg = this.client.send(dst, txt);
108                 if (msg != null)
109                         this.command(MESSAGE, msg);
110                 return msg;
111         }
112
113         public Message send(String txt)
114         {
115                 if (this.client == null)
116                         return null;
117                 Message msg = this.client.send(txt);
118                 if (msg != null)
119                         this.command(MESSAGE, msg);
120                 return msg;
121         }
122
123         public List<Object> getLog()
124         {
125                 this.lock.lock();
126                 LinkedList<Object> out = new LinkedList<Object>(this.log);
127                 this.lock.unlock();
128                 return out;
129         }
130
131         public boolean isRunning()
132         {
133                 return this.thread != null;
134         }
135
136         /* Runnable methods */
137         @Override
138         public void run()
139         {
140                 Os.debug("Task: thread run");
141
142                 // Setup notification bar
143                 this.notify("Connecting..", android.R.drawable.presence_invisible);
144
145                 // Grab preferences
146                 String  server   = this.prefs.getString ("pref_server",   this.client.server);
147                 String  port     = this.prefs.getString ("pref_port",     this.client.port + "");
148                 String  nickname = this.prefs.getString ("pref_nickname", this.client.nickname);
149                 String  channel  = this.prefs.getString ("pref_channel",  this.client.channel);
150                 boolean usesasl  = this.prefs.getBoolean("pref_usesasl",  this.client.usesasl);
151                 String  authname = this.prefs.getString ("pref_authname", this.client.authname);
152                 String  password = this.prefs.getString ("pref_password", this.client.password);
153
154                 // Update client settings
155                 this.client.setServer(server, Integer.parseInt(port));
156                 this.client.setUser(nickname, channel);
157                 this.client.setAuth(usesasl, authname, password);
158
159                 // Start connecting
160                 if (!this.client.connect()) {
161                         this.command(DISCONNECT, null);
162                         this.notify("Unable to connect", android.R.drawable.presence_offline);
163                         this.thread = null;
164                         return;
165                 }
166
167                 // Wait for login
168                 while (this.client.state == Client.State.SETUP) {
169                         Message msg = this.client.recv();
170                         if (msg == null)
171                                 break;
172                         this.command(MESSAGE, msg);
173                 }
174
175                 // Notify connection status
176                 if (this.client.state == Client.State.READY) {
177                         this.command(CONNECT, null);
178                         this.notify("Connected", android.R.drawable.presence_online);
179                 } else {
180                         this.command(DISCONNECT, null);
181                         this.notify("Connetion aborted", android.R.drawable.presence_offline);
182                 }
183
184                 // Process messages
185                 while (this.client.state == Client.State.READY) {
186                         Message msg = this.client.recv();
187                         if (msg == null)
188                                 break;
189                         this.command(MESSAGE, msg);
190                 }
191
192                 // Notify disconnect disconnected
193                 this.notify("Disconnected", android.R.drawable.presence_offline);
194                 this.command(DISCONNECT, null);
195
196                 // Shutdown the client
197                 this.client.abort();
198                 this.thread = null;
199
200                 Os.debug("Task: thread exit");
201         }
202
203         /* Service Methods */
204         @Override
205         public void onCreate()
206         {
207                 Os.debug("Task: onCreate");
208                 super.onCreate();
209
210                 this.log    = new LinkedList<Object>();
211                 this.lock   = new ReentrantLock();
212                 this.client = new Client();
213                 this.prefs  = PreferenceManager.getDefaultSharedPreferences(this);
214         }
215
216         @Override
217         public void onDestroy()
218         {
219                 Os.debug("Task: onDestroy");
220                 this.handle(DISCONNECT, null);
221         }
222
223         @Override
224         @SuppressWarnings("deprecation")
225         public void onStart(Intent intent, int startId)
226         {
227                 Os.debug("Task: onStart");
228                 super.onStart(intent, startId);
229                 int       cmd = intent.getExtras().getInt("Command");
230                 Messenger mgr = (Messenger)intent.getExtras().get("Messenger");
231                 this.handle(cmd, mgr);
232         }
233
234         @Override
235         public IBinder onBind(Intent intent)
236         {
237                 Os.debug("Task: onBind");
238                 return null;
239         }
240 }