版權聲明:本文為部落客原創文章,轉載請标明出處。 https://blog.csdn.net/chaoyu168/article/details/51150983
1、什麼是Open Core?
Open Core 是 Android 多媒體架構的核心,所有 Android 平台的音頻、視訊的采用以及播放等操作,都是通過它來實作。
2、Open Core 的具體功能
- 1、多媒體檔案的播放、下載下傳,包括:3GPP,MPEG-4,AAC 和 MP3 containers。
- 2、流媒體檔案的下載下傳、實時播放,包括:3GPP,HTTP 和 RTSP/RTP。
- 3、動态視訊和靜态圖像的編碼、解碼,例如:MPEG-4,H.263 和 AVC (H.264),JPEG。
- 4、語音編碼格式:MP3,AAC,AAC+。
- 5、視訊和圖像格式:3GPP,MPEG-4 和 JPEG。
- 6、視訊會議:基于 H324-M 标準。
Open Core 是一個多媒體的架構,從宏觀上來看,它主要包含了兩大方面的内容:
- 1、PVPPlayer:提供媒體播放器的功能,完成各種音頻(Audio)、視訊(Video)流的回放(Playback)功能。
- 2、PVAuthor:提供媒體流記錄的功能,完成各種音頻、視訊流以及靜态圖像的捕獲功能。
3、Mediaplayer 介紹
MediaPlayer 類可以用來播放音頻、視訊和流媒體,MediaPlayer 包含了 Audio 和 Video 的播放功能,在 Android 的界面上, Music 和 Video 兩個應用程式都是調用 MediaPlayer 實作的。下面兩張圖是 MediaPlayer 在 Android 和 Open Core 的示例圖:
下面是圖例顯示 MediaPlayer 的生命周期
3.1、MediaPlayer 常用方法介紹
- 方法: create ( Context context, Uri
uri)
解釋:靜态方法,通過Uri建立一個多媒體播放器。
- 方法:
context,
int resid)
解釋:靜态方法,通過資源ID建立一個多媒體播放器
- uri, SurfaceHolder
holder)
解釋:靜态方法,通過Uri和指定 SurfaceHolder 【抽象類】 建立一個多媒體播放器
- 方法: getCurrentPosition
()
解釋:傳回 Int, 得到目前播放位置
- getDuration 解釋:傳回 Int,得到檔案的時間
- getVideoHeight 解釋:傳回 Int ,得到視訊的高度
- getVideoWidth 解釋:傳回 Int,得到視訊的寬度
- isLooping 解釋:傳回 boolean ,是否循環播放
- isPlaying 解釋:傳回 boolean,是否正在播放
- pause 解釋:無傳回值 ,暫停
- prepare 解釋:無傳回值,準備同步
- prepareAsync 解釋:無傳回值,準備異步
- release 解釋:無傳回值,釋放 MediaPlayer 對象
- reset 解釋:無傳回值,重置 MediaPlayer 對象
- seekTo
(int
msec)
解釋:無傳回值,指定播放的位置(以毫秒為機關的時間)
- setAudioStreamType
streamtype)
解釋:無傳回值,指定流媒體的類型
- setDataSource String
path)
解釋:無傳回值,設定多媒體資料來源【根據 路徑】
- FileDescriptor
fd,
long offset, long length)
解釋:無傳回值,設定多媒體資料來源【根據 FileDescriptor】
-
fd)
解釋:無傳回值,設定多媒體資料來源【根據 FileDescriptor】
-
uri)
解釋:無傳回值,設定多媒體資料來源【根據 Uri】
- setDisplay
sh)
解釋:無傳回值,設定用 SurfaceHolder 來顯示多媒體
- setLooping
(boolean
looping)
解釋:無傳回值,設定是否循環播放
- 事件: setOnBufferingUpdateListener MediaPlayer.OnBufferingUpdateListener
listener)
解釋:監聽事件,網絡流媒體的緩沖監聽
- setOnCompletionListener MediaPlayer.OnCompletionListener 解釋:監聽事件,網絡流媒體播放結束監聽
- setOnErrorListener MediaPlayer.OnErrorListener 解釋:監聽事件,設定錯誤資訊監聽
- setOnVideoSizeChangedListener MediaPlayer.OnVideoSizeChangedListener 解釋:監聽事件,視訊尺寸監聽
- setScreenOnWhilePlaying
screenOn)
解釋:無傳回值,設定是否使用 SurfaceHolder 顯示
- setVolume
(float
leftVolume, float rightVolume)
解釋:無傳回值,設定音量
- start 解釋:無傳回值,開始播放
- stop 解釋:無傳回值,停止播放
4、完整音樂播放例子示範
實作的功能:
1.暫停/播放、下一首/上一首,點選某一首時播放
2.支援拖動進度條快進
3.清單排序
4.來電話時,停止播放,挂斷後繼續播放
5.可在背景播放
界面:
main.xml:
<pre name="code" class="html"><span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"
Android:orientation="vertical"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
>
<TextView
Android:id="@+id/name"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
/>
<SeekBar
Android:id="@+id/seekBar"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:layout_marginBottom="5dp"
/>
<LinearLayout
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:layout_marginBottom="20dp"
>
<Button
Android:layout_width="40dp"
Android:layout_height="40dp"
Android:text="|◀"
Android:onClick="previous"
/>
<Button
Android:id="@+id/pp"
Android:layout_width="40dp"
Android:layout_height="40dp"
Android:text="▶"
Android:onClick="pp"
/>
<Button
Android:layout_width="40dp"
Android:layout_height="40dp"
Android:text="▶|"
Android:onClick="next"
/>
</LinearLayout>
<ListView
Android:id="@+id/list"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
/>
</LinearLayout></span>
item.xml:
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:Android="http://schemas.android.com/apk/res/android"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:padding="10dp"
>
<TextView
Android:id="@+id/mName"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:textSize="15sp"
/>
</LinearLayout></span><span style="font-size: 18px;"> </span>
MainActivity:
<pre name="code" class="java"><span style="font-size:14px;">import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import Android.app.Activity;
import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.Intent;
import Android.content.IntentFilter;
import Android.media.MediaPlayer;
import Android.media.MediaPlayer.OnCompletionListener;
import Android.os.Bundle;
import Android.os.Environment;
import Android.os.Handler;
import Android.telephony.PhoneStateListener;
import Android.telephony.TelephonyManager;
import Android.view.View;
import Android.widget.AdapterView;
import Android.widget.Button;
import Android.widget.ListView;
import Android.widget.SeekBar;
import Android.widget.SimpleAdapter;
import Android.widget.TextView;
import Android.widget.AdapterView.OnItemClickListener;
import Android.widget.SeekBar.OnSeekBarChangeListener;
public class MainActivity extends Activity {
private TextView nameTextView;
private SeekBar seekBar;
private ListView listView;
private List<Map<String, String>> data;
private int current;
private MediaPlayer player;
private Handler handler = new Handler();
private Button ppButton;
private boolean isPause;
private boolean isStartTrackingTouch;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nameTextView = (TextView) findViewById(R.id.name);
seekBar = (SeekBar) findViewById(R.id.seekBar);
listView = (ListView) findViewById(R.id.list);
ppButton = (Button) findViewById(R.id.pp);
//建立一個音樂播放器
player = new MediaPlayer();
//顯示音樂播放清單
generateListView();
//進度條監聽器
seekBar.setOnSeekBarChangeListener(new MySeekBarListener());
//播放器監聽器
player.setOnCompletionListener(new MyPlayerListener());
//意圖過濾器
IntentFilter filter = new IntentFilter();
//播出電話暫停音樂播放
filter.addAction("Android.intent.action.NEW_OUTGOING_CALL");
registerReceiver(new PhoneListener(), filter);
//建立一個電話服務
TelephonyManager manager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
//監聽電話狀态,接電話時停止播放
manager.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
}
private final class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
pause();
}
}
private final class MyPlayerListener implements OnCompletionListener {
//歌曲播放完後自動播放下一首歌曲
public void onCompletion(MediaPlayer mp) {
next();
}
}
public void next(View view) {
next();
}
public void previous(View view) {
previous();
}
private void previous() {
current = current - 1 < 0 ? data.size() - 1 : current - 1;
play();
}
private void next() {
current = (current + 1) % data.size();
play();
}
private final class MySeekBarListener implements OnSeekBarChangeListener {
//移動觸發
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
//起始觸發
public void onStartTrackingTouch(SeekBar seekBar) {
isStartTrackingTouch = true;
}
//結束觸發
public void onStopTrackingTouch(SeekBar seekBar) {
player.seekTo(seekBar.getProgress());
isStartTrackingTouch = false;
}
}
private void generateListView() {
List<File> list = new ArrayList<File>();
//擷取sdcard中的所有歌曲
findAll(Environment.getExternalStorageDirectory(), list);
//播放清單進行排序,字元順序
Collections.sort(list);
data = new ArrayList<Map<String, String>>();
for (File file : list) {
Map<String, String> map = new HashMap<String, String>();
map.put("name", file.getName());
map.put("path", file.getAbsolutePath());
data.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item, new String[] { "name" }, new int[] { R.id.mName });
listView.setAdapter(adapter);
listView.setOnItemClickListener(new MyItemListener());
}
private final class MyItemListener implements OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
current = position;
play();
}
}
private void play() {
try {
//重播
player.reset();
//擷取歌曲路徑
player.setDataSource(data.get(current).get("path"));
//緩沖
player.prepare();
//開始播放
player.start();
//顯示歌名
nameTextView.setText(data.get(current).get("name"));
//設定進度條長度
seekBar.setMax(player.getDuration());
//播放按鈕樣式
ppButton.setText("||");
//發送一個Runnable, handler收到之後就會執行run()方法
handler.post(new Runnable() {
public void run() {
// 更新進度條狀态
if (!isStartTrackingTouch)
seekBar.setProgress(player.getCurrentPosition());
// 1秒之後再次發送
handler.postDelayed(this, 1000);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
private void findAll(File file, List<File> list) {
File[] subFiles = file.listFiles();
if (subFiles != null)
for (File subFile : subFiles) {
if (subFile.isFile() && subFile.getName().endsWith(".mp3"))
list.add(subFile);
else if (subFile.isDirectory())//如果是目錄
findAll(subFile, list); //遞歸
}
}
public void pp(View view) {
//預設從第一首歌曲開始播放
if (!player.isPlaying() && !isPause) {
play();
return;
}
Button button = (Button) view;
//暫停/播放按鈕
if ("||".equals(button.getText())) {
pause();
button.setText("▶");
} else {
resume();
button.setText("||");
}
}
private void resume() {
if (isPause) {
player.start();
isPause = false;
}
}
private void pause() {
if (player != null && player.isPlaying()) {
player.pause();
isPause = true;
}
}
private final class PhoneListener extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
pause();
}
}
protected void onResume() {
super.onResume();
resume();
}
}
</span>
注冊權限:
<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.android.com/apk/res/android"
package="cn.itcast.audio"
Android:versionCode="1"
Android:versionName="1.0">
<application Android:icon="@drawable/icon" android:label="@string/app_name">
<activity Android:name=".MainActivity"
Android:label="@string/app_name">
<intent-filter>
<action Android:name="android.intent.action.MAIN" />
<category Android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk Android:minSdkVersion="8" />
<!-- 監聽電話呼出 -->
<uses-permission Android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<!-- 監聽電話狀态改變 -->
<uses-permission Android:name="android.permission.READ_PHONE_STATE" />
</manifest>