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