瀏覽代碼

Initial commit for Multimedia related projects.

Cristian Tanas 11 年之前
父節點
當前提交
ff81eaffe6
共有 45 個文件被更改,包括 868 次插入0 次删除
  1. 30 0
      MultimediaMediaPlayerService/AndroidManifest.xml
  2. 二進制
      MultimediaMediaPlayerService/ic_launcher-web.png
  3. 二進制
      MultimediaMediaPlayerService/libs/android-support-v4.jar
  4. 二進制
      MultimediaMediaPlayerService/res/drawable-hdpi/ic_launcher.png
  5. 二進制
      MultimediaMediaPlayerService/res/drawable-hdpi/pause.png
  6. 二進制
      MultimediaMediaPlayerService/res/drawable-hdpi/play.png
  7. 二進制
      MultimediaMediaPlayerService/res/drawable-hdpi/stop.png
  8. 二進制
      MultimediaMediaPlayerService/res/drawable-mdpi/ic_launcher.png
  9. 二進制
      MultimediaMediaPlayerService/res/drawable-xhdpi/ic_launcher.png
  10. 二進制
      MultimediaMediaPlayerService/res/drawable-xxhdpi/ic_launcher.png
  11. 51 0
      MultimediaMediaPlayerService/res/layout/activity_main.xml
  12. 二進制
      MultimediaMediaPlayerService/res/raw/chasing_eidolon__set_me_free.mp3
  13. 11 0
      MultimediaMediaPlayerService/res/values-v11/styles.xml
  14. 12 0
      MultimediaMediaPlayerService/res/values-v14/styles.xml
  15. 10 0
      MultimediaMediaPlayerService/res/values/strings.xml
  16. 20 0
      MultimediaMediaPlayerService/res/values/styles.xml
  17. 118 0
      MultimediaMediaPlayerService/src/org/uab/android/multimedia/mediaplayerservice/AudioPlayerService.java
  18. 112 0
      MultimediaMediaPlayerService/src/org/uab/android/multimedia/mediaplayerservice/MainActivity.java
  19. 29 0
      MultimediaMediaRecorder/AndroidManifest.xml
  20. 二進制
      MultimediaMediaRecorder/ic_launcher-web.png
  21. 二進制
      MultimediaMediaRecorder/libs/android-support-v4.jar
  22. 二進制
      MultimediaMediaRecorder/res/drawable-hdpi/ic_launcher.png
  23. 二進制
      MultimediaMediaRecorder/res/drawable-mdpi/ic_launcher.png
  24. 二進制
      MultimediaMediaRecorder/res/drawable-xhdpi/ic_launcher.png
  25. 二進制
      MultimediaMediaRecorder/res/drawable-xxhdpi/ic_launcher.png
  26. 34 0
      MultimediaMediaRecorder/res/layout/activity_main.xml
  27. 11 0
      MultimediaMediaRecorder/res/values-v11/styles.xml
  28. 12 0
      MultimediaMediaRecorder/res/values-v14/styles.xml
  29. 11 0
      MultimediaMediaRecorder/res/values/strings.xml
  30. 20 0
      MultimediaMediaRecorder/res/values/styles.xml
  31. 238 0
      MultimediaMediaRecorder/src/org/uab/android/multimedia/mediarecorder/MainActivity.java
  32. 27 0
      MultimediaVideoView/AndroidManifest.xml
  33. 二進制
      MultimediaVideoView/ic_launcher-web.png
  34. 二進制
      MultimediaVideoView/libs/android-support-v4.jar
  35. 二進制
      MultimediaVideoView/res/drawable-hdpi/ic_launcher.png
  36. 二進制
      MultimediaVideoView/res/drawable-mdpi/ic_launcher.png
  37. 二進制
      MultimediaVideoView/res/drawable-xhdpi/ic_launcher.png
  38. 二進制
      MultimediaVideoView/res/drawable-xxhdpi/ic_launcher.png
  39. 15 0
      MultimediaVideoView/res/layout/activity_main.xml
  40. 二進制
      MultimediaVideoView/res/raw/moon.mp4
  41. 11 0
      MultimediaVideoView/res/values-v11/styles.xml
  42. 12 0
      MultimediaVideoView/res/values-v14/styles.xml
  43. 7 0
      MultimediaVideoView/res/values/strings.xml
  44. 20 0
      MultimediaVideoView/res/values/styles.xml
  45. 57 0
      MultimediaVideoView/src/org/uab/android/multimedia/videoview/MainActivity.java

+ 30 - 0
MultimediaMediaPlayerService/AndroidManifest.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.uab.android.multimedia.mediaplayerservice"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="19" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name=".MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <service 
+            android:name=".AudioPlayerService" />
+    </application>
+
+</manifest>

二進制
MultimediaMediaPlayerService/ic_launcher-web.png


二進制
MultimediaMediaPlayerService/libs/android-support-v4.jar


二進制
MultimediaMediaPlayerService/res/drawable-hdpi/ic_launcher.png


二進制
MultimediaMediaPlayerService/res/drawable-hdpi/pause.png


二進制
MultimediaMediaPlayerService/res/drawable-hdpi/play.png


二進制
MultimediaMediaPlayerService/res/drawable-hdpi/stop.png


二進制
MultimediaMediaPlayerService/res/drawable-mdpi/ic_launcher.png


二進制
MultimediaMediaPlayerService/res/drawable-xhdpi/ic_launcher.png


二進制
MultimediaMediaPlayerService/res/drawable-xxhdpi/ic_launcher.png


+ 51 - 0
MultimediaMediaPlayerService/res/layout/activity_main.xml

@@ -0,0 +1,51 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="${relativePackage}.${activityClass}" >
+
+    <ImageButton
+        android:id="@+id/playButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:layout_marginBottom="10dp"
+        android:src="@drawable/play"
+        android:contentDescription="@string/playDescription" />
+
+    <ImageButton
+        android:id="@+id/pauseButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBottom="@+id/playButton"
+        android:layout_toRightOf="@+id/playButton"
+        android:src="@drawable/pause"
+        android:contentDescription="@string/pauseDescription" />
+
+    <ImageButton
+        android:id="@+id/stopButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBottom="@+id/playButton"
+        android:layout_toLeftOf="@+id/playButton"
+        android:src="@drawable/stop"
+        android:contentDescription="@string/stopDescription" />
+
+    <TextView
+        android:id="@+id/songName"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+    <TextView
+        android:id="@+id/mediaPlayerStatus"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_above="@+id/playButton"
+        android:layout_centerHorizontal="true"
+        android:layout_marginBottom="42dp" />
+
+</RelativeLayout>

二進制
MultimediaMediaPlayerService/res/raw/chasing_eidolon__set_me_free.mp3


+ 11 - 0
MultimediaMediaPlayerService/res/values-v11/styles.xml

@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 12 - 0
MultimediaMediaPlayerService/res/values-v14/styles.xml

@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 10 - 0
MultimediaMediaPlayerService/res/values/strings.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">MultimediaMediaPlayerService</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="playDescription">Play</string>
+    <string name="pauseDescription">Pause</string>
+    <string name="stopDescription">Stop</string>
+
+</resources>

+ 20 - 0
MultimediaMediaPlayerService/res/values/styles.xml

@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>

+ 118 - 0
MultimediaMediaPlayerService/src/org/uab/android/multimedia/mediaplayerservice/AudioPlayerService.java

@@ -0,0 +1,118 @@
+package org.uab.android.multimedia.mediaplayerservice;
+
+import java.io.IOException;
+
+import android.app.Service;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.IBinder;
+import android.util.Log;
+
+public class AudioPlayerService extends Service {
+	
+	static final String LOG_TAG = "MULTIMEDIA_MEDIA_PLAYER_SERVICE_AUDIO_PLAYER_SERVICE";
+
+	// MediaPlayer object to reproduce an audio file 
+	MediaPlayer		mediaPlayer;
+	
+	@Override
+	public int onStartCommand(Intent intent, int flags, int startId) {
+		
+		return super.onStartCommand(intent, flags, startId);
+	}
+
+	@Override
+	public IBinder onBind(Intent intent) {
+		
+		// Create and return an instance of AudioPlayerServiceBinder
+		
+		AudioPlayerServiceBinder serviceBinder = new AudioPlayerServiceBinder();
+		return serviceBinder;
+	}
+	
+	@Override
+	public void onDestroy() {
+		
+		// Release any resources associated with the MediaPlayer
+		stop();
+		super.onDestroy();
+	}
+	
+	public void play(Uri audioFile) {
+		
+		if ( mediaPlayer != null ) {
+			
+			// If the MediaPlayer has already been initialized and been paused 
+			// try to resume the audio playback
+			try {
+				
+				mediaPlayer.start();
+				
+			} catch (IllegalStateException e) {
+				Log.e(LOG_TAG, "MediaPlayer has receive start in an invalid state.");
+			}
+		}
+		else {
+		
+			mediaPlayer = new MediaPlayer();
+
+			try {
+
+				// Set the audio file that should be reproduced
+				mediaPlayer.setDataSource(getBaseContext(), audioFile);
+
+				// Prepare the MediaPlayer resources. Note: This operation is SYNCHRONOUS
+				mediaPlayer.prepare();
+				
+				// Start playing
+				mediaPlayer.start();
+
+			} catch (IOException e) {
+				Log.e(LOG_TAG, "Couldn't prepare and start MediaPlayer");
+			}
+		}
+	}
+	
+	public void pause() {
+		
+		// If the MediaPlayer is playing audio, pause it
+		if ( mediaPlayer != null && mediaPlayer.isPlaying() ) {
+			mediaPlayer.pause();
+		}
+	}
+	
+	public void stop() {
+		
+		// If the MediaPlayer is playing audio, stop it and then release its resources
+		if ( mediaPlayer != null ) {
+			
+			if ( mediaPlayer.isPlaying() ) {
+				mediaPlayer.stop();
+			}
+			
+			mediaPlayer.release();
+			mediaPlayer = null;
+		}
+	}
+	
+	public boolean isPlaying() {
+		
+		if ( mediaPlayer != null && mediaPlayer.isPlaying() ) {
+			
+			return true;
+		}
+		
+		return false;
+	}
+
+	
+	public class AudioPlayerServiceBinder extends Binder {
+		
+		// Return a reference to the AudioPlayerService class
+		public AudioPlayerService getServiceInstance() {
+			return AudioPlayerService.this;
+		}
+	}
+}

+ 112 - 0
MultimediaMediaPlayerService/src/org/uab/android/multimedia/mediaplayerservice/MainActivity.java

@@ -0,0 +1,112 @@
+package org.uab.android.multimedia.mediaplayerservice;
+
+import org.uab.android.multimedia.mediaplayerservice.AudioPlayerService.AudioPlayerServiceBinder;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+public class MainActivity extends Activity {
+	
+	static final String LOG_TAG = "MULTIMEDIA_MEDIA_PLAYER_SERVICE_MAIN_ACTIVITY";
+	
+	// Reference to the AudioPlayerService for playback control
+	AudioPlayerService audioPlayerService;
+	
+	String		audioFilePath = "android.resource://org.uab.android.multimedia.mediaplayerservice/" + R.raw.chasing_eidolon__set_me_free;
+	
+	ImageButton		playButton;
+	ImageButton		pauseButton;
+	ImageButton		stopButton;
+	
+	TextView	songNameTv;
+	TextView	mediaPlayerStatus;
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_main);
+		
+		songNameTv = (TextView) findViewById(R.id.songName);
+		mediaPlayerStatus = (TextView) findViewById(R.id.mediaPlayerStatus);
+		
+		playButton = (ImageButton) findViewById(R.id.playButton);
+		playButton.setOnClickListener(new View.OnClickListener() {
+			
+			@Override
+			public void onClick(View v) {
+				
+				mediaPlayerStatus.setText("Playing");
+				songNameTv.setText(getResources().getResourceEntryName(R.raw.chasing_eidolon__set_me_free));
+				audioPlayerService.play(Uri.parse(audioFilePath));
+			}
+		});
+		
+		pauseButton = (ImageButton) findViewById(R.id.pauseButton);
+		pauseButton.setOnClickListener(new View.OnClickListener() {
+			
+			@Override
+			public void onClick(View v) {
+				
+				mediaPlayerStatus.setText("Paused");
+				audioPlayerService.pause();
+			}
+		});
+		
+		stopButton = (ImageButton) findViewById(R.id.stopButton);
+		stopButton.setOnClickListener(new View.OnClickListener() {
+			
+			@Override
+			public void onClick(View v) {
+				
+				mediaPlayerStatus.setText("Stopped");
+				songNameTv.setText("");
+				audioPlayerService.stop();
+			}
+		});
+		
+		Intent audioPlayerIntent = new Intent(this, AudioPlayerService.class);
+		bindService(
+				audioPlayerIntent, 
+				audioPlayerServiceConnection, 
+				Context.BIND_AUTO_CREATE
+				);
+	}
+	
+	@Override
+	protected void onDestroy() {
+		super.onDestroy();
+		
+		if ( !audioPlayerService.isPlaying() ) {
+			
+			unbindService(audioPlayerServiceConnection);
+		}
+		
+	}
+	
+	ServiceConnection audioPlayerServiceConnection = new ServiceConnection() {
+		
+		@Override
+		public void onServiceDisconnected(ComponentName name) {
+			
+			Log.i(LOG_TAG, "AudioPlayerService disconnected.");
+			audioPlayerService = null;
+		}
+		
+		@Override
+		public void onServiceConnected(ComponentName name, IBinder service) {
+			
+			Log.i(LOG_TAG, "AudioPlayerService connected.");
+			audioPlayerService = ((AudioPlayerServiceBinder) service).getServiceInstance();
+		}
+	};
+}

+ 29 - 0
MultimediaMediaRecorder/AndroidManifest.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.uab.android.multimedia.mediarecorder"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="19" />
+    
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name=".MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>

二進制
MultimediaMediaRecorder/ic_launcher-web.png


二進制
MultimediaMediaRecorder/libs/android-support-v4.jar


二進制
MultimediaMediaRecorder/res/drawable-hdpi/ic_launcher.png


二進制
MultimediaMediaRecorder/res/drawable-mdpi/ic_launcher.png


二進制
MultimediaMediaRecorder/res/drawable-xhdpi/ic_launcher.png


二進制
MultimediaMediaRecorder/res/drawable-xxhdpi/ic_launcher.png


+ 34 - 0
MultimediaMediaRecorder/res/layout/activity_main.xml

@@ -0,0 +1,34 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="${relativePackage}.${activityClass}" >
+
+    <TextView
+        android:id="@+id/doingWhat"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true" />
+
+    <ToggleButton
+        android:id="@+id/audioPlaying"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentRight="true"
+        android:textOn="@string/stopPlaying"
+        android:textOff="@string/startPlaying" />
+
+    <ToggleButton
+        android:id="@+id/audioRecording"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_above="@+id/audioPlaying"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentRight="true"
+        android:textOn="@string/stopRecording"
+        android:textOff="@string/startRecording" />
+
+</RelativeLayout>

+ 11 - 0
MultimediaMediaRecorder/res/values-v11/styles.xml

@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 12 - 0
MultimediaMediaRecorder/res/values-v14/styles.xml

@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 11 - 0
MultimediaMediaRecorder/res/values/strings.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">MultimediaMediaRecorder</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="startRecording">Start recording</string>
+    <string name="stopRecording">Stop recording</string>
+    <string name="startPlaying">Start playing</string>
+    <string name="stopPlaying">Stop playing</string>
+
+</resources>

+ 20 - 0
MultimediaMediaRecorder/res/values/styles.xml

@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>

+ 238 - 0
MultimediaMediaRecorder/src/org/uab/android/multimedia/mediarecorder/MainActivity.java

@@ -0,0 +1,238 @@
+package org.uab.android.multimedia.mediarecorder;
+
+import java.io.IOException;
+
+import android.app.Activity;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioManager.OnAudioFocusChangeListener;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaRecorder;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.CompoundButton;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+
+public class MainActivity extends Activity {
+	
+	ToggleButton	recordAudio;
+	ToggleButton	playAudio;
+	
+	TextView		what;
+	
+	MediaPlayer		mediaPlayer;
+	MediaRecorder	mediaRecorder;
+	AudioManager	audioManager;
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_main);
+		
+		recordAudio = (ToggleButton) findViewById(R.id.audioRecording);
+		playAudio = (ToggleButton) findViewById(R.id.audioPlaying);
+		
+		what = (TextView) findViewById(R.id.doingWhat);
+		
+		// Set up record button
+		recordAudio.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+			
+			@Override
+			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+				
+				// Enable or disable the play button
+				playAudio.setEnabled(!isChecked);
+				
+				// Start/stop recording
+				onRecordPressed(isChecked);
+			}
+
+			
+		});
+		
+		// Set up play button
+		playAudio.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+			
+			@Override
+			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+				
+				// Enable or disable the record button
+				recordAudio.setEnabled(!isChecked);
+				
+				// Start/stop playing
+				onPlayPressed(isChecked);
+			}
+		});
+		
+		// Get a reference to the AudioManager
+		audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+		
+		// Request audio focus
+		audioManager.requestAudioFocus(
+				audioFocusChangeListener, 		// Audio focus listener
+				AudioManager.STREAM_MUSIC, 		// Audio focus for music playback
+				AudioManager.AUDIOFOCUS_GAIN	// Audio focus time period unknown
+				);
+	}
+	
+	@Override
+	protected void onPause() {
+		
+		// Release recording and playback resources, if necessary
+		stopPlaying();
+		
+		if ( mediaRecorder != null ) {
+			mediaRecorder.release();
+			mediaRecorder = null;
+		}
+		
+		super.onPause();
+	}
+	
+	/**
+	 * Determines whether the MediaPlayer should start or stop playing.
+	 * 
+	 * @param shouldStartPlaying State of the play toggle button
+	 */
+	protected void onPlayPressed(boolean shouldStartPlaying) {
+		
+		if (shouldStartPlaying) {
+			startPlaying();
+		} else {
+			stopPlaying();
+		}
+	}
+	
+	/**
+	 * Initializes the MediaPlayer for audio playback.
+	 */
+	private void startPlaying() {
+		
+		what.setText("Playing audio.");
+		
+		mediaPlayer = new MediaPlayer();
+		
+		try {
+			// Set the audio file that should be reproduced
+			mediaPlayer.setDataSource(getFilesDir() + "/audio.m4a");
+			
+			// Set a listener to perform some action when the audio is done playing
+			mediaPlayer.setOnCompletionListener(audioCompletionListener);
+			
+			// Prepare the MediaPlayer resources. Note: This operation is SYNCHRONOUS
+			mediaPlayer.prepare();
+			
+			// Start playing
+			mediaPlayer.start();
+		} catch (IOException e) {
+			Log.e("MULTIMEDIA_MEDIA_RECORDER", "Couldn't prepare and start MediaPlayer");
+		}
+	}
+	
+	/**
+	 * Stops the MediaPlayer from audio playback and releases its resources.
+	 */
+	private void stopPlaying() {
+		
+		if ( mediaPlayer != null ) {
+			
+			if ( mediaPlayer.isPlaying() ) {
+				mediaPlayer.stop();
+			}
+			
+			mediaPlayer.release();
+			mediaPlayer = null;
+		}
+	}
+
+	/**
+	 * Determines whether the MediaRecorder should start or stop recording.
+	 * 
+	 * @param shouldStartRecording State of the record toggle button
+	 */
+	private void onRecordPressed(boolean shouldStartRecording) {
+		
+		if (shouldStartRecording) {
+			startRecording();
+		} else {
+			stopRecording();
+		}
+	}
+	
+	/**
+	 * Initializes the MediaRecorder for audio recording.
+	 */
+	private void startRecording() {
+		
+		what.setText("Recording audio.");
+		
+		mediaRecorder = new MediaRecorder();
+		
+		// Set the MediaRecorder audio source
+		mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+		
+		// Set the audio's output format
+		mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
+		
+		// Set the audio encoder to use to record the audio
+		mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+		
+		// Set the file where the audio should be save on internal storage
+		mediaRecorder.setOutputFile(getFilesDir() + "/audio.m4a");
+		
+		// Prepare the MediaRecorder resources
+		try {
+			mediaRecorder.prepare();
+		} catch (IOException e) {
+			Log.e("MULTIMEDIA_MEDIA_RECORDER", "Couldn't prepare and start MediaRecorder");
+		}
+
+		// Start recording
+		mediaRecorder.start();
+	}
+	
+	/**
+	 * Stops the MediaRecorder from recording and releases its resources
+	 */
+	private void stopRecording() {
+		
+		if ( mediaRecorder != null ) {
+			
+			mediaRecorder.stop();
+			mediaRecorder.release();
+			mediaRecorder = null;
+		}
+	}
+	
+	OnAudioFocusChangeListener audioFocusChangeListener = new OnAudioFocusChangeListener() {
+		
+		@Override
+		public void onAudioFocusChange(int focusChange) {
+			
+			// If the audio focus has been lost, abandon the audio focus for this 
+			// Activity and stop the MediaPlayer if playing audio.
+			if ( focusChange == AudioManager.AUDIOFOCUS_LOSS ) {
+				
+				audioManager.abandonAudioFocus(audioFocusChangeListener);
+				if ( mediaPlayer != null && mediaPlayer.isPlaying() ) {
+					
+					stopPlaying();
+				}
+			}
+		}
+	};
+	
+	OnCompletionListener audioCompletionListener = new OnCompletionListener() {
+		
+		@Override
+		public void onCompletion(MediaPlayer mp) {
+			
+			// If the audio has finished playing set the start/stop button to 
+			// its initial state
+			playAudio.toggle();
+			what.setText("");
+		}
+	};
+}

+ 27 - 0
MultimediaVideoView/AndroidManifest.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.uab.android.multimedia.videoview"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="19" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name=".MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>

二進制
MultimediaVideoView/ic_launcher-web.png


二進制
MultimediaVideoView/libs/android-support-v4.jar


二進制
MultimediaVideoView/res/drawable-hdpi/ic_launcher.png


二進制
MultimediaVideoView/res/drawable-mdpi/ic_launcher.png


二進制
MultimediaVideoView/res/drawable-xhdpi/ic_launcher.png


二進制
MultimediaVideoView/res/drawable-xxhdpi/ic_launcher.png


+ 15 - 0
MultimediaVideoView/res/layout/activity_main.xml

@@ -0,0 +1,15 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    tools:context="${relativePackage}.${activityClass}" >
+
+    <VideoView
+        android:id="@+id/videoView1"
+        android:layout_width="480dp"
+        android:layout_height="640dp"
+        android:layout_centerInParent="true"
+        android:gravity="center" />
+
+</RelativeLayout>

二進制
MultimediaVideoView/res/raw/moon.mp4


+ 11 - 0
MultimediaVideoView/res/values-v11/styles.xml

@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 12 - 0
MultimediaVideoView/res/values-v14/styles.xml

@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 7 - 0
MultimediaVideoView/res/values/strings.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">MultimediaVideoView</string>
+    <string name="hello_world">Hello world!</string>
+
+</resources>

+ 20 - 0
MultimediaVideoView/res/values/styles.xml

@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>

+ 57 - 0
MultimediaVideoView/src/org/uab/android/multimedia/videoview/MainActivity.java

@@ -0,0 +1,57 @@
+package org.uab.android.multimedia.videoview;
+
+import android.app.Activity;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Bundle;
+import android.widget.MediaController;
+import android.widget.VideoView;
+
+public class MainActivity extends Activity {
+	
+	VideoView 			videoViewer;
+	
+	MediaController 	videoViewerController;
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_main);
+		
+		// Get a reference to the VideoView
+		videoViewer = (VideoView) findViewById(R.id.videoView1);
+		
+		// Add a Media controller to allow forward/reverse/pause/resume 
+		videoViewerController = new MediaController(this, true);
+		videoViewerController.setEnabled(false);
+		
+		videoViewer.setMediaController(videoViewerController);
+		videoViewer.setVideoURI(Uri.parse(
+				"android.resource://org.uab.android.multimedia.videoview/raw/moon"
+				));
+		
+		// Add an OnPreparedListener to enable the MediaController once the video is ready
+		videoViewer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+			
+			@Override
+			public void onPrepared(MediaPlayer mp) {
+				
+				videoViewerController.setEnabled(true);
+			}
+		});
+	}
+	
+	@Override
+	protected void onPause() {
+		
+		// Clean up and release resources
+		
+		if ( videoViewer != null && videoViewer.isPlaying() ) {
+			videoViewer.stopPlayback();
+		}
+		
+		videoViewer = null;
+		
+		super.onPause();
+	}
+}