Transcript Document

Chapter 10
Multimedia Application Development
本投影片(下稱教用資源)僅授權給採用教用資源相關之旗標書籍為教科書之授課老師(下稱老師)專用,老師為教學使用之目的,得摘錄、編輯、重製教用資
源(但使用量不得超過各該教用資源內容之80%)以製作為輔助教學之教學投影片,並於授課時搭配旗標書籍公開播放,但不得為網際網路公開傳輸之遠距教學、
網路教學等之使用;除此之外,老師不得再授權予任何第三人使用,並不得將依此授權所製作之教學投影片之相關著作物移作他用。
著作權所有 © 旗標出版股份有限公司
Widget
Introduction on Widget
Android.widget includes many visual UI
elements and can apply operation interface in
application display
To get acquainted with Android multi-media
application development, we have to start from
widget. So examples in the chapters all focus
on application of android.widget
Introduction on Gallery
Gallery是一個水平的清單,移動清單時,會
將選擇項目放大顯示於中央,範例如圖所示。
About Gallery
Gallery includes some XML attributes and
methods as shown below:
XML Attribute
Methods
Description
android:animationDuration setAnimationDuration(int)
設定當佈局發生改變時,
動畫應多久才會運行(毫秒)
android:gravity
setGravity(int)
設定物件的擺放位置
android:spacing
setSpacing(int)
android:unselectedAlpha
setUnselectedAlpha(float)
設定項目未被選擇時的透明度
Gallery Layout.xml
Layout.xml (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 Codes-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 Codes-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 Codes-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;
}
Owing to the codes are numerous, please
refer to the reference disc to find the
complete codes of GalleryEX.java
AnalogClock
 AnalogClock is an analog clock component with hour
hand and minute hand .It is shown below:
AnalogClock
Layout.xml (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
 It is similar to AnalogClock, but it adopts digital
time display (which shows hour/minute/second). It
is shown below:
DigitalClock
Layout.xml (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>
Multimedia Application Development
Multimedia Application Development
Android對於多媒體的支援性非常強大,在
SDK中的android.media提供了許多媒體相關
類別可使用,像是一般播放音樂、影片及錄
音…等等功能都可藉由SDK達成,也可自行
搭配元件開發。
其中Android所支援的音訊、圖像、視訊格
式可由下頁圖得知。
Multimedia Application Development
Android Support Formats
AudioManager
在手機應用程式當中,有時候會需要調整手
機音量或轉換手機聲音模式。
如果要開發一個具有音量調整功能的程式,
Android API中的AudioManager提供了許多
相關的方法,可在程式中控制音量大小、切
換聲音模式,範例如下圖所示。
AudioManager
Diagram of the Example :
AudioManager Layout.xml
Layout.xml-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"
/>
Layout.xml-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 Layout.xml
Layout.xml-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 Codes
Codes-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 Codes
Codes-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 Codes
Codes-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);
Owing to the codes are numerous, please
refer to the reference disc to find the
complete codes of AudioManagerEX.java
AudioManager
 Some constants of AudioManager can be found in
Android SDK. Here we only list the important
constants: 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
Operation State Chart Diagram:
Diagram of the Example :
MediaRecorder
Layout.xml (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
Codes (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);
Owing to the codes are numerous, please
refer to the reference disc to find the
complete codes of MediaRecorderEX.java
AudioTrack
AudioTrack負責為Java應用程式管理與播放
聲音資源,雖然MediaPlayer也可播放聲音,
但AudioTrack可以設置的屬性更多,播放起
來也較好操作。
它運作有兩種模式:static與streaming
– static通常用於處理時間較短且延遲需求高的聲
音。
– straming則用於播放品質較好、檔案較大或需要
緩衝的聲音。程式範例如下頁圖所示。
AudioTrack
Diagram of the Example:
AudioTrack
Layout.xml (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
Codes (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);
Owing to the codes are numerous, please
refer to the reference disc to find the
complete codes of AudioTrackEX.java
MediaPlayer
MediaPlayer can be used to display
sound/video. The following shows the shift of
the display mode and the example
MediaPlayer
Layout.xml(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
Codes (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();
}
Owing to the codes are numerous, please
refer to the reference disc to find the
complete codes of 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
Diagram of the the Example:
VideoView
Layout.xml (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
Codes (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
Layout.xml (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
Codes (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);
Owing to the codes are numerous, please
refer to the reference disc to find the
complete codes of RingtoneManager.java
Q&A