首先,我自己在做一個關於音樂的插件。
其次,該插件的一個需求是在某一個條件下運行,然後彈出一些操作。而這種條件就是當有應用在跑時,如果有背景音樂在播放(play)狀態,我不做某些操作。但如果背景音樂在暫停或停止狀態(pause or stop),我這邊就會做一些操作。
現在的情況是,我找了很多關於android音樂的處理,在底層服務層沒有找到能獲取到當前音樂播放狀態的方式,只能獲取到isActive,但這個狀態在播放和暫停時都是返回true的。而上層情況是其他應用都是用mediaplay進行播放控制,而我作為另一個應用是獲取不到別人應用的類對象的,所以這個問題陷入迷茫狀態,希望做過或了解過這塊的大神們能給出點方法,意見或思路哦。謝謝了,小弟快苦惱死了,搞了一個星期了
研究兩個星期,終於把這個問題進行了曲線救國,下面我來分享下自己的經驗:
思路:
首先別人應用使用的播放方法是不同的,有jetPlay,mediaplay,更有牛的人用上了復雜的mediatrack。所以必須得用一個通用的方法進行獲取。
其次,對於別人應用來說,無論用那種方法,我們都是獲取不到它的播放實例的,比如我研究的是一個Unity3d游戲,底層核心是用mediaplay進行播放控制的,但我們是獲取不到它生成的那個實例的。
最後,我們就必須將思路放到底層,比如service,framework,甚至是驅動級
講一下我自己的研究過程:
首先使用的是liunx下的hook方法,對一些應用調用的庫文件進行hook,如果能夠直接獲取到它自身的函數,比如play,pause等,或者狀態參數返回,那這種方法當然是最好的,准確無誤,不存在外界干擾。唯一的就是需要root權限,這個我想很簡單吧。但有一個很大的缺點,hook函數的調用時frame級別的,如果不做系統是沒辦法是用的。
但我自己進行了研究,發現在unity3d游戲下,hook方法實用性太差,因為它的封裝性太好,而且結構與android正常結構不同,所以我就放棄了。
最後我把思路轉向應用級,試試在應用級上能否找到獲取狀態的函數,但最後不幸的是,除了一個isActive()外,我找不到關於狀態的回饋。柳暗花明又一村,就在這裡我發現了一個音樂播放器常用的東西----頻譜。然後我就試著進行頻譜分析來獲取狀態,而且頻譜與播放形式無關,只跟輸出數據有關。結果是真讓我找到一個歪門邪道。雖然會有延遲還得自己邏輯,但起碼是獲取到了狀態情況。
簡約寫下流程
{
private Visualizer visualizer = null;//頻譜測試器
private byte [] mRawVizData;//頻譜容器
//實例化 Visualizer 對象
visualizer = new Visualizer(0);
mRawVizData = new byte[128];
//對象的初始化
if(visualizer != null)
{
if (visualizer.getEnabled()) {
visualizer.setEnabled(false);
}
visualizer.setCaptureSize(mRawVizData.length);//一定要在頻譜false狀態使用
visualizer.setEnabled(true);//開啟頻譜獲取
}
下面是開一個線程進行循環獲取頻譜信息,我只把獲取給貼出來
int status = Visualizer.ERROR;
if(visualizer != null)
{
//音樂頻譜獲取
status = visualizer.getFft(mRawVizData);//獲取波形圖
if(status != Visualizer.SUCCESS)
{
Log.i("answer", "getWaveFail");
}
else
{
int j = 0;
for(int i = 0; i < 128; i++)
{
if(mRawVizData[i] == 0)
{
j++;
}
}
Log.i("answer", "getWave j = " + j);
}
}
}
最後我們可以看到j的數量,如果j的數量跟你當時申請數組128相同,說明此時是沒有數據流出的,也就是說當前是在pause或stop狀態了,其他數據不一樣就是有數據進行輸出。
關於頻譜的使用大家可以參照http://blog.csdn.net/caryee89/article/details/6935237 大牛之作。
本人也就是使用獲取一下數據而已,並沒多復雜處理,僅供參考。