liaoxiang1987
2013-05-06 10:35
采纳率: 50%
浏览 3.8k

android 获取其他应用的背景音乐状态

首先,我自己在做一个关于音乐的插件。
其次,该插件的一个需求是在某一个条件下运行,然后弹出一些操作。而这种条件就是当有应用在跑时,如果有背景音乐在播放(play)状态,我不做某些操作。但如果背景音乐在暂停或停止状态(pause or stop),我这边就会做一些操作。

现在的情况是,我找了很多关于android音乐的处理,在底层服务层没有找到能获取到当前音乐播放状态的方式,只能获取到isActive,但这个状态在播放和暂停时都是返回true的。而上层情况是其他应用都是用mediaplay进行播放控制,而我作为另一个应用是获取不到别人应用的类对象的,所以这个问题陷入迷茫状态,希望做过或了解过这块的大神们能给出点方法,意见或思路哦。谢谢了,小弟快苦恼死了,搞了一个星期了

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • liaoxiang1987 2013-05-09 03:59
    已采纳

    研究两个星期,终于把这个问题进行了曲线救国,下面我来分享下自己的经验:

    思路:
    首先别人应用使用的播放方法是不同的,有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 大牛之作。
    本人也就是使用获取一下数据而已,并没多复杂处理,仅供参考。

    已采纳该答案
    打赏 评论
  • Jobernowl 2013-05-07 07:03

    你做这个好像很高级 虽然我不知道他是否正在听歌(你好像说可以检测到) 但是我可以知道他暂停的时机

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_HEADSET_PLUG);
        filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
        filter.addAction(Intent.ACTION_SHUTDOWN);
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        registerReceiver(br, filter);
    

    多数播放器会接受这些广播来决定是否暂停音乐播放或者继续播放 当然还有一个重要的广播 那就是线控 那个只能在xml中注册

    打赏 评论

相关推荐 更多相似问题