/paw/src/com/google/marvin/paw/WidgetService.java
Java | 211 lines | 165 code | 44 blank | 2 comment | 20 complexity | d60967c714f794517ce53419611e07af MD5 | raw file
1package com.google.marvin.paw; 2 3import java.util.ArrayList; 4import java.util.Calendar; 5 6import android.app.Service; 7import android.content.Context; 8import android.content.Intent; 9import android.hardware.Sensor; 10import android.hardware.SensorEvent; 11import android.hardware.SensorEventListener; 12import android.hardware.SensorListener; 13import android.hardware.SensorManager; 14import android.media.AudioManager; 15import android.net.Uri; 16import android.os.Handler; 17import android.os.IBinder; 18import android.os.RemoteException; 19import android.os.Vibrator; 20import android.util.Log; 21import android.widget.Toast; 22 23public class WidgetService extends Service { 24 private static final int TIMEOUT_LIMIT = 300; 25 private static final long DOUBLE_TAP_THRESHOLD = 1500; 26 27 private WidgetService self; 28 29 private SensorManager accelerometer; 30 31 private AudioManager audioManager; 32 33 private boolean needReset = true; 34 35 private boolean isTalking = false; 36 37 private boolean isDizzy = false; 38 39 String lastState = ""; 40 41 private Vibrator vibe; 42 43 private long[] pattern = {0, 1, 40, 41}; 44 45 long lastTapTime = 0; 46 47 private int idleTimeout = TIMEOUT_LIMIT; 48 49 50 private SensorEventListener accelerometerListener = new SensorEventListener() { 51 private final double deletionForce = 1; 52 53 private final int deletionCount = 2; 54 55 int shakeCount = 0; 56 57 boolean lastShakePositive = false; 58 59 private int shakeCountTimeout = 1500; 60 61 boolean isResetting = false; 62 63 public void onAccuracyChanged(Sensor sensor, int accuracy) { 64 // TODO Auto-generated method stub 65 } 66 67 public void onSensorChanged(SensorEvent event) { 68 if ((event.values[0] > deletionForce) && !lastShakePositive) { 69 if (!isResetting) { 70 isResetting = true; 71 (new Thread(new resetShakeCount())).start(); 72 } 73 shakeCount++; 74 lastShakePositive = true; 75 } else if ((event.values[0] < -deletionForce) && lastShakePositive) { 76 if (!isResetting) { 77 isResetting = true; 78 (new Thread(new resetShakeCount())).start(); 79 } 80 shakeCount++; 81 lastShakePositive = false; 82 } 83 if (shakeCount > deletionCount) { 84 shakeCount = 0; 85 isResetting = false; 86 enterDizzyState(); 87 } 88 } 89 90 class resetShakeCount implements Runnable { 91 public void run() { 92 try { 93 Thread.sleep(shakeCountTimeout); 94 shakeCount = 0; 95 isResetting = false; 96 } catch (InterruptedException e) { 97 e.printStackTrace(); 98 } 99 } 100 } 101 102 }; 103 104 105 public void onStart(Intent intent, int startId) { 106 super.onStart(intent, startId); 107 this.setForeground(true); 108 109 if (needReset) { 110 self = this; 111 112 vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); 113 accelerometer = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 114 115 accelerometer.registerListener(accelerometerListener, accelerometer 116 .getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL, 117 new Handler()); 118 119 needReset = false; 120 121 isTalking = false; 122 isDizzy = false; 123 124 audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 125 126 idleTimeout = TIMEOUT_LIMIT; 127 128 Intent updateAnimIntent = new Intent("com.google.marvin.paw.idle"); 129 sendBroadcast(updateAnimIntent); 130 131 (new Thread(new animationUpdater())).start(); 132 } else { 133 Calendar cal = Calendar.getInstance(); 134 if ((cal.getTimeInMillis() - lastTapTime) < DOUBLE_TAP_THRESHOLD) { 135 vibe.vibrate(pattern, -1); 136 Intent recoIntent = new Intent("com.google.marvin.paw.doReco"); 137 recoIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 138 startActivity(recoIntent); 139 } 140 lastTapTime = cal.getTimeInMillis(); 141 } 142 } 143 144 @Override 145 public IBinder onBind(Intent arg0) { 146 // Not binding to the service 147 return null; 148 } 149 150 public void enterDizzyState() { 151 if (!isDizzy) { 152 (new Thread(new undizzy())).start(); 153 } 154 isDizzy = true; 155 } 156 157 class undizzy implements Runnable { 158 public void run() { 159 try { 160 Thread.sleep(6000); 161 isDizzy = false; 162 } catch (InterruptedException e) { 163 e.printStackTrace(); 164 } 165 } 166 } 167 168 public void updateAnimationState() { 169 String currentState = ""; 170 if (isTalking) { 171 Log.e("paw", "I'm talking!"); 172 idleTimeout = TIMEOUT_LIMIT; 173 } else if (audioManager.isMusicActive()) { 174 currentState = "com.google.marvin.paw.dance"; 175 idleTimeout = TIMEOUT_LIMIT; 176 } else if (isDizzy) { 177 currentState = "com.google.marvin.paw.dizzy"; 178 idleTimeout = TIMEOUT_LIMIT; 179 } else { 180 currentState = "com.google.marvin.paw.idle"; 181 idleTimeout = idleTimeout - 1; 182 } 183 if (!lastState.equals(currentState)) { 184 Intent updateAnimIntent = new Intent(currentState); 185 sendBroadcast(updateAnimIntent); 186 lastState = currentState; 187 } 188 if (idleTimeout < 1) { 189 needReset = true; 190 Intent sleepIntent = new Intent("com.google.marvin.paw.sleep"); 191 sendBroadcast(sleepIntent); 192 this.stopSelf(); 193 return; 194 } 195 (new Thread(new animationUpdater())).start(); 196 } 197 198 class animationUpdater implements Runnable { 199 public void run() { 200 try { 201 Thread.sleep(1000); 202 updateAnimationState(); 203 } catch (InterruptedException e) { 204 e.printStackTrace(); 205 } 206 } 207 } 208 209 210 211}