| /* |
| * Copyright (C) 2015 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| package com.googlecode.android_scripting.activity; |
| |
| import android.app.AlarmManager; |
| import android.app.Notification; |
| import android.app.PendingIntent; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.os.Binder; |
| import android.os.IBinder; |
| |
| import com.google.common.base.Preconditions; |
| import com.googlecode.android_scripting.BaseApplication; |
| import com.googlecode.android_scripting.ForegroundService; |
| import com.googlecode.android_scripting.IntentBuilders; |
| import com.googlecode.android_scripting.NotificationIdFactory; |
| import com.googlecode.android_scripting.R; |
| import com.googlecode.android_scripting.event.Event; |
| import com.googlecode.android_scripting.facade.EventFacade; |
| import com.googlecode.android_scripting.facade.EventFacade.EventObserver; |
| import com.googlecode.android_scripting.facade.FacadeConfiguration; |
| import com.googlecode.android_scripting.facade.FacadeManager; |
| import com.googlecode.android_scripting.trigger.EventGenerationControllingObserver; |
| import com.googlecode.android_scripting.trigger.Trigger; |
| import com.googlecode.android_scripting.trigger.TriggerRepository; |
| import com.googlecode.android_scripting.trigger.TriggerRepository.TriggerRepositoryObserver; |
| |
| /** |
| * The trigger service takes care of installing triggers serialized to the preference storage. |
| * |
| * <p> |
| * The service also installs an alarm that keeps it running, unless the user force-quits the |
| * service. |
| * |
| * <p> |
| * When no triggers are installed the service shuts down silently as to not consume resources |
| * unnecessarily. |
| * |
| * @author Felix Arends (felix.arends@gmail.com) |
| * @author Damon Kohler (damonkohler@gmail.com) |
| */ |
| public class TriggerService extends ForegroundService { |
| private static final int NOTIFICATION_ID = NotificationIdFactory.create(); |
| private static final long PING_MILLIS = 10 * 1000 * 60; |
| |
| private final IBinder mBinder; |
| private TriggerRepository mTriggerRepository; |
| private FacadeManager mFacadeManager; |
| private EventFacade mEventFacade; |
| |
| public class LocalBinder extends Binder { |
| public TriggerService getService() { |
| return TriggerService.this; |
| } |
| } |
| |
| public TriggerService() { |
| super(NOTIFICATION_ID); |
| mBinder = new LocalBinder(); |
| } |
| |
| @Override |
| public IBinder onBind(Intent intent) { |
| return mBinder; |
| } |
| |
| @Override |
| public void onCreate() { |
| super.onCreate(); |
| |
| mFacadeManager = |
| new FacadeManager(FacadeConfiguration.getSdkLevel(), this, null, |
| FacadeConfiguration.getFacadeClasses()); |
| mEventFacade = mFacadeManager.getReceiver(EventFacade.class); |
| |
| mTriggerRepository = ((BaseApplication) getApplication()).getTriggerRepository(); |
| mTriggerRepository.bootstrapObserver(new RepositoryObserver()); |
| mTriggerRepository.bootstrapObserver(new EventGenerationControllingObserver(mFacadeManager)); |
| installAlarm(); |
| } |
| |
| @Override |
| public void onStart(Intent intent, int startId) { |
| if (mTriggerRepository.isEmpty()) { |
| stopSelfResult(startId); |
| return; |
| } |
| } |
| |
| /** Returns the notification to display whenever the service is running. */ |
| @Override |
| protected Notification createNotification() { |
| Intent notificationIntent = new Intent(this, TriggerManager.class); |
| Notification.Builder builder = new Notification.Builder(this); |
| builder.setSmallIcon(R.drawable.sl4a_logo_48) |
| .setTicker("SL4A Trigger Service started.") |
| .setWhen(System.currentTimeMillis()) |
| .setContentTitle("SL4A Trigger Service") |
| .setContentText("Tap to view triggers") |
| .setContentIntent(PendingIntent.getActivity(this, 0, notificationIntent, 0)); |
| Notification notification = builder.build(); |
| notification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; |
| return notification; |
| } |
| |
| private class TriggerEventObserver implements EventObserver { |
| private final Trigger mTrigger; |
| |
| public TriggerEventObserver(Trigger trigger) { |
| mTrigger = trigger; |
| } |
| |
| @Override |
| public void onEventReceived(Event event) { |
| mTrigger.handleEvent(event, TriggerService.this); |
| } |
| } |
| |
| private class RepositoryObserver implements TriggerRepositoryObserver { |
| int mTriggerCount = 0; |
| |
| @Override |
| public void onPut(Trigger trigger) { |
| mTriggerCount++; |
| mEventFacade.addNamedEventObserver(trigger.getEventName(), new TriggerEventObserver(trigger)); |
| } |
| |
| @Override |
| public void onRemove(Trigger trigger) { |
| Preconditions.checkArgument(mTriggerCount > 0); |
| // TODO(damonkohler): Tear down EventObserver associated with trigger. |
| if (--mTriggerCount == 0) { |
| // TODO(damonkohler): Use stopSelfResult() which would require tracking startId. |
| stopSelf(); |
| } |
| } |
| } |
| |
| private void installAlarm() { |
| AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); |
| alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + PING_MILLIS, |
| PING_MILLIS, IntentBuilders.buildTriggerServicePendingIntent(this)); |
| } |
| |
| private void uninstallAlarm() { |
| AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); |
| alarmManager.cancel(IntentBuilders.buildTriggerServicePendingIntent(this)); |
| } |
| |
| @Override |
| public void onDestroy() { |
| super.onDestroy(); |
| uninstallAlarm(); |
| } |
| } |