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