/paw/src/com/google/marvin/paw/WidgetService.java

http://eyes-free.googlecode.com/ · Java · 211 lines · 165 code · 44 blank · 2 comment · 20 complexity · d60967c714f794517ce53419611e07af MD5 · raw file

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