3 import java
.io
.BufferedInputStream
;
4 import java
.io
.BufferedOutputStream
;
6 import java
.io
.FileOutputStream
;
7 import java
.util
.Enumeration
;
8 import java
.util
.zip
.ZipEntry
;
9 import java
.util
.zip
.ZipFile
;
11 import android
.app
.Notification
;
12 import android
.app
.NotificationManager
;
13 import android
.app
.PendingIntent
;
14 import android
.app
.Service
;
15 import android
.content
.Intent
;
16 import android
.os
.Binder
;
17 import android
.os
.IBinder
;
18 import android
.util
.Log
;
20 public class RockboxService
extends Service
22 /* this Service is really a singleton class */
23 public static RockboxFramebuffer fb
= null;
24 private static RockboxService instance
;
25 private Notification notification
;
27 public void onCreate()
29 mNM
= (NotificationManager
)getSystemService(NOTIFICATION_SERVICE
);
34 private void do_start(Intent intent
)
39 private void LOG(CharSequence text
)
41 Log
.d("Rockbox", (String
) text
);
45 public void onStart(Intent intent
, int startId
) {
50 public int onStartCommand(Intent intent
, int flags
, int startId
)
53 /* Display a notification about us starting. We put an icon in the status bar. */
54 create_notification();
58 private void startservice()
60 fb
= new RockboxFramebuffer(this);
61 final int BUFFER
= 2048;
62 /* the following block unzips libmisc.so, which contains the files
63 * we ship, such as themes. It's needed to put it into a .so file
64 * because there's no other way to ship files and have access
65 * to them from native code
69 BufferedOutputStream dest
= null;
70 BufferedInputStream is
= null;
72 File file
= new File("/data/data/org.rockbox/lib/libmisc.so");
73 /* use arbitary file to determine whether extracting is needed */
74 File file2
= new File("/data/data/org.rockbox/app_rockbox/rockbox/codecs/mpa.codec");
75 if (!file2
.exists() || (file
.lastModified() > file2
.lastModified()))
77 ZipFile zipfile
= new ZipFile(file
);
78 Enumeration
<?
extends ZipEntry
> e
= zipfile
.entries();
80 while(e
.hasMoreElements()) {
81 entry
= (ZipEntry
) e
.nextElement();
82 LOG("Extracting: " +entry
);
83 if (entry
.isDirectory())
85 folder
= new File(entry
.getName());
89 } catch (SecurityException ex
){
94 is
= new BufferedInputStream(zipfile
.getInputStream(entry
));
96 byte data
[] = new byte[BUFFER
];
97 folder
= new File(new File(entry
.getName()).getParent());
98 LOG("" + folder
.getAbsolutePath());
101 FileOutputStream fos
= new FileOutputStream(entry
.getName());
102 dest
= new BufferedOutputStream(fos
, BUFFER
);
103 while ((count
= is
.read(data
, 0, BUFFER
)) != -1) {
104 dest
.write(data
, 0, count
);
111 } catch(Exception e
) {
115 System
.loadLibrary("rockbox");
117 Thread rb
= new Thread(new Runnable()
128 private native void main();
130 public IBinder
onBind(Intent intent
) {
131 // TODO Auto-generated method stub
134 private NotificationManager mNM
;
137 * Class for clients to access. Because we know this service always
138 * runs in the same process as its clients, we don't need to deal with
141 public class LocalBinder
extends Binder
{
142 RockboxService
getService() {
143 return RockboxService
.this;
147 /* heavily based on the example found on
148 * http://developer.android.com/reference/android/app/Service.html
151 private void create_notification()
153 // In this sample, we'll use the same text for the ticker and the expanded notification
154 CharSequence text
= getText(R
.string
.notification
);
156 // Set the icon, scrolling text and timestamp
157 notification
= new Notification(R
.drawable
.rb
, text
,
158 System
.currentTimeMillis());
160 // The PendingIntent to launch our activity if the user selects this notification
161 Intent intent
= new Intent(this, RockboxActivity
.class);
162 PendingIntent contentIntent
= PendingIntent
.getActivity(this, 0, intent
, 0);
165 // Set the info for the views that show in the notification panel.
166 notification
.setLatestEventInfo(this, getText(R
.string
.notification
), text
, contentIntent
);
169 public static void startForeground()
171 if (instance
!= null)
173 // Send the notification.
174 // We use a layout id because it is a unique number. We use it later to cancel.
175 instance
.mNM
.notify(R
.string
.notification
, instance
.notification
);
178 * this call makes the service run as foreground, which
179 * provides enough cpu time to do music decoding in the
182 instance
.startForeground(R
.string
.notification
, instance
.notification
);
186 public static void stopForeground()
188 if (instance
.notification
!= null)
190 instance
.stopForeground(true);
191 instance
.mNM
.cancel(R
.string
.notification
);