/documentation/tutorial/MusicFileBrowser/MusicFileBrowser_Tutorial2/src/com/google/marvin/tutorials/musicFileBrowser2/MusicFileBrowser.java

http://eyes-free.googlecode.com/ · Java · 265 lines · 224 code · 26 blank · 15 comment · 47 complexity · f7d0f08f88dff8411dd110128a567f9b MD5 · raw file

  1. package com.google.marvin.tutorials.musicFileBrowser2;
  2. /**
  3. * Music File Browser with speech and gestures added.
  4. *
  5. * File browsing code is based on a tutorial from anddev.org by Nicolas Gramlich
  6. * http://www.anddev.org/building_an_android_filebrowser_list-based_ -t67.html
  7. *
  8. * @author clchen@google.com (Charles L. Chen)
  9. */
  10. import com.google.marvin.widget.TouchGestureControlOverlay;
  11. import com.google.marvin.widget.TouchGestureControlOverlay.Gesture;
  12. import com.google.marvin.widget.TouchGestureControlOverlay.GestureListener;
  13. import com.google.tts.TTS;
  14. import java.io.File;
  15. import java.util.ArrayList;
  16. import java.util.Collections;
  17. import java.util.List;
  18. import android.app.Activity;
  19. import android.content.Context;
  20. import android.media.MediaPlayer;
  21. import android.net.Uri;
  22. import android.os.Bundle;
  23. import android.os.Vibrator;
  24. import android.view.KeyEvent;
  25. import android.view.MotionEvent;
  26. import android.view.View;
  27. import android.widget.AdapterView;
  28. import android.widget.ArrayAdapter;
  29. import android.widget.FrameLayout;
  30. import android.widget.ListView;
  31. import android.widget.Toast;
  32. import android.widget.AdapterView.OnItemClickListener;
  33. public class MusicFileBrowser extends Activity {
  34. private static final long[] VIBE_PATTERN = {0, 10, 70, 80};
  35. private Vibrator vibe;
  36. private List<String> directoryEntries = new ArrayList<String>();
  37. private File currentDirectory = new File("/sdcard/");
  38. private MediaPlayer mp = new MediaPlayer();
  39. private int lastPosition;
  40. private String lastPlayedFilename = "";
  41. private TTS tts;
  42. private ListView myList;
  43. private FrameLayout myFrame;
  44. private TouchGestureControlOverlay myGestureOverlay;
  45. private boolean overlayActive;
  46. private TTS.InitListener ttsInitListener = new TTS.InitListener() {
  47. public void onInit(int version) {
  48. lastPosition = 0;
  49. vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
  50. browseTo(new File("/sdcard/"));
  51. tts.speak("Music File Browser started.", 0, null);
  52. }
  53. };
  54. private GestureListener gestureListener = new GestureListener() {
  55. public void onGestureChange(Gesture arg0) {
  56. }
  57. public void onGestureFinish(Gesture arg0) {
  58. if (arg0 == Gesture.CENTER) {
  59. File musicFile = new File(lastPlayedFilename);
  60. if (musicFile.isFile()) {
  61. togglePlaying(musicFile);
  62. vibe.vibrate(VIBE_PATTERN, -1);
  63. }
  64. } else if (arg0 == Gesture.RIGHT) {
  65. playNext();
  66. vibe.vibrate(VIBE_PATTERN, -1);
  67. }
  68. }
  69. public void onGestureStart(Gesture arg0) {
  70. }
  71. };
  72. /** Called when the activity is first created. */
  73. @Override
  74. public void onCreate(Bundle icicle) {
  75. super.onCreate(icicle);
  76. myList = new ListView(this);
  77. myList.setOnItemClickListener(new OnItemClickListener() {
  78. public void onItemClick(AdapterView<?> l, View v, int position, long id) {
  79. if (position == 0) {
  80. playNext();
  81. } else if (position == 1) {
  82. upOneLevel();
  83. } else {
  84. lastPosition = position;
  85. File clickedFile =
  86. new File(currentDirectory.getAbsolutePath() + directoryEntries.get(position));
  87. if (clickedFile != null) {
  88. browseTo(clickedFile);
  89. }
  90. }
  91. }
  92. });
  93. myFrame = new FrameLayout(this);
  94. myFrame.addView(myList);
  95. myGestureOverlay = new TouchGestureControlOverlay(this, gestureListener);
  96. overlayActive = false;
  97. setContentView(myFrame);
  98. tts = new TTS(this, ttsInitListener, true);
  99. }
  100. /**
  101. * This function browses up one level according to the field: currentDirectory
  102. * Returns whether or not navigation occurred.
  103. */
  104. private boolean upOneLevel() {
  105. String parent = this.currentDirectory.getParent();
  106. if (parent.equals("/")) {
  107. browseTo(new File("/sdcard/"));
  108. return false;
  109. } else if (this.currentDirectory.getParent() != null) {
  110. this.browseTo(this.currentDirectory.getParentFile());
  111. }
  112. return true;
  113. }
  114. private void browseTo(final File aDirectory) {
  115. if (aDirectory.isDirectory()) {
  116. this.currentDirectory = aDirectory;
  117. fill(aDirectory.listFiles());
  118. lastPosition = 0;
  119. myList.setSelection(0);
  120. } else {
  121. togglePlaying(aDirectory);
  122. }
  123. }
  124. private void togglePlaying(final File aFile) {
  125. if (mp.isPlaying()) {
  126. mp.stop();
  127. } else {
  128. lastPlayedFilename = aFile.getAbsolutePath();
  129. mp = MediaPlayer.create(this, Uri.parse(lastPlayedFilename));
  130. mp.start();
  131. }
  132. }
  133. private void playNext() {
  134. if (mp.isPlaying()) {
  135. mp.stop();
  136. }
  137. int i = lastPosition;
  138. i++;
  139. String path = this.currentDirectory.getAbsolutePath();
  140. while (i < this.directoryEntries.size()) {
  141. String filename = this.directoryEntries.get(i);
  142. File currentFile = new File(path + filename);
  143. if (currentFile.isFile()) {
  144. lastPosition = i;
  145. togglePlaying(currentFile);
  146. return;
  147. }
  148. i++;
  149. }
  150. i = 0;
  151. while (i <= lastPosition) {
  152. String filename = this.directoryEntries.get(i);
  153. File currentFile = new File(path + filename);
  154. if (currentFile.isFile()) {
  155. lastPosition = i;
  156. togglePlaying(currentFile);
  157. return;
  158. }
  159. i++;
  160. }
  161. Toast.makeText(this, R.string.no_files, 1).show();
  162. tts.speak(getString(R.string.no_files), 0, null);
  163. }
  164. private void fill(File[] files) {
  165. this.directoryEntries.clear();
  166. // Add the top two choices
  167. this.directoryEntries.add(currentDirectory.getAbsolutePath());
  168. if (this.currentDirectory.getParent() != null) {
  169. this.directoryEntries.add(" up one level");
  170. }
  171. int currentPathStringLength = this.currentDirectory.getAbsolutePath().length();
  172. List<String> directories = new ArrayList<String>();
  173. for (File file : files) {
  174. if (file.isDirectory()) {
  175. String filename = file.getAbsolutePath().substring(currentPathStringLength);
  176. if (!filename.startsWith("/.")) {
  177. directories.add(filename);
  178. }
  179. }
  180. }
  181. Collections.sort(directories);
  182. this.directoryEntries.addAll(directories);
  183. List<String> audioFiles = new ArrayList<String>();
  184. for (File file : files) {
  185. if (file.getPath().endsWith(".mp3")) {
  186. String filename = file.getAbsolutePath().substring(currentPathStringLength);
  187. if (!filename.startsWith("/.")) {
  188. audioFiles.add(filename);
  189. }
  190. }
  191. }
  192. Collections.sort(audioFiles);
  193. this.directoryEntries.addAll(audioFiles);
  194. ArrayAdapter<String> directoryList =
  195. new ArrayAdapter<String>(this, R.layout.file_row, this.directoryEntries);
  196. myList.setAdapter(directoryList);
  197. }
  198. @Override
  199. public boolean onTrackballEvent(MotionEvent event) {
  200. int selectedId = myList.getSelectedItemPosition();
  201. if (selectedId == -1) {
  202. selectedId = 0;
  203. }
  204. if (lastPosition != selectedId) {
  205. lastPosition = selectedId;
  206. vibe.vibrate(VIBE_PATTERN, -1);
  207. String filename = directoryEntries.get(selectedId);
  208. tts.speak(filename.substring(1), 0, null);
  209. }
  210. return super.onTrackballEvent(event);
  211. }
  212. @Override
  213. public boolean onKeyDown(int keyCode, KeyEvent event) {
  214. if (keyCode == KeyEvent.KEYCODE_BACK) {
  215. // Pressing back should go up a level, not quit the app
  216. if (upOneLevel()) {
  217. return true;
  218. }
  219. } else if (keyCode == KeyEvent.KEYCODE_MENU) {
  220. if (overlayActive) {
  221. myFrame.removeView(myGestureOverlay);
  222. overlayActive = false;
  223. tts.speak("Gestures disabled.", 0, null);
  224. } else {
  225. myFrame.addView(myGestureOverlay);
  226. overlayActive = true;
  227. tts.speak("Gestures activated.", 0, null);
  228. }
  229. return true;
  230. }
  231. return super.onKeyDown(keyCode, event);
  232. }
  233. @Override
  234. public void onDestroy(){
  235. tts.shutdown();
  236. mp.stop();
  237. super.onDestroy();
  238. }
  239. }