下面是我對Android application層進一步學習的一些筆記(linux 環境),轉載時請註明出處 http://blog.csdn.net/zyc13701469860
1.創建帶有sdcard的模擬器
在Eclipse下可以直接創建模擬器,並讓其支持sdcard.但是這種用這種方法創建的sdcard有一個很大的缺點,就是一旦你改變模擬器的參數,那麼這個sdcard就會被清空。也就是說之前push到sdcard裏面的東西全都沒有了。
所以我們要先創建一個sdcard的鏡像文件(.iso),這個鏡像文件可以作爲多個模擬器的sdcard,但是在一個模擬器使用時,該sdcard會被上鎖,其他的模擬器無法訪問。
終端創建sdcard命令
$mksdcard 1024MB sdcard.iso
終端啓動模擬器並附帶剛纔創建的sdcard
$emulator -avd avdname -sdcard sdcard.iso
也可以在Eclipse下通過加載sdcard.iso的方式創建sdcard.
emulator指令的參數選項還非常的多,您可以運行emulator -help獲得更多的參數功能
如-partition-size 128 設置模擬器的內存爲128M
2.關於R.java文件無法自動生成的解決辦法
在用Eclipse的時候,有時會發現R.java文件無法自動生成。遇到這種請況,你需要check:
2.1.在xml文件中,每一個佈局,控件定義的是否正確。有時雖然Eclipse不報錯,比如你爲控件設置了該控件沒有的屬性(語法沒有任何問題),那麼在解析xml文件時就會出錯。
2.2.要注意xml文件名只能爲小寫字母和數字,否則就會報文件名不符合正則表達式的錯誤。所以要根據控制檯打出的信息來找出錯誤的原因。
3.關於在Eclipse中工程內的文件都編譯正確,但是在工程文件夾上有錯誤標識的解決方法
很簡單,選擇菜單項的project ->clean,再重新編譯即可。
4.Android UI的更新
如果我們需要對UI進行更新,不能採用如下方法:
Timer timer = new Timer();
TimerTask task = new TimerTask(){
public void run() {
changeCurrentTime();//update the TextView
}
};
timer.schedule(task, 0, 1000);
因爲Android 線程的安全機制,不允許UI線程在子線程中執行,即UI線程只能在主線程執行。原因是如果子線程需要耗費大量時間,比如下載文件,那麼主線程就因爲超時而down掉。所以要使用Handler類來實現主線程和子線程的通信:
Handler handler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
changeCurrentTime();
break;
}
}
}
class audioTimerTask extends TimerTask{
@Override
public void run() {
handler.sendEmptyMessage(0);
}
}
Time timer = new Timer();
timer.schedule(new audioTimerTask(), 0, 1000);
5.關於Android MediaPlayer
最近,我主要在研究MediaPlayer,並製作了一個demo.
5.1MediaPlayer的生命週期(這裏引用了http://blog.csdn.net/ddna/archive/2010/01/11/5178864.aspx)
MediaPlayer的狀態轉換圖也表徵了它的生命週期,搞清楚這個圖可以幫助我們在使用MediaPlayer時考慮情況更周全,寫出的代碼也更具健壯性。
這張狀態轉換圖清晰的描述了MediaPlayer的各個狀態,也列舉了主要的方法的調用時序,每種方法只能在一些特定的狀態下使用,如果使用時MediaPlayer的狀態不正確則會引發IllegalStateException異常。
Idle 狀態:當使用new()方法創建一個MediaPlayer對象或者調用了其reset()方法時,該MediaPlayer對象處於idle狀態。這兩種方法的一個重要差別就是:如果在這個狀態下調用了getDuration()等方法(相當於調用時機不正確),通過reset()方法進入idle狀態的話會觸發OnErrorListener.onError(),並且MediaPlayer會進入Error狀態;如果是新創建的MediaPlayer對象,則並不會觸發onError(),也不會進入Error狀態。
End 狀態:通過release()方法可以進入End狀態,只要MediaPlayer對象不再被使用,就應當儘快將其通過release()方法釋放掉,以釋放相關的軟硬件組件資源,這其中有些資源是隻有一份的(相當於臨界資源)。如果MediaPlayer對象進入了End狀態,則不會在進入任何其他狀態了。
Initialized 狀態:這個狀態比較簡單,MediaPlayer調用setDataSource()方法就進入Initialized狀態,表示此時要播放的文件已經設置好了。
Prepared 狀態:初始化完成之後還需要通過調用prepare()或prepareAsync()方法,這兩個方法一個是同步的一個是異步的,只有進入Prepared狀態,才表明MediaPlayer到目前爲止都沒有錯誤,可以進行文件播放。
Preparing 狀態:這個狀態比較好理解,主要是和prepareAsync()配合,如果異步準備完成,會觸發OnPreparedListener.onPrepared(),進而進入Prepared狀態。
Started 狀態:顯然,MediaPlayer一旦準備好,就可以調用start()方法,這樣MediaPlayer就處於Started狀態,這表明MediaPlayer正在播放文件過程中。可以使用isPlaying()測試MediaPlayer是否處於了Started狀態。如果播放完畢,而又設置了循環播放,則MediaPlayer仍然會處於Started狀態,類似的,如果在該狀態下MediaPlayer調用了seekTo()或者start()方法均可以讓MediaPlayer停留在Started狀態。
Paused 狀態:Started狀態下MediaPlayer調用pause()方法可以暫停MediaPlayer,從而進入Paused狀態,MediaPlayer暫停後再次調用start()則可以繼續MediaPlayer的播放,轉到Started狀態,暫停狀態時可以調用seekTo()方法,這是不會改變狀態的。
Stop 狀態:Started或者Paused狀態下均可調用stop()停止MediaPlayer,而處於Stop狀態的MediaPlayer要想重新播放,需要通過prepareAsync()和prepare()回到先前的Prepared狀態重新開始纔可以。
PlaybackCompleted狀態:文件正常播放完畢,而又沒有設置循環播放的話就進入該狀態,並會觸發OnCompletionListener的onCompletion()方法。此時可以調用start()方法重新從頭播放文件,也可以stop()停止MediaPlayer,或者也可以seekTo()來重新定位播放位置。
Error狀態:如果由於某種原因MediaPlayer出現了錯誤,會觸發OnErrorListener.onError()事件,此時MediaPlayer即進入Error狀態,及時捕捉並妥善處理這些錯誤是很重要的,可以幫助我們及時釋放相關的軟硬件資源,也可以改善用戶體驗。通過setOnErrorListener(android.media.MediaPlayer.OnErrorListener)可以設置該監聽器。如果MediaPlayer進入了Error狀態,可以通過調用reset()來恢復,使得MediaPlayer重新返回到Idle狀態。
5.2製作一個MediaPlayer播放器
這是我做的一個PPT,全英文的~下面我把主要的步驟和方法貼了出來。我的demo在Android3.0模擬器上可以順利運行.
5.2.1How to use MediaPlayer to play an audio
1.Create a MediaPlayer object
MediaPlayer mp = new MediaPlayer();
2.There are two mainly ways to set the data source.
2.1Play a resource file. You can create a folder named “raw” under folder “res”.Then put you media file in it.
mp.create(this,R.raw.xxx);
Note:Use this method don't need perpare().
3. Finally,you can play your media file.
mp.start();
You also can use MediaPlayer.OnPreparedListener interface when play a stream file.
public void onPrepared(MediaPlayer mp) {
mp.start();
}
And you need register at first.
mp.set.OnPreparedListener(this);
When the MediaPlayer is not used,we should release it's software and hardware resource by the method of release() as soon as possible.
if(mp != null){
mp.stop();
mp.release();
mp = null;
}
5.2.2 Play a video on SurfaceView
1.Define a SurfaceView in your xml file.
2.Get the SurfaceView
SurfaceView mSurfaceView = (SurfaceView) findViewById(R.id.xxx);
3.Define a SurfaceHolder in your code.
SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
4.Create a MediaPlayer object and setDataSource() like audio.
5.2.5 Use SeekBar to control the process of media file
1.Define a SeekBar in xml file.And get it from code.
android:id="@+id/seekbar"
SeekBar mSeekBar = (SeekBar) findViewById(R.id.seekbar);
2.Set the listener of the seekbar
mSeekBar.setOnSeekBarChangeListener(seekBarChangeListener);
3.When the seekbar changed,we set the process of the media.
We need set the Max of the seekbar.
The max is the time of the media file.(ms)
mSeekBar.setMax(mp.getDuration());
private OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener(){
......
public void onStopTrackingTouch(SeekBar seekBar) {
mp.seekTo(seekBar.getProgress());
}
};
Then the media will play from the process.
5.2.6 Control the sound volume
We can use AudioManager.
AudioManager provides access to volume and ringer mode control.
AudioManager mAudioManager =(AudioManager) getSystemService(Context.AUDIO_SERVICE);
We can't set the volume arbitrary,because the stream volume of media is STREAM_MUSIC,and the volume is from 0 to 15.
int maxVolume = mAudioManager.GetStreamMaxVolume ( AudioManager.STREAM_MUSIC ); //volume is 15
int currentVolume = mAudioManager.GetStreamVolume ( AudioManager.STREAM_MUSIC );
if(currentVolume < maxVolume){
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume + 1, AudioManager.FLAG_SHOW_UI);
}