下面是我对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);
}