Transcript Document

Chapter 10
多媒體程式開發
本投影片(下稱教用資源)僅授權給採用教用資源相關之旗標書籍為教科書之授課老師(下稱老師)專用,老師為教學使用之目的,得摘錄、編輯、重製教用資
源(但使用量不得超過各該教用資源內容之80%)以製作為輔助教學之教學投影片,並於授課時搭配旗標書籍公開播放,但不得為網際網路公開傳輸之遠距教學、
網路教學等之使用;除此之外,老師不得再授權予任何第三人使用,並不得將依此授權所製作之教學投影片之相關著作物移作他用。
著作權所有 © 旗標出版股份有限公司
Widget
Widget簡介
android.widget套件包含了許多視覺性的UI元
素,可用來將操作界面展示在應用程式畫面
上。
要熟悉Android多媒體程式的開發,必須從
widget套件著手,因此本章所舉的範例,便
是以android.widget套件的應用為中心。
Gallery簡介
Gallery是一個水平的清單,移動清單時,會
將選擇項目放大顯示於中央,範例如圖所示。
Gallery相關
Gallery包含了一些XML屬性及方法,如下
表所示:
XML屬性
方法
敘述
android:animationDuration setAnimationDuration(int)
設定當佈局發生改變時,動畫應多
久才會運行(毫秒)
android:gravity
setGravity(int)
設定物件的擺放位置
android:spacing
setSpacing(int)
android:unselectedAlpha
setUnselectedAlpha(float)
設定項目未被選擇時的透明度
Gallery布局文件
布局文件(res/layout/main.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageSwitcher android:id="@+id/switcher"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
/>
<Gallery android:id="@+id/gallery"
android:background="#55000000"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:gravity="center_vertical"
android:spacing="16dp"
/>
</RelativeLayout>
Gallery程式碼-1
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSwitcher = (ImageSwitcher) findViewById(R.id.switcher);
/* 設定ImageSwitcher的Factory進行資源配置 */
mSwitcher.setFactory(this);
/* 設定ImageSwitcher動畫 */
mSwitcher.setInAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_in));
mSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_out));
/* 初始化Gallery */
Gallery g = (Gallery) findViewById(R.id.gallery);
/* 設定Adapter */
g.setAdapter(new ImageAdapter(this));
/* 設定項目選擇監聽器 */
g.setOnItemSelectedListener(this);
}
Gallery程式碼-2
public View makeView()
{
ImageView i = new ImageView(this);
/* 設定ImageView屬性 */
i.setBackgroundColor(0xFF000000);
i.setScaleType(ImageView.ScaleType.FIT_CENTER);
i.setLayoutParams(new
ImageSwitcher.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
return i;
}
/* 當項目被選擇到時發生 */
@SuppressWarnings("unchecked")
public void onItemSelected(AdapterView parent, View v, int position, long id)
{
/* 為ImageSwitcher設定圖檔資源 */
mSwitcher.setImageResource(mImageIds[position]);
}
Gallery程式碼-3
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView i = new ImageView(mContext);
/* 設定ImageView屬性 */
i.setImageResource(mThumbIds[position]);
i.setAdjustViewBounds(true);
i.setLayoutParams(new Gallery.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
return i;
}
由於程式碼過多,完整程式碼請參考光
碟中GalleryEX.java
AnalogClock
AnalogClock是一個類比時鐘元件,具有時
針與分針。範例如圖所示。
AnalogClock
布局文件(res/layout/main.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<AnalogClock
android:id="@+id/AnalogClock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
/>
</RelativeLayout>
DigitalClock
與AnalogClock類似,但是以數位的方式呈
現,有時/分/秒,範例如下圖所示。
DigitalClock
布局文件(res/layout/main.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<AnalogClock
android:id="@+id/AnalogClock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
/>
<DigitalClock
android:id="@+id/DigitalClock"
android:text="DigitalClock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@id/AnalogClock"
/>
</RelativeLayout>
多媒體開發
多媒體開發
Android對於多媒體的支援性非常強大,在
SDK中的android.media提供了許多媒體相關
類別可使用,像是一般播放音樂、影片及錄
音…等等功能都可藉由SDK達成,也可自行
搭配元件開發。
其中Android所支援的音訊、圖像、視訊格
式可由下頁圖得知。
多媒體開發
Android支援格式
AudioManager
在手機應用程式當中,有時候會需要調整手
機音量或轉換手機聲音模式。
如果要開發一個具有音量調整功能的程式,
Android API中的AudioManager提供了許多
相關的方法,可在程式中控制音量大小、切
換聲音模式,範例如下圖所示。
AudioManager
程式範例圖:
AudioManager布局文件
布局文件-1:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/widget33"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<ImageButton
android:id="@+id/btnDown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/down"
android:layout_alignLeft="@+id/up"
android:layout_centerHorizontal="true"
/>
<ImageButton
android:id="@+id/btnUp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/up"
android:layout_toLeftOf="@+id/btnDown"
/>
<ImageButton
android:id="@+id/btnMute"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/mute"
android:layout_alignRight="@+id/btnDown"
android:layout_below="@+id/btnDown"
/>
布局文件-2:
<ImageButton
android:id="@+id/btnVibrate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/vibrate"
android:layout_toRightOf="@+id/btnMute"
android:layout_alignTop="@+id/btnMute"
/>
<ImageButton
android:id="@+id/btnNormal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/normal"
android:layout_alignRight="@+id/btnUp"
android:layout_below="@+id/btnUp"
/>
<ImageView
android:id="@+id/imageStatus"
android:src="@drawable/normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="135sp"
android:layout_marginLeft="140sp"
/>
AudioManager布局文件
布局文件-3:
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/barInfo"
android:layout_alignBottom="@+id/ProgressBar"
android:text="音量大小"/>
<TextView
android:layout_above="@+id/barInfo"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/modeInfo"
android:layout_alignBottom="@+id/imageStatus"
android:text="聲音模式"/>
<ProgressBar
android:id="@+id/ProgressBar"
android:layout_width="200px"
android:layout_height="wrap_content"
android:layout_marginTop="200sp"
android:layout_marginLeft="140sp"
style="?android:attr/progressBarStyleHorizontal"
/>
</RelativeLayout>
AudioManager程式碼
程式碼-1(AudioManagerEX.java):
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/* 初始化元件 */
audioManager = (AudioManager)
getSystemService(Context.AUDIO_SERVICE);
btnUp = (ImageButton)findViewById(R.id.btnUp);
btnDown = (ImageButton)findViewById(R.id.btnDown);
btnNormal = (ImageButton)findViewById(R.id.btnNormal);
btnMute = (ImageButton)findViewById(R.id.btnMute);
btnVibrate = (ImageButton)findViewById(R.id.btnVibrate);
volumeBar = (ProgressBar)findViewById(R.id.ProgressBar);
imageStatus = (ImageView)findViewById(R.id.imageStatus);
/* 取得目前手機音量 */
volume = audioManager.getStreamVolume(AudioManager.STREAM_RING);
/* 設定音量條 */
volumeBar.setMax(8);
volumeBar.setProgress(volume);
AudioManager程式碼
程式碼-2(AudioManagerEX.java) :
/* 透過AudioManager取得目前響鈴模式並進行比對,此處為比對一般模式 */
if( ( mode = audioManager.getRingerMode() ) ==
AudioManager.RINGER_MODE_NORMAL )
{
/* 設定目前手機模式的圖示為響鈴 */
imageStatus.setImageDrawable( getResources().getDrawable(R.drawable.normal) );
}
/* 此處為比對靜音模式 */
else if ( mode == AudioManager.RINGER_MODE_SILENT)
{
/* 設定目前手機模式的圖示為靜音 */
imageStatus.setImageDrawable( getResources().getDrawable(R.drawable.mute) );
}
/* 此處為比對震動模式 */
else if ( mode == AudioManager.RINGER_MODE_VIBRATE)
{
/* 設定目前手機模式的圖示為震動 */
imageStatus.setImageDrawable( getResources().getDrawable(R.drawable.vibrate) );
}
AudioManager程式碼
程式碼-3(AudioManagerEX.java) :
/* 透過AudioManager.ADJUST_RAISE調大音量 */
audioManager.adjustVolume(AudioManager.ADJUST_RAISE, 0);
volume = audioManager.getStreamVolume(AudioManager.STREAM_RING);
volumeBar.setProgress(volume);
/* 透過AudioManager.ADJUST_LOWER調小音量 */
audioManager.adjustVolume(AudioManager.ADJUST_LOWER, 0);
volume = audioManager.getStreamVolume(AudioManager.STREAM_RING);
volumeBar.setProgress(volume);
由於程式碼過多,完整程式碼請參考光碟中
AudioManagerEX.java
AudioManager
有關AudioManager中的一些常數可於
Android SDK中找到,在此僅列出較為重要
之常數。
AudioManager常數
ADJUST_LOWER
降低響鈴音量
ADJUST_RAISE
增加響鈴音量
ADJUST_SAME
維持目前音量
MODE_CURRENT
目前聲音模式
MODE_IN_CALL
通話中聲音模式
MODE_NORMAL
一般的聲音模式(無響鈴且無通話進來)
MODE_RINGTONE
響鈴聲音模式
STREAM_ALARM
鬧鐘聲音串流
STREAM_MUSIC
音樂播放串流
STREAM_NOTIFICATION
通知音效串流
STREAM_RING
響鈴串流
STREAM_SYSTEM
系統音效串流
STREAM_VOICE_CALL
通話聲音串流
VIBRATE_SETTING_OFF
震動模式關閉
VIBRATE_SETTING_ON
震動模式開啟
MediaRecorder
MediaRecorder原先只支援音訊錄製,不過
在Android 1.5版本以後開始支援視訊錄製功
能,透過MediaRecorder類別的方法可以錄
製視訊並儲存為MPEG4、H.263和H.264編
碼的視訊。
MediaRecorder運作狀態、範例程式如下頁
圖所示:
MediaRecorder
運作狀態圖:
範例圖:
MediaRecorder
布局文件(res/layout/main.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/white"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/mTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
/>
<ImageButton
android:id="@+id/btnRecord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/record"
android:layout_below="@+id/mTextView"
/>
<ImageButton
android:id="@+id/btnStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/stop"
android:layout_alignTop="@+id/btnRecord"
android:layout_toRightOf="@+id/btnRecord"
/>
<ImageButton
android:id="@+id/btnPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/play"
android:layout_alignTop="@+id/btnRecord"
android:layout_toRightOf="@+id/btnStop"
/>
</RelativeLayout>
MediaRecorder
程式碼(MediaRecorder.java):
/* 監聽錄音按鈕 */
btnRecord.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
try
{
/* 檢查目前是否還有錄音資源 */
if (recorder == null)
recorder = new MediaRecorder();
/* 設置輸入為麥克風 */
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
/* 設置輸出的格式為3gp文件 */
/* 音效編碼採用AMR */
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
/* 暫存文件路徑,檔名為當前系統時間 */
path = "/sdcard/" + System.currentTimeMillis() + ".3ga";
/* 設定輸出路徑 */
recorder.setOutputFile(path);
/* 準備緩衝 */
recorder.prepare();
/* 開始錄音 */
recorder.start();
/* 將狀態設置為正在錄音 */
state = RECORDING;
handler.sendEmptyMessage(UPDATE);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
由於程式碼過多,完整程式碼請參考光
碟中MediaRecorderEX.java
AudioTrack
AudioTrack負責為Java應用程式管理與播放
聲音資源,雖然MediaPlayer也可播放聲音,
但AudioTrack可以設置的屬性更多,播放起
來也較好操作。
它運作有兩種模式:static與streaming
– static通常用於處理時間較短且延遲需求高的聲
音。
– straming則用於播放品質較好、檔案較大或需要
緩衝的聲音。程式範例如下頁圖所示。
AudioTrack
範例圖:
AudioTrack
布局文件(res/layout/main.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/textView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/btnLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="left"
/>
<Button
android:id="@+id/btnRight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="right"
/>
</LinearLayout>
AudioTrack
程式碼(AudioTrackEX.java):
private void playSound(String strPath, int iChannel)
{
/* 檢查是否有AudioTrack物件未釋放 */
if ( audioTrack != null )
{
/* 釋放資源 */
audioTrack.release();
audioTrack = null;
}
/* 設定Buffer */
int iMinBufSize = AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
由於程式碼過多,完整程式碼請參考光
碟中AudioTrackEX.java
MediaPlayer
MediaPlayer可用於控制播放聲音/影像,下
圖描述播放狀態的轉換及程式範例。
MediaPlayer
布局文件(res/layout/main.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/white"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/mTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
/>
<ImageButton
android:id="@+id/btnPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/play"
android:layout_below="@+id/mTextView"
/>
<ImageButton
android:id="@+id/btnPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/pause"
android:layout_alignTop="@+id/btnPlay"
android:layout_toRightOf="@+id/btnPlay"
/>
……
MediaPlayer
程式碼(MediaPlayerEX.java):
/* 建立MediaPlayer物件,使用raw中的sample.mp3資源檔案 */
player = MediaPlayer.create(this,R.raw.sample);
/* 監聽播放音樂按鈕 */
btnPlay.setOnClickListener(new ImageButton.OnClickListener()
{
@Override
public void onClick(View v)
{
try
{
/* 檢查是否存在MediaPlayer物件 */
if(player != null)
{
/* 停止播放 */
player.stop();
}
player.prepare();
/* 開始播放 */
player.start();
text.setText("音樂播放中...");
}
catch (Exception e)
{
text.setText("播放發生異常...");
e.printStackTrace();
}
由於程式碼過多,完整程式碼請參考光
碟中MediaPlayer.java
}
});
MediaPlayer
如果想播放記憶卡中的音樂或利用URL下載
音樂來播放可使用下列方法,主要是透過
MediaPlayer.setDataSource() 方法,將URL或
檔案路徑以字串方式傳入。
MediaPlayer player = new MediaPlayer();
player.setDataSource(URL/檔案路徑);
player.prepare();
player.start();
VideoView
另外如果要播放影片的話,則使用Android
內建之VideoView來播放影片,需先準備格
式為*.3gp格式的影片,並將影片置於sdcard
中,指令如圖所示。需要注意的是在模擬器
上是無法正常播放的,模擬器在模擬一些視
音訊方面還是會有一些問題,故範例需於執
行於Hero實機上。
VideoView
程式範例圖:
VideoView
布局文件(res/layout/main.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<VideoView
android:id="@+id/videoView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
VideoView
程式碼(VideoViewEX.java):
public class MediaPlayerEX2 extends Activity
{
private VideoView videoView;
private String path;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/* 初始化VideoView */
videoView = (VideoView) findViewById(R.id.videoView);
/* 設定VideoView屬性*/
path = "/sdcard/oldhouse.3gp";
videoView.setVideoPath(path);
videoView.setMediaController(new MediaController(this));
videoView.requestFocus();
}
}
RingtoneManager
RingtoneManager提供存取鈴聲、通知或其
他類型的音效。
Android預設系統鈴聲儲存於
【/system/media/audio/ringtones/】。
如不使用預設的位置,則可將檔案置於
【/sdcard/music/】中,還可進一步分類為三
種不同用途的資料夾。
RingtoneManager
此後便可透過RingtoneManager,在設定鈴
聲時,以intent.putExtra產生不同的鈴聲選單,
範例如圖所示。
RingtoneManager
布局文件(res/layout/main.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/Ringtone"
android:text="選擇鈴聲"
/>
</LinearLayout>
RingtoneManager
程式碼(RingtoneManagerEX.java):
/* 設定選擇鈴聲Intent */
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
/* Intent屬性設定 */
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "設定鈴聲");
if( strPath != null)
{
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(strPath));
}
else
{
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, (Uri)null);
}
/* 開啟一個活動並等待回傳值 */
startActivityForResult(intent, RINGTONE_PICKED);
由於程式碼過多,完整程式碼請參考光
碟中RingtoneManager.java
Q&A