PS:今天搞了一下如何实现音频播放...结果被坑了,看书上写的代码是挺简单的,但是有个函数就是死活没看懂,这真是受不了...最后才弄明白,原来是一个实现异步任务的一个类...这个类使用java.util.concurrent这个高效框架来管理线程以及任务的执行...可以解决匿名线程存在的问题...

学习内容:

1.理解AsyncTask

2.如何实现音频播放...

1.AsyncTask

  AsyncTask的特点就是实现一个任务在另一个线程内执行,而不是在主函数中进行执行,这样就不会导致主线程的任务形成阻塞..从而可以一直执行下去,耗时的操作可以在另一个异步的线程中执行...

  AsyncTask定义了三种泛型类型...Params,Progress,Result...这三种类型...

i.Params表示的是启动任务执行的参数...

ii.Progress表示当前这个线程执行任务的百分比...

iii.Result表示的是线程执行完毕后的结果,然后返回给主线程...

 使用AsyncTask还需要覆盖其中的方法,必须要进行覆盖的方法就是protected String doInBackground(Integer... params) {}这个方法,这个方法表示的是我们在后台执行另外一个线程...还有一个常需要覆盖的方法就是protected void onPostExecute(String result){}...这个表示将执行完毕的结果返回给主线程...

 这个类的调用时必须要在主线程中完成调用的...使用new updateseekbar.execute(uri1,uri2,uri3);来完成调用,updateseekbar是我自己定义的类...

 private class updateseekbar extends AsyncTask<Integer, Integer, String>{

        protected void onPostExecute(String result){}
protected void onProgressUpdate(Integer...progress){
seekbar.setProgress(progress[0]);
}
@Override
protected String doInBackground(Integer... params) {
// TODO Auto-generated method stub
while(MainActivity.this.playflag){
try {
Thread.sleep(params[0]);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.publishProgress(MainActivity.this.media.getCurrentPosition());
}
return null;
}
}

  完成了调用,那么就说一下它的执行顺序,首先是执行onPreExecute()函数,这个函数可有可无,然后就是执行doInbackground()函数,来完成耗时的操作...这里的params[0]表示的是第一个参数uri1,并且我们可以调用publishProgress()来更新进度...然后是onProgressUpdate()函数的执行,这个函数的执行是在doInbackground()方法没有执行完时才执行的,执行的时间是不定的,用这个函数里可以加入一个进度条或者是文本显示来告知用户程序执行的进度...最后当doInbackground()函数彻底执行完毕之后,调用onPostExecute()函数来返回程序执行完毕后的结果...

  注意:使用这个类是要遵守一些规则的...

i.任务实例的创建必须要在UI线程里执行,说白了就是实例化这个对象时必须要在UI中完成...

ii.必须在UI线程里调用execute(Params...)方法...

iii.我们不能手动的去调用上面的那四种方法...

iv.这个任务只能执行一次,否则会抛出异常信息...

 再简单阐述一下这个类的工作原理...我先粘贴一下其中如何实现的源代码...

//当在UI线程中调用execute()方法以后,下面这个方法将被调用...
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);//
}
/**
* Executes the task with the specified parameters. The task returns
* itself (this) so that the caller can keep a reference to it.
*
* <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to
* allow multiple tasks to run in parallel on a pool of threads managed by
* AsyncTask, however you can also use your own {@link Executor} for custom
* behavior.
*
* <p><em>Warning:</em> Allowing multiple tasks to run in parallel from
* a thread pool is generally <em>not</em> what one wants, because the order
* of their operation is not defined. For example, if these tasks are used
* to modify any state in common (such as writing a file due to a button click),
* there are no guarantees on the order of the modifications.
* Without careful work it is possible in rare cases for the newer version
* of the data to be over-written by an older one, leading to obscure data
* loss and stability issues. Such changes are best
* executed in serial; to guarantee such work is serialized regardless of
* platform version you can use this function with {@link #SERIAL_EXECUTOR}.
*
* <p>This method must be invoked on the UI thread.
*
* @param exec The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a
* convenient process-wide thread pool for tasks that are loosely coupled.
* @param params The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException If {@link #getStatus()} returns either
* {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
*/
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
} mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params;
exec.execute(mFuture); return this;
}
/**
* Convenience version of {@link #execute(Object...)} for use with
* a simple Runnable object.
*/
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}

  这就是如何实现的源代码,那么这个到底是如何实现的呢,就是当我们在UI启动execute()方法时,会直接调用最上面的那个方法,在这个方法内部自行调用下一个方法...这个方法内部会自行调用onPreExecute()方法...然后在内部调用最下面的这个方法,这个方法来开启另外一个异步线程来完成工作...最后返回...然后另一个异步线程就会执行耗时的工作,最后把最终工作完成的结果进行返回...这就是使用AsyncTask类的使用目的...

  2.实现音乐播放...

  Android多媒体技术应用的就非常的广泛了...我才学习到音乐播放...简单的介绍一下如何实现音乐的播放...这个音乐的播放就使用到了上面的类...目的是实现音乐播放的时候与一个进度条实现同步...当拖拉进度条的时候,音乐的播放也会完成同步...

<LinearLayout 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=".MainActivity" >
<TextView
android:id="@+id/info"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="等待播放"/>
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="wrap_content">
<ImageButton
android:id="@+id/play"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/play"/>
<ImageButton
android:id="@+id/pause"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/pause"/>
<ImageButton
android:id="@+id/stop"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/stop"/>
</LinearLayout>
<SeekBar
android:id="@+id/seekbar"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</LinearLayout>

  布局文件相对的也非常的简单...就是三个图片按钮和一个进度条与一个文本显示控件...每一个音乐播放器都是用图片按钮和进度条组成的...我这里也就弄了个简单的...都看得懂就不解释了...

  在触发图片按钮的时候我们进行监听...获取监听后我们就可以在内部执行一些操作...

package com.example.exam7_2;

import java.io.IOException;

import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView; public class MainActivity extends Activity implements View.OnClickListener, SeekBar.OnSeekBarChangeListener{
private MediaPlayer media;
private boolean playflag=true;
private boolean pauseflag=false;
private SeekBar seekbar=null;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView) findViewById(R.id.info);
findViewById(R.id.play).setOnClickListener(this);
findViewById(R.id.pause).setOnClickListener(this);
findViewById(R.id.stop).setOnClickListener(this);
seekbar=(SeekBar) findViewById(R.id.seekbar); }
private class updateseekbar extends AsyncTask<Integer, Integer, String>{ protected void onPostExecute(String result){}
protected void onProgressUpdate(Integer...progress){
seekbar.setProgress(progress[0]);
}
@Override
protected String doInBackground(Integer... params) {
// TODO Auto-generated method stub
while(MainActivity.this.playflag){
try {
Thread.sleep(params[0]);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.publishProgress(MainActivity.this.media.getCurrentPosition());
}
return null;
} }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId()){
case R.id.play:
{
media=MediaPlayer.create(MainActivity.this, R.raw.wind);
MainActivity.this.media.setOnCompletionListener(new OnCompletionListener() { @Override
public void onCompletion(MediaPlayer arg0) {
// TODO Auto-generated method stub
playflag=false;
media.release();
}
});
seekbar.setMax(MainActivity.this.media.getDuration());
updateseekbar update=new updateseekbar();
//执行者execute
update.execute(1000);
seekbar.setOnSeekBarChangeListener(this);
if(MainActivity.this.media!=null){
MainActivity.this.media.stop();
}
try {
MainActivity.this.media.prepare();
MainActivity.this.media.start();
tv.setText("正在播放文件...");
} catch (Exception e) {
// TODO Auto-generated catch block
tv.setText("文件出现异常...");
e.printStackTrace();
}
break;
}
case R.id.pause:
if(media!=null){
if(pauseflag){
media.start();
pauseflag=false;
}else{
media.pause();
pauseflag=true;
}
}
break;
case R.id.stop:
if(media!=null){
media.stop();
tv.setText("停止播放文件...");
}
break;
}
} @Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
} @Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
} @Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
media.seekTo(seekbar.getProgress());
} }

  非常简单的代码...在这里我就使用了一个类来继承AsyncTask...然后在这个类的内部来完成一些操作...有了上面的基础这个代码就变得很容易懂了...就是另外开了一个异步线程来控制进度条与主线程中的音乐播放实现同步...只有实现了这两者的同步才能够完成一个简单音乐播放器的实现...

 

Android 学习笔记多媒体技术之 AsyncTask+实现音频播放...的更多相关文章

  1. Android 学习笔记多媒体技术之 Drawable类+Tween(补间动画)+Frame(帧动画)

    学习内容: 1.了解Drawable类的作用 2.如何使用Drawable... 3.了解Tween动画... 4.如何创建和使用Tween动画... 1.Drawable类...   Drawabl ...

  2. 【转】 Pro Android学习笔记(九二):AsyncTask(1):AsyncTask类

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在Handler的学习系列中,学习了如何h ...

  3. 【转】 Pro Android学习笔记(七四):HTTP服务(8):使用后台线程AsyncTask

    目录(?)[-] 5秒超时异常 AsyncTask 实现AsyncTask抽象类 对AsyncTask的调用 在哪里运行 其他重要method 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注 ...

  4. 【转】 Pro Android学习笔记(七六):服务(1):local和remote

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ Android提供服务,服务是运行在后台的 ...

  5. 【转】Pro Android学习笔记(四):了解Android资源(下)

    处理任意的XML文件 自定义的xml文件放置在res/xml/下,可以通过R.xml.file_name来获取一个XMLResourceParser对象.下面是xml文件的例子: <rootna ...

  6. Android 学习笔记之Volley(七)实现Json数据加载和解析...

    学习内容: 1.使用Volley实现异步加载Json数据...   Volley的第二大请求就是通过发送请求异步实现Json数据信息的加载,加载Json数据有两种方式,一种是通过获取Json对象,然后 ...

  7. Android学习笔记进阶之在图片上涂鸦(能清屏)

    Android学习笔记进阶之在图片上涂鸦(能清屏) 2013-11-19 10:52 117人阅读 评论(0) 收藏 举报 HandWritingActivity.java package xiaos ...

  8. android学习笔记36——使用原始XML文件

    XML文件 android中使用XML文件,需要开发者手动创建res/xml文件夹. 实例如下: book.xml==> <?xml version="1.0" enc ...

  9. Android学习笔记之JSON数据解析

    转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...

随机推荐

  1. django开发的社区和博客

    社区 线上地址:http://codetheme.sinaapp.com/ Githubhttps://github.com/BeginMan/codetheme 由于利用两周下班时间熬夜做的,难免有 ...

  2. Android 的EditText实现不可编辑

    android:editable is deprecated: Use an <EditText> to make it editable android:editable is depr ...

  3. [C++] zlatlcv: ATL字符串转换辅助库。能很方便的将UTF-8字符串转为TCHAR等字符串

    作者:zyl910 如今,UTF-8字符串的使用频率越来越多了.但是在VC中,不能直接处理UTF-8字符串,得专门去写UTF-8与窄字符串.宽字符串.TCHAR字符串相互转换的代码.不仅费时费力,而且 ...

  4. 【转】JAVA 接口

    1.定义接口    使用interface来定义一个接口.接口定义同类的定义类似,也是分为接口的声明和接口体,其中接口体由常量定义和方法定义两部分组成.定义接口的基本格式如下: [修饰符] inter ...

  5. mahout分类学习和遇到的问题总结

    这段时间学习Mahout有喜有悲.在这里首先感谢樊哲老师的指导.以下列出关于这次Mahout分类的学习和遇到的问题,还请大家多多提出建议:(全部文件操作都使用是在hdfs上边进行的). (本人用的环境 ...

  6. Java基础集锦——利用Collections.sort方法对list排序

    要想对List进行排序,可以让实体对象实现Comparable接口,重写compareTo方法即可实现按某一属性排序,但是这种写法很单一,只能按照固定的一个属性排序,没变法变化.通过下面这种方法,可以 ...

  7. Linux下php5.3编译oracle客户端

    因项目需要在linux下进行php5.3的oracle客户端编译,简要介绍一下步骤及走过的弯路. 1.下载Oracle客户端程序包,其中包含OCI.OCCI和JDBC-OCI等相关文件. 1.1下载文 ...

  8. [ITSEC]信息安全·Web安全培训第一期客户端安全之UBB系列

    缩略图: 引文: 所谓UBB代码,是指论坛中的替代HTML代码的安全代码.ubb发帖编辑器 这种代码使用正则表达式来进行匹配,不同的论坛所使用的UBB代码很可能不同,不能一概而论.UBB代码的出现,使 ...

  9. Spring进阶教程之在ApplicationContext初始化完成后重定义Bean

    前言 很久没有写博客了,也是两个原因:一是自己觉得一直在班门弄斧,其实自己没什么技术可言:二是很多朋友的问题实际上可以自行解决,我经常觉得不该我来过问,或者是有时候我认为技术还得靠自己钻研,我一两句话 ...

  10. Gson整合Volley返回对象--GsonRequest

    Gson是一个使用映射支持JSON与Java对象之间相互转换的库文件.你可以定义和JSON keys相对应名称的Java对象.把对象传递给传递Gson,然后Gson会帮你为对象填充字段值. 下面是一个 ...