/* * Copyright (c) 2013, Psiphon Inc. * All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package ca.psiphon.ploggy; import java.util.List; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.text.Html; import com.squareup.otto.Subscribe; /** * Android Service for hosting long-running Engine instance. */ public class PloggyService extends Service { private static final String LOG_TAG = "Service"; private Engine mEngine; private Notification mNotification = null; public PloggyService() { } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { try { Events.register(this); mEngine = new Engine(this); mEngine.start(); } catch (Utils.ApplicationError e) { Log.addEntry(LOG_TAG, "failed to start Engine"); stopSelf(); return; } doForeground(); } @Override public void onDestroy() { Events.unregister(this); if (mEngine != null) { mEngine.stop(); mEngine = null; } } private void doForeground() { updateNotification(null); startForeground(R.string.foregroundServiceNotificationId, mNotification); } private void updateNotification(List<Data.AnnotatedMessage> newMessages) { // Max, as per documentation: http://developer.android.com/reference/android/app/Notification.InboxStyle.html final int MAX_LINES = 5; // Invoke main Activity when notification is clicked Intent intent = new Intent(this, ActivityMain.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); int iconResourceId; String contentTitle; if (newMessages != null && newMessages.size() > 0) { intent.setAction(ActivityMain.ACTION_DISPLAY_MESSAGES); iconResourceId = R.drawable.ic_notification_with_new_messages; contentTitle = getResources().getQuantityString( R.plurals.foreground_service_notification_content_title_with_new_messages, newMessages.size(), newMessages.size()); } else { intent.setAction("android.intent.action.MAIN"); iconResourceId = R.drawable.ic_notification_without_new_messages; contentTitle = getString(R.string.foreground_service_notification_content_title_without_new_messages); } PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); Notification.Builder notificationBuilder = new Notification.Builder(this) .setContentIntent(pendingIntent) .setContentTitle(contentTitle) .setSmallIcon(iconResourceId); Notification notification; if (newMessages != null && newMessages.size() > 0) { // Use default (system) sound, lights, and vibrate notificationBuilder.setDefaults(Notification.DEFAULT_ALL); // Build email-style big view with summary of new messages Notification.InboxStyle inboxStyleBuilder = new Notification.InboxStyle(notificationBuilder); for (int i = 0; i < MAX_LINES && i < newMessages.size(); i++) { inboxStyleBuilder.addLine( Html.fromHtml( getString( R.string.foreground_service_notification_inbox_line, newMessages.get(i).mPublicIdentity.mNickname, newMessages.get(i).mMessage.mContent))); } if (newMessages.size() > MAX_LINES) { inboxStyleBuilder.setSummaryText( getString( R.string.foreground_service_notification_inbox_summary, newMessages.size() - MAX_LINES)); } notification = inboxStyleBuilder.build(); } else { notification = notificationBuilder.build(); } if (mNotification == null) { mNotification = notification; } else { // TODO: if other notification attributes are added (ie ticker), copy them here mNotification.contentIntent = notification.contentIntent; mNotification.bigContentView = notification.bigContentView; mNotification.contentView = notification.contentView; mNotification.icon = notification.icon; mNotification.largeIcon = notification.largeIcon; mNotification.defaults = notification.defaults; } } @Subscribe public synchronized void onUpdatedNewMessages(Events.UpdatedNewMessages updatedNewMessages) { try { // Update the service notification with new messages updateNotification(Data.getInstance().getNewMessages()); NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager != null) { notificationManager.notify(R.string.foregroundServiceNotificationId, mNotification); } } catch (Utils.ApplicationError e) { Log.addEntry(LOG_TAG, "failed to create new messages notification"); } } }