Android Open Source - cicada Cicada App






From Project

Back to project page cicada.

License

The source code is released under:

Apache License

If you think the Android project cicada listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

// Copyright (C) 2011 Cicada contributors
////from  ww w  .j  av a 2s  .c o  m
// 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 org.cicadasong.cicadalib;

package org.cicadasong.cicadalib;

import org.cicadasong.apollo.ApolloConfig;
import org.cicadasong.apollo.BitmapUtil;

import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

/**
 * Base class for Cicada apps that provides a clean interface for dealing with CicadaService.
 */

public abstract class CicadaApp extends Service {
  
  public enum AppType {
    NONE,
    WIDGET,
    APP,
    WIDGET_AND_APP
  }
  
  public enum WatchButton {
    NO_BUTTON    ((byte) -1),
    TOP_RIGHT    ((byte) 0),
    MIDDLE_RIGHT ((byte) 1),
    BOTTOM_RIGHT ((byte) 2),
    TOP_LEFT     ((byte) 6),
    MIDDLE_LEFT  ((byte) 5),
    BOTTOM_LEFT  ((byte) 3);
    
    private final byte value;
    
    private WatchButton(byte value) {
      this.value = value;
    }
    
    public byte value() {
      return value;
    }
    
    public static WatchButton valueOf(int arg1) {
      for (WatchButton possibleButton : WatchButton.values()) {
        if (possibleButton.value == arg1) {
          return possibleButton;
        }
      }
      return NO_BUTTON;
    }
  }
  
  // Received from Cicada
  public static final int MESSAGETYPE_ACTIVATE = 1;
  public static final int MESSAGETYPE_DEACTIVATE = 2;
  public static final int MESSAGETYPE_BUTTON_EVENT = 3;

  // Sent to Cicada
  public static final int MESSAGETYPE_PUSH_CANVAS = 100;
  public static final int MESSAGETYPE_VIBRATE = 101;
  
  private AppType currentMode = AppType.NONE;
  private Bitmap bitmap;
  private Canvas canvas;
  private boolean isActive = false;
  private int sessionId;
  private Messenger replyMessenger;

  // The messenger for communication with CicadaService.
  final Messenger messenger = new Messenger(new IncomingHandler());

  // This is a no-op here, but I'm pulling it up to this level so that it'll be more visible
  // to people using IDEs.
  @Override
  public void onCreate() {
    super.onCreate();
  }

  @Override
  public void onDestroy() {
    if (isActive) {
      deactivate();
    }
    super.onDestroy();
  }
  
  /**
   * Handler of incoming messages from clients.
   */
  class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
      switch(msg.what){
      case MESSAGETYPE_ACTIVATE:
        if (!isActive) {
          sessionId = msg.arg1;
          activate(AppType.values()[msg.arg2], msg.replyTo);
        }
        break;

      case MESSAGETYPE_DEACTIVATE:
        if (isActive) {
          deactivate();
        }
        break;
        
      case MESSAGETYPE_BUTTON_EVENT:
        onButtonPress(WatchButton.valueOf(msg.arg1));
        break;

      default:
        super.handleMessage(msg);
        break;
      }
    }
  }


  @Override
  public IBinder onBind(Intent intent) {
    return messenger.getBinder();
  }
  
  /**
   * @return the human-readable name of the app (only used for debugging at the moment)
   */
  public String getAppName() {
    return this.getClass().getSimpleName();
  }

  /**
   * Called when this app is activated by CicadaService.  onDraw() will be triggered at the
   * conclusion of this method.
   */
  protected abstract void onResume();
  
  /**
   * Called when this app is deactivated; it should no longer call invalidate() to trigger screen
   * updates past this point.
   */
  protected abstract void onPause();
  
  /**
   * Called when one of the watch buttons is pressed while this app is active.
   * 
   * @param button indicates which watch button was pressed.
   */
  protected abstract void onButtonPress(WatchButton button);
  
  /**
   * Called when the app needs to render its screen contents.  This method should not be called
   * directly by the app; if the app author wishes to trigger a screen update, they should call
   * invalidate().
   * 
   * @param canvas the canvas on which the display contents will be drawn.  Note that the canvas
   *        will be different sizes in widget and app modes, and that the contents of the canvas
   *        will be flattened to monochrome before being pushed to the display.
   */
  protected abstract void onDraw(Canvas canvas);
  
  /**
   * @return Either AppType.APP if this app currently has the entire watch screen,
   *         or AppType.Widget if this app only has 1/3 of the watch screen.
   */
  protected AppType getCurrentMode() {
    return currentMode;
  }
  
  
  protected boolean isWidget() {
    return getCurrentMode() == AppType.WIDGET;
  }
  
  protected boolean isApp() {
    return getCurrentMode() == AppType.APP;
  }
  
  private Canvas getCanvas() {
    if (canvas == null) {
      int height = ApolloConfig.DISPLAY_HEIGHT;
      if (isWidget()) {
        height /= 3;
      }
      bitmap = Bitmap.createBitmap(ApolloConfig.DISPLAY_WIDTH, height, Bitmap.Config.RGB_565);
      canvas = new Canvas(bitmap);
    }
    
    return canvas;
  }
  
  /**
   * Push the canvas to the device.  Before calling this, get the canvas via getCanvas() and
   * draw on it using Android graphics functions.  Note that the canvas contents will be flattened
   * to monochrome for display on the device.  This method should only be called when the app
   * is active.
   */
  private void pushCanvas() {
    if (!isActive || canvas == null || replyMessenger == null) {
      return;
    }
    
    Bundle parameters = new Bundle();
    parameters.putByteArray(CicadaIntents.EXTRA_BUFFER, BitmapUtil.bitmapToBuffer(bitmap));
    parameters.putString(CicadaIntents.EXTRA_APP_NAME, getAppName());
    parameters.putInt(CicadaIntents.EXTRA_SESSION_ID, sessionId);
    
    Message message = Message.obtain(null, MESSAGETYPE_PUSH_CANVAS);
    message.setData(parameters);
    try {
      replyMessenger.send(message);
    } catch (RemoteException e) {
      Log.e(this.getClass().getSimpleName(), "Couldn't send screen update message to Cicada");
    }
  }
  
  /**
   * Called by the Cicada app to request a screen update.  The app's onDraw will subsequently
   * be called with an appropriately-sized canvas, and the result pushed to the device.
   */
  protected void invalidate() {
    if (!isActive) {
      throw new RuntimeException("CicadaApp.invalidate() called when the app wasn't active!");
    }
    
    // Make sure the canvas has been initialized to the appropriate size for the app mode
    getCanvas();
    
    // Ensure that the canvas is white, since the apps will tend to start drawing in black
    canvas.drawColor(Color.WHITE);
    
    onDraw(canvas);
    pushCanvas();
  }
  
  /**
   * Called by the Cicada app to trigger a vibration.  Should only be called when the app is active.
   * 
   * @param onMillis the duration in milliseconds of each pulse
   * @param offMillis the duration in milliseconds of the pauses between pulses
   * @param numPulses the number of pulses
   */
  protected void vibrate(int onMillis, int offMillis, int numPulses) {
    if (!isActive) {
      throw new RuntimeException("CicadaApp.vibrate() called when the app wasn't active!");
    }

    Bundle parameters = new Bundle();
    parameters.putInt(CicadaIntents.EXTRA_VIBRATE_ON_MSEC, onMillis);
    parameters.putInt(CicadaIntents.EXTRA_VIBRATE_OFF_MSEC, offMillis);
    parameters.putInt(CicadaIntents.EXTRA_VIBRATE_NUM_CYCLES, numPulses);
    parameters.putString(CicadaIntents.EXTRA_APP_NAME, getAppName());
    parameters.putInt(CicadaIntents.EXTRA_SESSION_ID, sessionId);
    
    Message message = Message.obtain(null, MESSAGETYPE_VIBRATE);
    message.setData(parameters);
    try {
      replyMessenger.send(message);
    } catch (RemoteException e) {
      Log.e(this.getClass().getSimpleName(), "Couldn't send vibration request message to Cicada");
    }
  }
  
  protected boolean isActive() {
    return isActive;
  }
  
  private void activate(AppType mode, Messenger messenger) {
    isActive = true;
    replyMessenger = messenger;
    if (currentMode != mode) {
      // Make sure the canvas is reset to the correct size when changing mode.
      canvas = null;
    }
    currentMode = mode;
    onResume();
    invalidate();
  }
  
  private void deactivate() {
    isActive = false;
    replyMessenger = null;
    
    canvas = null;
    bitmap = null;
    
    onPause();
  }
}




Java Source Code List

com.hydraproductions.cicada.StopWatch.java
org.cicadasong.apollo.ApolloConfig.java
org.cicadasong.apollo.ApolloIntents.java
org.cicadasong.apollo.BitmapUtil.java
org.cicadasong.apollo.SimulatedDisplayView.java
org.cicadasong.cicada.AppDatabase.java
org.cicadasong.cicada.AppDescription.java
org.cicadasong.cicada.AppList.java
org.cicadasong.cicada.AppScanner.java
org.cicadasong.cicada.CicadaService.java
org.cicadasong.cicada.CicadaSettingsActivity.java
org.cicadasong.cicada.Cicada.java
org.cicadasong.cicada.DeviceService.java
org.cicadasong.cicada.HotkeySetupActivity.java
org.cicadasong.cicada.HotkeySetupEntry.java
org.cicadasong.cicada.MetaWatchConnection.java
org.cicadasong.cicada.NotificationRenderer.java
org.cicadasong.cicada.PackageMonitor.java
org.cicadasong.cicada.PackageUtil.java
org.cicadasong.cicada.PrefUtil.java
org.cicadasong.cicada.WidgetScreen.java
org.cicadasong.cicada.WidgetSetup.java
org.cicadasong.cicadalib.CicadaApp.java
org.cicadasong.cicadalib.CicadaIntents.java
org.cicadasong.cicadalib.CicadaNotificationManager.java
org.cicadasong.cicadalib.CicadaNotification.java
org.cicadasong.cicadalib.TextBlock.java
org.cicadasong.samples.bitly.Bitly.java
org.cicadasong.samples.digitalclock.DigitalClock.java
org.cicadasong.samples.hellocicada.HelloCicada.java
org.cicadasong.samples.nextbuses.NextBuses.java
org.cicadasong.samples.notificationdemo.NotificationDemo.java
org.cicadasong.samples.notifications.NotificationAccessibilityService.java
org.cicadasong.samples.notifications.Notifications.java
org.cicadasong.samples.quicktext.QuickTextSetup.java
org.cicadasong.samples.quicktext.QuickText.java
org.cicadasong.samples.smsnotifier.SMSBroadcastReceiver.java
org.cicadasong.samples.tubestatus.Preferences.java
org.cicadasong.samples.tubestatus.TubeStatusSettingsActivity.java
org.cicadasong.samples.tubestatus.TubeStatus.java
org.cicadasong.samples.webimageplayer.Preferences.java
org.cicadasong.samples.webimageplayer.WebImagePlayerSettingsActivity.java
org.cicadasong.samples.webimageplayer.WebImagePlayer.java