1
0
Fork 0
forked from len0rd/rockbox
foxbox/android/src/org/rockbox/Helper/RunForegroundManager.java
Thomas Martitz d6ce7fe3d4 Android: Fix some race conditions and crashes on startup.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29341 a1c6a512-1295-4272-9138-f99709370657
2011-02-19 16:42:44 +00:00

181 lines
6.1 KiB
Java

package org.rockbox.Helper;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.rockbox.R;
import org.rockbox.RockboxActivity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.widget.RemoteViews;
public class RunForegroundManager
{
/* all below is heavily based on the examples found on
* http://developer.android.com/reference/android/app/Service.html#setForeground(boolean)
*/
private Notification mNotification;
private NotificationManager mNM;
private IRunForeground api;
private Service mCurrentService;
public RunForegroundManager(Service service)
{
mCurrentService = service;
mNM = (NotificationManager)
service.getSystemService(Service.NOTIFICATION_SERVICE);
RemoteViews views = new RemoteViews(service.getPackageName(), R.layout.statusbar);
/* create Intent for clicking on the expanded notifcation area */
Intent intent = new Intent(service, RockboxActivity.class);
intent = intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mNotification = new Notification();
mNotification.tickerText = service.getString(R.string.notification);
mNotification.icon = R.drawable.notification;
mNotification.contentView = views;
mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
mNotification.contentIntent = PendingIntent.getActivity(service, 0, intent, 0);
try {
api = new newForegroundApi(R.string.notification, mNotification);
} catch (NoSuchMethodException e) {
/* Fall back on the old API */
api = new oldForegroundApi();
}
}
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String)text);
}
private void LOG(CharSequence text, Throwable tr)
{
Log.d("Rockbox", (String)text, tr);
}
public void startForeground()
{
/*
* Send the notification.
* We use a layout id because it is a unique number.
* We use it later to cancel.
*/
mNM.notify(R.string.notification, mNotification);
/*
* this call makes the service run as foreground, which
* provides enough cpu time to do music decoding in the
* background
*/
api.startForeground();
}
public void stopForeground()
{
/* Note to cancel BEFORE changing the
* foreground state, since we could be killed at that point.
*/
mNM.cancel(R.string.notification);
api.stopForeground();
}
public void updateNotification(String title, String artist, String album)
{
RemoteViews views = mNotification.contentView;
views.setTextViewText(R.id.title, title);
views.setTextViewText(R.id.content, artist+"\n"+album);
if (artist.equals(""))
mNotification.tickerText = title;
else
mNotification.tickerText = title+" - "+artist;
mNM.notify(R.string.notification, mNotification);
Intent widgetUpdate = new Intent("org.rockbox.TrackUpdateInfo");
widgetUpdate.putExtra("title", title);
widgetUpdate.putExtra("artist", artist);
widgetUpdate.putExtra("album", album);
mCurrentService.sendBroadcast(widgetUpdate);
}
public void finishNotification()
{
Log.d("Rockbox", "TrackFinish");
Intent widgetUpdate = new Intent("org.rockbox.TrackFinish");
mCurrentService.sendBroadcast(widgetUpdate);
}
private interface IRunForeground
{
void startForeground();
void stopForeground();
}
private class newForegroundApi implements IRunForeground
{
Class<?>[] mStartForegroundSignature =
new Class[] { int.class, Notification.class };
Class<?>[] mStopForegroundSignature =
new Class[] { boolean.class };
private Method mStartForeground;
private Method mStopForeground;
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];
newForegroundApi(int id, Notification notification)
throws SecurityException, NoSuchMethodException
{
/*
* Get the new API through reflection
*/
mStartForeground = Service.class.getMethod("startForeground",
mStartForegroundSignature);
mStopForeground = Service.class.getMethod("stopForeground",
mStopForegroundSignature);
mStartForegroundArgs[0] = id;
mStartForegroundArgs[1] = notification;
mStopForegroundArgs[0] = Boolean.TRUE;
}
public void startForeground()
{
try {
mStartForeground.invoke(mCurrentService, mStartForegroundArgs);
} catch (InvocationTargetException e) {
/* Should not happen. */
LOG("Unable to invoke startForeground", e);
} catch (IllegalAccessException e) {
/* Should not happen. */
LOG("Unable to invoke startForeground", e);
}
}
public void stopForeground()
{
try {
mStopForeground.invoke(mCurrentService, mStopForegroundArgs);
} catch (InvocationTargetException e) {
/* Should not happen. */
LOG("Unable to invoke stopForeground", e);
} catch (IllegalAccessException e) {
/* Should not happen. */
LOG("Unable to invoke stopForeground", e);
}
}
}
private class oldForegroundApi implements IRunForeground
{
public void startForeground()
{
mCurrentService.setForeground(false);
}
public void stopForeground()
{
mCurrentService.setForeground(false);
}
}
}