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. 努力学习 HTML5 (4)—— 浏览器对语义元素的支持情况

    经过上一节学习,我们已经建立一个结构良好的页面,如果在旧版的 IE 浏览器中浏览可能这些语义元素无法显示. 毕竟这些语义元素什么也不做,要支持它们,只要让浏览器把它们当做普通的 <div> ...

  2. C++ Data Member内存布局

    如果一个类只定义了类名,没定义任何方法和字段,如class A{};那么class A的每个实例占用1个字节的内存,编译器会会在这个其实例中安插一个char,以保证每个A实例在内存中有唯一的地址,如A ...

  3. 超棒的 15 款 Bootstrap UI 编辑器

    自从 2011 年 Mark Otto 和 Jacob Thornton 开发了  Bootstrap,我们第一次接触并熟知了 Bootstrap .这些都归功于  Twitter!从那以后,它就非常 ...

  4. [转] The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing

    https://www.smartftp.com/support/kb/the-program-cant-start-because-api-ms-win-crt-runtime-l1-1-0dll- ...

  5. leveldb - log格式

    log文件在LevelDb中的主要作用是系统故障恢复时,能够保证不会丢失数据.因为在将记录写入内存的Memtable之前,会先写入Log文件,这样即使系统发生故障,Memtable中的数据没有来得及D ...

  6. LCLFramework框架之Repository模式

    Respository模式在示例中的实际目的小结一下 Repository模式是架构模式,在设计架构时,才有参考价值: Repository模式主要是封装数据查询和存储逻辑: Repository模式 ...

  7. adding validation annotators to model classes 在linq to EntityFrame的Model中添加前台验证validation annotators

    The same solution can be applied for LINQ to SQL. The snippet the article shows for using the Metada ...

  8. Mesos源码分析

    Mesos源码分析(1): Mesos的启动过程总论 Mesos源码分析(2): Mesos Master的启动之一 Mesos源码分析(3): Mesos Master的启动之二 Mesos源码分析 ...

  9. Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别

    <context:annotation-config> 和 <context:component-scan>的区别 <context:annotation-config& ...

  10. 代码生成的地址:mygeneration

    一个代码生成的地址: https://gitshell.com/shiningrise/mygeneration/