绑定服务后台播放音频的简单示例

简介: 绑定服务后台播放音频的简单示例

1.服务


当应用程序不再位于前台且没有正在使用它的活动的时候,为了确保音频继续播放,我们需要创建一个服务。服务是安卓应用程序的一个组件,其用于在后台运行任务,而无须与用户交互。


2. 本地服务与远程服务


安卓中存在几个可用的不同服务类。本地服务(Local Service):作为特定应用程序的一部分存在,而且只能通过该应用程序访问和控制。远程服务(Remote Service):是另一种类型的服务,它们可以与其他应用程序进行通信,由其他应用程序访问和控制。在此,仅介绍使用一个本地服务提供音频播放的功能。


3.本地服务


服务类需要继承android.app.Service类。该类是抽象类,所以为了扩展它,必须实现onBind方法。

public IBinder onBind(Intent intent)
{
  // TODO Auto-generated method stub
  return msBinder;//*
}

通常如果只是实现简单服务,并不实现“绑定”的话,可以选择return null。

还有三个表示服务生命周期的方法,onCreate和onDestroy就不用说了,重点说说onStartCommand。每当利用一个匹配服务的意图调用startService时,就会调用onStartCommand方法,因此可能会多次调用它。onStartCommand方法将返回一个整数值,其表示如果结束该服务,那么操作系统应该如何执行操作。可以使用START_STICKY表明如果结束服务,那么将重新启动该服务。


public int onStartCommand(Intent intent, int flags, int startId)
  {
    // TODO Auto-generated method stub
    Log.v(TAG,"onStartCommand");
    if(!mediaPlayer.isPlaying())
    {
      mediaPlayer.start();
    }
    return START_STICKY;
    //return super.onStartCommand(intent, flags, startId);
  }

插一句:从android2.0中引入了onStartCommand方法,在此之前使用的是onStart方法。onStart方法的参数是一个意图和一个表示startId的整数。它不包括int类型的flags参数,而且没有返回值。如果目标电话在2.0之前运行,那么需要使用onStart方法。


注意,别忘了在清单文件中加入一个条目指定该服务。


下一步,我们还希望能够通过活动来控制服务中的MediaPlayer,而发出命令则显得更为复杂。为了控制MediaPlayer,需要利用bindService方法把该活动与服务绑定在一起(解绑定则使用unbindService)。一旦这样做了,由于活动与服务在相同的进程中运行,因此可以直接调用服务中的方法。如果正在创建一个远程服务,那么必须采取更深入一步的步骤。


                //启动音乐服务
    playMusicServiceIntent=new Intent(this,MusicService.class);
    startService(playMusicServiceIntent);
    //serviceConnection是一个ServiceConnection类型的对象,它是一个接口,用于监控所绑定服务的状态
    serviceConnection=new ServiceConnection()
    {
      @Override
      public void onServiceDisconnected(ComponentName name)
      {
        // TODO Auto-generated method stub
        musicService=null;
      }
      //注意该方法传入了一个IBinder对象,其实际上是由服务本身创建并提交的
      @Override
      public void onServiceConnected(ComponentName name, IBinder service)
      {
        // TODO Auto-generated method stub
        musicService=((MusicService.MusicServiceBinder)service).getService();
      }
    };
    //绑定服务时,需要传入intent和serviceConnection
    bindService(playMusicServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);

我们在服务类中创建了一个私有内部类,其继承自Binder类,在活动中请求连接服务时,用于返回服务本身

public class MusicServiceBinder extends Binder//*
   {
     MusicService getService()
     {
       return MusicService.this;
     }
   }

现在就搭好了基础,可以向服务中添加任何喜欢的功能,同时通过绑定服务,可以直接调用服务中定义的各种方法。如果不绑定服务的话,那么除了启动和停止服务之外,我们将不能做任何其他的事情。

完整代码示例:

活动中的代码:

//启动音乐服务
    playMusicServiceIntent=new Intent(this,MusicService.class);
    startService(playMusicServiceIntent);
    serviceConnection=new ServiceConnection()
    {
      @Override
      public void onServiceDisconnected(ComponentName name)
      {
        // TODO Auto-generated method stub
        musicService=null;
      }
      @Override
      public void onServiceConnected(ComponentName name, IBinder service)
      {
        // TODO Auto-generated method stub
        musicService=((MusicService.MusicServiceBinder)service).getService();
      }
    };
    //绑定服务
    bindService(playMusicServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
    //控制音乐服务的按钮
    Musicbtn=(Button) findViewById(R.id.musicOn);
    Musicbtn.setBackgroundResource(R.drawable.musicon);
    Musicbtn.setOnClickListener(new OnClickListener()
    {
      @Override
      public void onClick(View v)
      {
        // TODO Auto-generated method stub
        if(musicService.IsPlayNow())
        {
          Musicbtn.setBackgroundResource(R.drawable.musicoff);
          musicService.PauseMusic();
        }
        else
        {
          Musicbtn.setBackgroundResource(R.drawable.musicon);
          musicService.ResumeMusic();
        }
      }
    });

服务类代码:

public class MusicService extends Service implements OnCompletionListener
{
   static final String TAG="PLAYERSERVICE";
   MediaPlayer mediaPlayer;
   private final IBinder msBinder=new MusicServiceBinder();//*
   public class MusicServiceBinder extends Binder//*
   {
     MusicService getService()
     {
       return MusicService.this;
     }
   }
  @Override
  public void onCreate()
  {
    // TODO Auto-generated method stub
    //super.onCreate();
    Log.v(TAG,"onCreate");
    mediaPlayer=MediaPlayer.create(this,R.raw.music);
    mediaPlayer.setOnCompletionListener(this);
  }
  @Override
  public void onDestroy()
  {
    // TODO Auto-generated method stub
    if(mediaPlayer.isPlaying())
    {
      mediaPlayer.stop();
    }
    mediaPlayer.release();
    Log.v(TAG,"onDestroy");
    //super.onDestroy();
  }
  @Override
  public int onStartCommand(Intent intent, int flags, int startId)
  {
    // TODO Auto-generated method stub
    Log.v(TAG,"onStartCommand");
    if(!mediaPlayer.isPlaying())
    {
      mediaPlayer.start();
    }
    return START_STICKY;
    //return super.onStartCommand(intent, flags, startId);
  }
  @Override
  public IBinder onBind(Intent intent)
  {
    // TODO Auto-generated method stub
    return msBinder;//*
  }
  @Override
  public void onCompletion(MediaPlayer mediaPlayer)
  {
    // TODO Auto-generated method stub
    //stopSelf();
    mediaPlayer.start();
  }
  public void PauseMusic()
  {
    if(mediaPlayer.isPlaying())
    {
      mediaPlayer.pause();
    }
  }
  public void ResumeMusic()
  {
    if(!mediaPlayer.isPlaying())
    {
      mediaPlayer.start();
    }
  }
  public boolean IsPlayNow()
  {
    return mediaPlayer.isPlaying();
  }
}
目录
相关文章
|
安全 Ubuntu 算法
CVE-2014-0224:OpenSSL在Heartbleed之后再爆“CCS”新漏洞
重要的互联网基础工具OpenSSL在Heartbleed“心脏出血”漏洞发生不久后,于2014年6月5日再次修正了一个可以导致中间人攻击的新漏洞“CCS”(CVE-2014-0224)。
2575 0
CVE-2014-0224:OpenSSL在Heartbleed之后再爆“CCS”新漏洞
|
SQL 存储 分布式计算
Hive数据仓库设计与优化策略:面试经验与必备知识点解析
本文深入探讨了Hive数据仓库设计原则(分区、分桶、存储格式选择)与优化策略(SQL优化、内置优化器、统计信息、配置参数调整),并分享了面试经验及常见问题,如Hive与RDBMS的区别、实际项目应用和与其他组件的集成。通过代码样例,帮助读者掌握Hive核心技术,为面试做好充分准备。
1288 0
|
消息中间件 机器学习/深度学习 存储
字节跳动大数据开发面试题-附答案 (一)
此面试题来自牛客网友分享的字节跳动应届一面,面试时长一小时。 网友情况:985 本硕。
2200 0
字节跳动大数据开发面试题-附答案 (一)
|
11月前
|
人工智能 安全 大数据
企业内训|信创工作的技术难点与最佳实践-某央企金科公司
近日,TsingtaoAI组织信创技术专家,为上海某央企金融科技公司研发信创技术企业培训课程。课程通过系统化的理论学习与丰富的案例分析,全面解析信创政策、监管要求、行业趋势以及信创技术的核心难点。课程涵盖信创政策解读、行业信息洞察、业界技术栈分析、核心数据库信创改造、信创终端推广适配等多个模块。通过案例式、项目式和实战式的教学模式,帮助学员在复杂多变的信创环境中高效应对各种挑战。
541 3
|
数据可视化 数据挖掘 UED
Plotly交互式数据可视化
【10月更文挑战第12天】本文介绍了如何使用 Plotly 实现交互式数据可视化,涵盖从安装 Plotly 到数据准备、图表创建、添加交互功能、导出图表及自定义图表样式的全过程。通过具体示例,展示了如何创建和优化交互式折线图,提升数据分析的效率和趣味性。
505 60
|
芯片
【TI速成】半小时入门MSPM0G3507简明教程之按键定时器(二)
半小时入门MSPM0G3507简明教程之按键定时器
1235 0
|
缓存 网络协议 NoSQL
基于UDP的可靠性传输协议-KCP简介
基于UDP的可靠性传输协议-KCP简介
571 0
|
Linux Python
Linux离线安装Python依赖包
本文介绍了在Linux环境下离线安装Python依赖包的方法,包括从Python依赖包检索网站下载所需依赖包的压缩文件,上传到Linux服务器,然后通过解压、编译和安装步骤完成依赖包的安装。
1082 0
|
Java 测试技术
Java实现自动贩卖机/售货机
Java实现自动贩卖机/售货机
1370 0
Java实现自动贩卖机/售货机
|
传感器 Java API
基于JAVA的智能家居控制系统设计与实现
基于JAVA的智能家居控制系统设计与实现
625 0