PageRenderTime 63ms CodeModel.GetById 17ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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}