Android中Ringtone播放詳解【安卓原始碼解析五】
現在咱們來聊聊android系統中鈴聲的播放,從framework層面說說Ringtone的播放原理,我在android原始碼中碰到了播放系統鈴聲中的問題,所以仔細研究了這方面的知識,現在整理一下,給讀者一些幫助,現在我對鈴聲的播放和設定特別親切,不管是簡訊鈴聲方面的,來電鈴聲,還是日曆鈴聲,email的鈴聲,鬧鐘的鈴聲,都能解決鈴聲方面的bug。前面我說了Notification的播放機制,Android中Notification的framework層講解【安卓原始碼解析四】 . 大概給大家說了說,有想了解的可以參考看一看。鈴聲播放的機制都是用MediaPlayer來播放的,通過MediaPlayer來申請AudioManager機制來播放音樂鈴聲的。前面我寫了個呼叫系統鈴聲和sdcard卡中鈴聲的demo,
寫一個intent來啟動播放ringtone的activity:
[java] view plaincopyprint?-
<span style="FONT-SIZE: 16px">Intent intent =
- // Allow user to pick 'Default'
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
- // Show only ringtones
-
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);
- //set the default Notification value
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
- // Don't show 'Silent'
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
- startActivityForResult(intent, SMS_RINGTONE_PICKED);
- </span>
這個activity啟動後就跑到了framework的com.android.internal.app.RingtonePickerActivity裡面去了,在framework部分也可以寫activity類得,這個挺有意思的,哈哈,新發現,有種“山窮水復疑無路,柳暗花明又一村”的感覺!哈哈,這個intent的action發到哪兒去了呢??
在frameworks\base\core\res\AndroidManifest.xml中可以搜到這個action:
[html] view plaincopyprint?- <activityandroid:name="com.android.internal.app.RingtonePickerActivity"
- android:theme="@style/Theme.Dialog.Alert"
- android:excludeFromRecents="true"
- android:multiprocess="true">
- <intent-filter>
- <actionandroid:name="android.intent.action.RINGTONE_PICKER"/>
- <categoryandroid:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- </activity>
<action android:name="android.intent.action.RINGTONE_PICKER" />這個就是接受這個intent的action動作的對應的activity的類,找這個RingtonePickerActivity.java類,這個類的繼承和實現有點特殊,注意觀察:
[java] view plaincopyprint?- publicfinalclass RingtonePickerActivity extends AlertActivity implements
- AdapterView.OnItemSelectedListener, Runnable, DialogInterface.OnClickListener,
- AlertController.AlertParams.OnPrepareListViewListener
這個類繼承AlertActivity並實現了這麼多介面,找到點選每個選項播放的方法監聽:
[java] view plaincopyprint?- private DialogInterface.OnClickListener mRingtoneClickListener =
- new DialogInterface.OnClickListener() {
- /*
- * On item clicked
- */
- publicvoid onClick(DialogInterface dialog, int which) {
- // Save the position of most recently clicked item
- mClickedPos = which;
- // Play clip
- playRingtone(which, 0);
- }
- };
然後找到playRingtone(which, 0);這個方法去:
[java] view plaincopyprint?- privatevoid playRingtone(int position, int delayMs) {
- mHandler.removeCallbacks(this);
- mSampleRingtonePos = position;
- mHandler.postDelayed(this, delayMs);
- }
這個postDelayed(this, delayMs);this代表當前物件,因為這個類是實現了Runnable介面,所以這時候會走到run方法中去:
- publicvoid run() {
- if (mSampleRingtonePos == mSilentPos) {
- mRingtoneManager.stopPreviousRingtone();
- return;
- }
- /*
- * Stop the default ringtone, if it's playing (other ringtones will be
- * stopped by the RingtoneManager when we get another Ringtone from it.
- * by bw on start
- * when it`s not null set the default ringtone is null
- * modify by wangxianming in 2011-12-28
- */
- if (mDefaultRingtone != null) {
- // if(mDefaultRingtone.isPlaying()){
- mDefaultRingtone.stop();
- // }
- mDefaultRingtone = null;
- }
- Ringtone ringtone;
- if (mSampleRingtonePos == mDefaultRingtonePos) {
- if (mDefaultRingtone == null) {
- mDefaultRingtone = RingtoneManager.getRingtone(this, mUriForDefaultItem);
- }
- ringtone = mDefaultRingtone;
- /*
- * Normally the non-static RingtoneManager.getRingtone stops the
- * previous ringtone, but we're getting the default ringtone outside
- * of the RingtoneManager instance, so let's stop the previous
- * ringtone manually.
- */
- mRingtoneManager.stopPreviousRingtone();
- } else {
- ringtone = mRingtoneManager.getRingtone(getRingtoneManagerPosition(mSampleRingtonePos));
- }
- if (ringtone != null) {
- ringtone.play();
- }
- }
這時候找到這裡就基本上找到根源了,ringtone.play();就是播放ringtone音樂的方法;注意:15行,16行,我對原始碼進行了修改,這個有點問題,原始碼對原生態的音樂格式支援的很好,但是對mid格式的音樂支援的不太好,所以如果播放mid格式的音樂不能用多個mediaplayer來播放,只能用一個來播放,只能hold住一個,不能重複hold這個ringtone,所以把這個mDefaultRingtone = null;每次都置為空,這樣每次都是一個物件就可以了。這樣播放系統鈴聲就沒有問題了!
再去frameworks\base\media\java\android\media\Ringtone.java這個類去找到play()方法:
[java] view plaincopyprint?- publicvoid play() {
- if (mAudio == null) {
- try {
- openMediaPlayer();
- } catch (Exception ex) {
- Log.e(TAG, "play() caught ", ex);
- mAudio = null;
- }
- }
- if (mAudio != null) {
- // do not ringtones if stream volume is 0
- // (typically because ringer mode is silent).
- if (mAudioManager.getStreamVolume(mStreamType) != 0) {
- if (mIsLoop){
- mAudio.setLooping(true);
- }
- mAudio.start();
- }
- }
- }
找到openMediaPlayer()方法 :
[java] view plaincopyprint?- privatevoid openMediaPlayer() throws IOException {
- mAudio = new MediaPlayer();
- if (mUri != null) {
- mAudio.setDataSource(mContext, mUri);
- } elseif (mFileDescriptor != null) {
- mAudio.setDataSource(mFileDescriptor);
- } elseif (mAssetFileDescriptor != null) {
- // Note: using getDeclaredLength so that our behavior is the same
- // as previous versions when the content provider is returning
- // a full file.
- if (mAssetFileDescriptor.getDeclaredLength() < 0) {
- mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor());
-
} else
相關推薦
Android中Ringtone播放詳解【安卓原始碼解析五】
現在咱們來聊聊android系統中鈴聲的播放,從framework層面說說Ringtone的播放原理,我在android原始碼中碰到了播放系統鈴聲中的問題,所以仔細研究了這方面的知識,現在整理一下,給讀者一些幫助,現在我對鈴聲的播放和設定特別親切,不管是簡
Android中的動畫詳解系列【1】——逐幀動畫
逐幀動畫其實很簡單,下面我們來看一個例子:<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:andro
Eclipse中的BuildPath詳解【轉載】
sdn libraries 依賴 源代碼 title 打開 低版本 代碼 功能 什麽是Build Path? Build Path是指定Java工程所包含的資源屬性集合。 在一個成熟的Java工程中,不僅僅有自己編寫的源代碼,還需要引用系統運行庫(JRE)、第三方的功能擴展
android中wifi原理詳解(轉)
二:Wifi模組的初始化:: 在 SystemServer 啟動的時候,會生成一個ConnectivityService的例項, try { Log.i(TAG, "Starting Connectivity Service."); ServiceManager.addService(Con
Android中JNI使用詳解(4)---Java與C之間資料型別轉換
Jni中基本型別轉換對應的表格 Java型別 本地型別 說明 boolean jboolean 無符號,8位 byte jbyte
Android中JNI使用詳解(3)---Android Studio中SO檔案生成
Android中JNI使用詳解(2)---Android Studio中SO檔案生成 上一篇寫到過在Android Studio中配置NDK環境地址:Android Studio中NDK環境配置 這篇文章講解在Android Studio中
Android中JNI使用詳解(2)---Android Studio中NDK環境配置
Android Studio中的NDK環境配置 1、下載NKD 在Android Studio中選擇File----Settings----Appearance&Behavior---System Settings----Andr
Android中JNI使用詳解(1)---Eclipse中NDK配置So檔案生成
1、NDK下載和配置 NDK下載地址:http://www.androiddevtools.cn/ NDK下載完成後,選擇Eclipse上方Window選單Preferences - Android - NDK 在NDK&nb
Android中的Service詳解
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
android中wifi原理詳解 轉
二:Wifi模組的初始化::在 SystemServer 啟動的時候,會生成一個ConnectivityService的例項,try {Log.i(TAG, "Starting Connectivity Service.");ServiceManager.addService(
Android中SQLite應用詳解
上次我向大家介紹了SQLite的基本資訊和使用過程,相信朋友們對SQLite已經有所瞭解了,那今天呢,我就和大家分享一下在Android中如何使用SQLite。 現在的主流移動裝置像Android、iPhone等都使用SQLite作為複雜資料的儲存引擎,在我們為移動裝置開發
Http——Android中HttpURLConnection使用詳解
認識Http協議 ndroid中傳送http網路請求是很常見的,要有GET請求和POST請求。一個完整的http請求需要經歷兩個過程:客戶端傳送請求到伺服器,然後伺服器將結果返回給客戶端,如下圖所示: 客戶端->伺服器 客戶端向伺服器傳送請求主要包含以下資
Android中AsyncTask使用詳解
在Android中我們可以通過Thread+Handler實現多執行緒通訊,一種經典的使用場景是:在新執行緒中進行耗時操作,當任務完成後通過Handler向主執行緒傳送Message,這樣主執行緒的Handler在收到該Message之後就可以進行更新UI的操作
[轉載]Android中AndroidManifest.xml詳解
一、關於AndroidManifest.xml AndroidManifest.xml 是每個android程式中必須的檔案。它位於整個專案的根目錄,描述了package中暴露的元件(activities, services, 等等),他們各自的實現類,各種能被處理的資料和
Android 中 HttpURLConnection 使用詳解
認識Http協議 Android中傳送http網路請求是很常見的,要有GET請求和POST請求。一個完整的http請求需要經歷兩個過程:客戶端傳送請求到伺服器,然後伺服器將結果返回給客戶端,如下圖所示: 客戶端->伺服器 客戶端向伺服器傳送請求主要包含以下
Android中Service(服務)詳解
Service是Android中四大元件之一,在Android開發中起到非常重要的作用,先來看一下官方對Service的定義: A is an application component that can perform long-running operation
Android中垃圾回收詳解
在這個例子中,一個新的物件被建立,由於它沒有使用,所以該物件迅速地變為不可達,程式編譯後,執行命令: java -verbosegc TestGC 後結果為: [Full GC 168K->97K(1984K), 0.0253873 secs] 機器的環境為,Windows 2000 + JDK
Android中的Binder詳解
Binder簡介 由於Binder在Android的資訊傳輸中佔有比較重要的作用,所以把對Binder的分析單獨出一篇文章來記錄一下。 什麼是Binder Binder,翻譯為粘合劑,在Android程序間通訊相關的知識中經常出現。一般來說對Binder
Android中shape屬性詳解
一、簡單使用 剛開始,就先不講一堆標籤的意義及用法,先簡單看看shape標籤怎麼用。 1、新建shape檔案 首先在res/drawable資料夾下,新建一個檔案,命名為:shape_radius.xml 內容是這樣的:(先不需要理解,先看sh
Android中ContentProvider元件詳解
1.ContentProvider Android提供了一些主要資料型別的ContentProvider,比如音訊、視訊、圖片和私人通訊錄等。可在android.provider包下面找到一些Android提供的ContentProvider。通過獲得這些ContentProvider可以查詢它們包含的資料,