2 * Copyright (C) 2010 Felix Bechstein
4 * This file is part of WebSMS.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free Software
8 * Foundation; either version 3 of the License, or (at your option) any later
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * You should have received a copy of the GNU General Public License along with
17 * this program; If not, see <http://www.gnu.org/licenses/>.
19 package de
.ub0r
.android
.andGMXsms
;
21 import java
.util
.ArrayList
;
23 import android
.app
.Notification
;
24 import android
.app
.NotificationManager
;
25 import android
.app
.PendingIntent
;
26 import android
.app
.Service
;
27 import android
.content
.Context
;
28 import android
.content
.Intent
;
29 import android
.content
.SharedPreferences
;
30 import android
.net
.Uri
;
31 import android
.os
.Bundle
;
32 import android
.os
.IBinder
;
33 import android
.preference
.PreferenceManager
;
34 import android
.util
.Log
;
35 import de
.ub0r
.android
.websms
.connector
.common
.HelperAPI5Service
;
38 * IOService handles all IO as a service. Call it with RPC!
42 public class IOService
extends Service
{
43 /** Tag for output. */
44 private static final String TAG
= "WebSMS.IO";
46 /** Intent's action for sending a message. */
47 static final String INTENT_ACTION
= "de.ub0r.andGMXsms.send";
48 /** Intent's extra for params. */
49 static final String INTENT_PARAMS
= "prams";
50 /** Intent's extra for connector. */
51 static final String INTENT_CONNECTOR
= "connector";
53 /** Ref to single instance. */
54 private static IOService me
= null;
56 /** Number of jobs running. */
57 private static int currentIOOps
= 0;
59 /** Notification ID of this Service. */
60 private static final int NOTIFICATION_PENDING
= 0;
62 /** A list of notifications to display on destroy. */
63 private static ArrayList
<Notification
> notifications
= new ArrayList
<Notification
>();
65 /** Next notification ID. */
66 private static int nextNotificationID
= 1;
68 /** Wrapper for API5 commands. */
69 private HelperAPI5Service helperAPI5s
= null;
75 public final IBinder
onBind(final Intent intent
) {
76 Log
.d(TAG
, "onBind()");
84 public final void onCreate() {
86 Log
.d(TAG
, "onCreate()");
90 this.helperAPI5s
= new HelperAPI5Service();
91 if (!this.helperAPI5s
.isAvailable()) {
92 this.helperAPI5s
= null;
94 } catch (VerifyError e
) {
95 this.helperAPI5s
= null;
96 Log
.d(TAG
, "no api5 running", e
);
104 public final void onStart(final Intent intent
, final int startId
) {
105 if (intent
!= null) {
106 final String a
= intent
.getAction();
107 if (a
!= null && a
.equals(INTENT_ACTION
)) {
108 final Bundle b
= intent
.getExtras();
109 final String
[] params
= b
.getStringArray(INTENT_PARAMS
);
110 // FIXME: final ConnectorSpecs connector =
111 // Connector.getConnectorSpecs(
112 // this, b.getString(INTENT_CONNECTOR));
113 // Connector.send(IOService.this, connector, params);
122 public final int onStartCommand(final Intent intent
, final int flags
,
124 this.onStart(intent
, startId
);
125 return START_NOT_STICKY
;
129 * Display Notification for failed message.
134 private void displayFailedNotification(final Notification n
) {
135 n
.flags
|= Notification
.FLAG_SHOW_LIGHTS
;
136 n
.ledARGB
= 0xffff0000;
140 final SharedPreferences p
= PreferenceManager
141 .getDefaultSharedPreferences(this);
142 boolean vibrateOnFail
= p
.getBoolean(WebSMS
.PREFS_FAIL_VIBRATE
, true);
143 final String s
= p
.getString(WebSMS
.PREFS_FAIL_SOUND
, null);
145 if (s
== null || s
.length() <= 0) {
148 soundOnFail
= Uri
.parse(s
);
152 n
.flags
|= Notification
.DEFAULT_VIBRATE
;
154 n
.sound
= soundOnFail
;
156 NotificationManager mNotificationMgr
= (NotificationManager
) this
157 .getSystemService(Context
.NOTIFICATION_SERVICE
);
158 mNotificationMgr
.notify(getNotificationID(), n
);
165 public final void onDestroy() {
167 Log
.d(TAG
, "onDestroy()");
168 Log
.d(TAG
, "currentIOOps=" + currentIOOps
);
169 final int s
= IOService
.notifications
.size();
170 for (int i
= 0; i
< s
; i
++) {
171 this.displayFailedNotification(IOService
.notifications
.get(i
));
173 this.displayNotification(0);
177 * Register a IO task.
180 * Notification for pending message
182 public static final synchronized void register(final Notification n
) {
183 Log
.d(TAG
, "register(" + n
+ ")");
184 Log
.d(TAG
, "currentIOOps=" + currentIOOps
);
185 notifications
.add(n
);
187 me
.displayNotification(currentIOOps
);
188 Log
.d(TAG
, "currentIOOps=" + currentIOOps
);
192 * Unregister a IO task.
195 * Notification for pending message
199 public static final synchronized void unregister(final Notification n
,
200 final boolean failed
) {
201 Log
.d(TAG
, "unregister(" + n
+ ", " + failed
+ ")");
202 Log
.d(TAG
, "currentIOOps=" + currentIOOps
);
204 me
.displayFailedNotification(n
);
206 notifications
.remove(n
);
208 me
.displayNotification(currentIOOps
);
209 if (currentIOOps
<= 0) {
212 Log
.d(TAG
, "currentIOOps=" + currentIOOps
);
216 * Display a notification for pending send.
219 * number of pending messages?
221 private void displayNotification(final int count
) {
222 Log
.d(TAG
, "displayNotification(" + count
+ ")");
223 NotificationManager mNotificationMgr
= (NotificationManager
) this
224 .getSystemService(Context
.NOTIFICATION_SERVICE
);
227 if (this.helperAPI5s
== null) {
228 this.setForeground(false);
230 this.helperAPI5s
.stopForeground(this, true);
232 mNotificationMgr
.cancel(NOTIFICATION_PENDING
);
234 // set foreground, don't let kill while IO
235 final Notification notification
= new Notification(
236 R
.drawable
.stat_notify_sms_pending
, this
237 .getString(R
.string
.notify_sending
), System
238 .currentTimeMillis());
239 final PendingIntent contentIntent
= PendingIntent
.getActivity(this,
240 0, new Intent(this, WebSMS
.class), 0);
241 notification
.setLatestEventInfo(this, this
242 .getString(R
.string
.notify_sending
), "", contentIntent
);
243 notification
.defaults
|= Notification
.FLAG_NO_CLEAR
;
244 mNotificationMgr
.notify(NOTIFICATION_PENDING
, notification
);
245 if (this.helperAPI5s
== null) {
246 this.setForeground(true);
248 this.helperAPI5s
.startForeground(this, NOTIFICATION_PENDING
,
252 Log
.d(TAG
, "displayNotification(" + count
+ ") return");
256 * Get a fresh and unique ID for a new notification.
258 * @return return the ID
260 private static synchronized int getNotificationID() {
261 ++nextNotificationID
;
262 return nextNotificationID
;