Android 学习笔记多媒体技术之 AsyncTask+实现音频播放...
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+实现音频播放...的更多相关文章
- Android 学习笔记多媒体技术之 Drawable类+Tween(补间动画)+Frame(帧动画)
学习内容: 1.了解Drawable类的作用 2.如何使用Drawable... 3.了解Tween动画... 4.如何创建和使用Tween动画... 1.Drawable类... Drawabl ...
- 【转】 Pro Android学习笔记(九二):AsyncTask(1):AsyncTask类
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在Handler的学习系列中,学习了如何h ...
- 【转】 Pro Android学习笔记(七四):HTTP服务(8):使用后台线程AsyncTask
目录(?)[-] 5秒超时异常 AsyncTask 实现AsyncTask抽象类 对AsyncTask的调用 在哪里运行 其他重要method 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注 ...
- 【转】 Pro Android学习笔记(七六):服务(1):local和remote
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ Android提供服务,服务是运行在后台的 ...
- 【转】Pro Android学习笔记(四):了解Android资源(下)
处理任意的XML文件 自定义的xml文件放置在res/xml/下,可以通过R.xml.file_name来获取一个XMLResourceParser对象.下面是xml文件的例子: <rootna ...
- Android 学习笔记之Volley(七)实现Json数据加载和解析...
学习内容: 1.使用Volley实现异步加载Json数据... Volley的第二大请求就是通过发送请求异步实现Json数据信息的加载,加载Json数据有两种方式,一种是通过获取Json对象,然后 ...
- Android学习笔记进阶之在图片上涂鸦(能清屏)
Android学习笔记进阶之在图片上涂鸦(能清屏) 2013-11-19 10:52 117人阅读 评论(0) 收藏 举报 HandWritingActivity.java package xiaos ...
- android学习笔记36——使用原始XML文件
XML文件 android中使用XML文件,需要开发者手动创建res/xml文件夹. 实例如下: book.xml==> <?xml version="1.0" enc ...
- Android学习笔记之JSON数据解析
转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...
随机推荐
- Swift - UITableViewCell倒计时重用解决方案
Swift - UITableViewCell倒计时重用解决方案 效果 源码 https://github.com/YouXianMing/Swift-Animations // // CountDo ...
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...
- 【转】Xcode 6制作动态及静态Framework
http://years.im/Home/Article/detail/id/52.html 创建iOS动态库 新建工程并选择默认Target为Cocoa Touch Framework, 如图: 做 ...
- Java 中的instanceof简单讲解
Java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. 用法:resu ...
- jquery scrollLeft居中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Entity Framework Core 实现读写分离
在之前的版本中我们可用构造函数实现,其实现在的版本也一样,之前来构造连接字符串,现在相似,构造DbContextOptions<T> 代码如下: public SContext(Maste ...
- ASP.NET MVC验证标注的扩展-checkbox必选
我们知道ASP.NET mvc提供一些表单的验证标注,比如必填属性RequiredAttribute 但是这个属性不适合选择框的必选 但是很多时候,我们却是需要一些必选的单选框 比如网站注册的时候,需 ...
- 恶心的sbt 超级慢--解决
最近在看sbt相关的资料.发现其构建仓库是用ivy和maven 相信使用过maven的人都知道下载 jar的过程十分痛苦(因为你穷,买不起VPN) 然后我们天朝本来有开源中国的maven库,后来又突然 ...
- vmtool安装成功,但是hgfs下没有被挂接共享目录!
vmtool安装成功,但是hgfs下没有被挂接共享目录! 2013-01-04 16:05:18| 分类: Linux|字号 订阅 1.使用vmtool 提供的命令——vmware-hgfs ...
- ooofc.com域名备案问题导致无法正常访问临时解决方案
各位尊敬的easyradius用户: 由于临时收到ooofc.coom域名备案被删除的消息,之后ooofc.com就无法访问.导致用户无法访问控制台oa.ooofc.com,及用户中心user.ooo ...