]> Pileus Git - ~andy/spades/blob - src/org/pileus/spades/Task.java
Fix bug were we can no longer control Task
[~andy/spades] / src / org / pileus / spades / 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         private void notify(String text, int icon)
55         {
56                 // Notify Main
57                 this.command(NOTIFY, text);
58
59                 // Notification bar
60                 Notification  note   = new Notification(icon, null, 0);
61                 Intent        intent = new Intent(this, Main.class);
62                 PendingIntent pend   = PendingIntent.getActivity(this, 0, intent, 0);
63
64                 note.setLatestEventInfo(this, "Spades!", text, pend);
65                 this.startForeground(1, note);
66         }
67
68         private void handle(int cmd, Messenger mgr)
69         {
70                 // Validate messenger
71                 if (cmd != REGISTER && mgr != null && mgr != this.messenger) {
72                         Os.debug("Task: handle - invalid messenger");
73                 }
74
75                 // Setup communication with Main
76                 if (cmd == REGISTER) {
77                         Os.debug("Task: handle - register");
78                         this.messenger = mgr;
79                         this.command(REGISTER, this);
80                 }
81
82                 // Create client thread
83                 if (cmd == CONNECT && this.thread == null) {
84                         Os.debug("Task: handle - connect");
85                         this.thread = new Thread(this);
86                         this.thread.start();
87                 }
88
89                 // Stop client thread
90                 if (cmd == DISCONNECT && this.thread != null) {
91                         Os.debug("Task: handle - register");
92                         try {
93                                 this.client.abort();
94                                 this.thread.join();
95                         } catch (Exception e) {
96                                 Os.debug("Task: error stopping service", e);
97                         }
98                 }
99         }
100
101         /* Public methods */
102         public Message send(String txt)
103         {
104                 if (this.client == null)
105                         return null;
106                 Message msg = this.client.send(txt);
107                 if (msg != null)
108                         this.command(MESSAGE, msg);
109                 return msg;
110         }
111
112         public List<Object> getLog()
113         {
114                 this.lock.lock();
115                 LinkedList<Object> out = new LinkedList<Object>(this.log);
116                 this.lock.unlock();
117                 return out;
118         }
119
120         public boolean isRunning()
121         {
122                 return this.thread != null;
123         }
124
125         /* Runnable methods */
126         @Override
127         public void run()
128         {
129                 Os.debug("Task: thread run");
130
131                 // Setup notification bar
132                 this.notify("Connecting..", android.R.drawable.presence_invisible);
133
134                 // Grab preferences
135                 String  server   = this.prefs.getString ("pref_server",   this.client.server);
136                 String  port     = this.prefs.getString ("pref_port",     this.client.port + "");
137                 String  nickname = this.prefs.getString ("pref_nickname", this.client.nickname);
138                 String  channel  = this.prefs.getString ("pref_channel",  this.client.channel);
139                 boolean usesasl  = this.prefs.getBoolean("pref_usesasl",  this.client.usesasl);
140                 String  authname = this.prefs.getString ("pref_authname", this.client.authname);
141                 String  password = this.prefs.getString ("pref_password", this.client.password);
142
143                 // Update client settings
144                 this.client.setServer(server, Integer.parseInt(port));
145                 this.client.setUser(nickname, channel);
146                 this.client.setAuth(usesasl, authname, password);
147
148                 // Start connecting
149                 if (!this.client.connect()) {
150                         this.command(DISCONNECT, null);
151                         this.notify("Unable to connect", android.R.drawable.presence_offline);
152                         this.thread = null;
153                         return;
154                 }
155
156                 // Wait for login
157                 while (this.client.state == Client.State.SETUP) {
158                         Message msg = this.client.recv();
159                         if (msg == null)
160                                 break;
161                         this.command(MESSAGE, msg);
162                 }
163
164                 // Notify connection status
165                 if (this.client.state == Client.State.READY) {
166                         this.command(CONNECT, null);
167                         this.notify("Connected", android.R.drawable.presence_online);
168                 } else {
169                         this.command(DISCONNECT, null);
170                         this.notify("Connetion aborted", android.R.drawable.presence_offline);
171                 }
172
173                 // Process messages
174                 while (this.client.state == Client.State.READY) {
175                         Message msg = this.client.recv();
176                         if (msg == null)
177                                 break;
178                         this.command(MESSAGE, msg);
179                 }
180
181                 // Notify disconnect disconnected
182                 this.notify("Disconnected", android.R.drawable.presence_offline);
183                 this.command(DISCONNECT, null);
184
185                 // Shutdown the client
186                 this.client.abort();
187                 this.thread = null;
188
189                 Os.debug("Task: thread exit");
190         }
191
192         /* Service Methods */
193         @Override
194         public void onCreate()
195         {
196                 Os.debug("Task: onCreate");
197                 super.onCreate();
198
199                 this.log    = new LinkedList<Object>();
200                 this.lock   = new ReentrantLock();
201                 this.client = new Client();
202                 this.prefs  = PreferenceManager.getDefaultSharedPreferences(this);
203         }
204
205         @Override
206         public void onDestroy()
207         {
208                 Os.debug("Task: onDestroy");
209                 this.handle(DISCONNECT, null);
210         }
211
212         @Override
213         public void onStart(Intent intent, int startId)
214         {
215                 Os.debug("Task: onStart");
216                 super.onStart(intent, startId);
217                 int       cmd = intent.getExtras().getInt("Command");
218                 Messenger mgr = (Messenger)intent.getExtras().get("Messenger");
219                 this.handle(cmd, mgr);
220         }
221
222         @Override
223         public IBinder onBind(Intent intent)
224         {
225                 Os.debug("Task: onBind");
226                 return null;
227         }
228 }