Android培训之通过startService播放背景音乐简单示例
- 格式:doc
- 大小:80.00 KB
- 文档页数:11
Android使⽤Service实现简单⾳乐播放实例Service翻译成中⽂是服务,熟悉Windows 系统的同学⼀定很熟悉了。
Android⾥的Service跟Windows⾥的Service功能差不多,就是⼀个不可见的进程在后台执⾏。
Android中的服务,它与Activity不同,它是不能与⽤户交互的,不能⾃⼰启动的,运⾏在后台的程序,如果我们退出应⽤时,Service进程并没有结束,它仍然在后台运⾏,例如我们打开⼀个⾳乐播放器来听⾳乐,在听⾳乐的同时也想做下其它的事情,⽐如上⽹聊Q、或者上⽹浏览新闻之类的事情。
这样的话,我们就需要⽤到Service服务了。
下⾯我们以⼀个简单的⾳乐播放器的实例来说明下Service的⽣命周期和Service的使⽤。
下⾯是⾳乐播放器Demo的程序结构图:Android Service 的⽣命周期:Android中Service的⽣命周期并不是很复杂,只是继承了onCreate(), onStart(), onDestory()三个⽅法。
当我们第⼀次启动Service服务时,调⽤onCreate() --> onStart()两个⽅法,当停⽌Service服务时,调⽤onDestory()⽅法。
如果Service已经启动了,第⼆次再启动同⼀个服务时,就只是调⽤ onStart() 这个⽅法了。
Android Service 的使⽤:[1] 参照上⾯的程序结构图,我们可以创建⼀个Android程序,在src⽬录下创建⼀个Activity,⼀个继承⾃Service类的服务类;同时在资源⽂件夹res⽬录下创建⼀个raw的⽂件夹存放⾳频⽂件,如把music.mp3⾳乐⽂件放在该⽬录下。
该程序的主界⾯如下:[2] layout⽬录下的main.xml⽂件的源码:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android" android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="Welcome to Andy's blog!"android:textSize="16sp"/><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="⾳乐播放服务"/><Buttonandroid:id="@+id/startMusic"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="开启⾳乐播放服务"/><Buttonandroid:id="@+id/stopMusic"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="停⽌⾳乐播放服务"/><Buttonandroid:id="@+id/bindMusic"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="绑定⾳乐播放服务"/><Buttonandroid:id="@+id/unbindMusic"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="解除 ——绑定⾳乐播放服务"/></LinearLayout>[3] src⽬录下MusicService.java源码:package com.andyidea.service;import android.content.Intent;import android.media.MediaPlayer;import android.os.IBinder;import android.util.Log;import android.widget.Toast;public class MusicService extends Service {//为⽇志⼯具设置标签private static String TAG = "MusicService";//定义⾳乐播放器变量private MediaPlayer mPlayer;//该服务不存在需要被创建时被调⽤,不管startService()还是bindService()都会启动时调⽤该⽅法 @Overridepublic void onCreate() {Toast.makeText(this, "MusicSevice onCreate()", Toast.LENGTH_SHORT).show();Log.e(TAG, "MusicSerice onCreate()");mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.music);//设置可以重复播放mPlayer.setLooping(true);super.onCreate();}@Overridepublic void onStart(Intent intent, int startId) {Toast.makeText(this, "MusicSevice onStart()", Toast.LENGTH_SHORT).show();Log.e(TAG, "MusicSerice onStart()");mPlayer.start();super.onStart(intent, startId);}@Overridepublic void onDestroy() {Toast.makeText(this, "MusicSevice onDestroy()", Toast.LENGTH_SHORT).show();Log.e(TAG, "MusicSerice onDestroy()");mPlayer.stop();super.onDestroy();}//其他对象通过bindService ⽅法通知该Service时该⽅法被调⽤@Overridepublic IBinder onBind(Intent intent) {Toast.makeText(this, "MusicSevice onBind()", Toast.LENGTH_SHORT).show();Log.e(TAG, "MusicSerice onBind()");mPlayer.start();return null;}//其它对象通过unbindService⽅法通知该Service时该⽅法被调⽤@Overridepublic boolean onUnbind(Intent intent) {Toast.makeText(this, "MusicSevice onUnbind()", Toast.LENGTH_SHORT).show();Log.e(TAG, "MusicSerice onUnbind()");mPlayer.stop();return super.onUnbind(intent);}}[4] src⽬录下MusicServiceActivity源码:package com.andyidea.service;import android.app.Activity;import ponentName;import android.content.Context;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;public class MusicServiceActivity extends Activity {//为⽇志⼯具设置标签private static String TAG = "MusicService";/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.main);//输出Toast消息和⽇志记录Toast.makeText(this, "MusicServiceActivity",Toast.LENGTH_SHORT).show();Log.e(TAG, "MusicServiceActivity");initlizeViews();}private void initlizeViews(){Button btnStart = (Button)findViewById(R.id.startMusic);Button btnStop = (Button)findViewById(R.id.stopMusic);Button btnBind = (Button)findViewById(R.id.bindMusic);Button btnUnbind = (Button)findViewById(R.id.unbindMusic);//定义点击监听器OnClickListener ocl = new OnClickListener() {@Overridepublic void onClick(View v) {//显⽰指定 intent所指的对象是个 serviceIntent intent = new Intent(MusicServiceActivity.this,MusicService.class);switch(v.getId()){case R.id.startMusic://开始服务startService(intent);break;case R.id.stopMusic://停⽌服务stopService(intent);break;case R.id.bindMusic://绑定服务bindService(intent, conn, Context.BIND_AUTO_CREATE);break;case R.id.unbindMusic://解绑服务unbindService(conn);break;}}};//绑定点击监听btnStart.setOnClickListener(ocl);btnStop.setOnClickListener(ocl);btnBind.setOnClickListener(ocl);btnUnbind.setOnClickListener(ocl);}//定义服务链接对象final ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {Toast.makeText(MusicServiceActivity.this, "MusicServiceActivity onSeviceDisconnected" , Toast.LENGTH_SHORT).show();Log.e(TAG, "MusicServiceActivity onSeviceDisconnected");}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Toast.makeText(MusicServiceActivity.this, "MusicServiceActivity onServiceConnected",Toast.LENGTH_SHORT).show();Log.e(TAG, "MusicServiceActivity onServiceConnected");}};}[5] 最后,我们别忘了在AndroidManifest.xml配置⽂件中添加对Service的注册。
Android 中服务的调用案例-音乐播放器一、需求通过该案例,我们可以更加直观地感受 Bound Service 的使用方法。
在后台(Service )运行播放音乐服务,在界面(Activity )控制音乐播放器。
音乐播放器原型图如图 1-7所示。
因为要播放音乐,因此需要提前准备一个音频文件,然后我把该文件放到 res 下的 raw 目录下,注意,raw 目录需要我们手动创建,该文件名字必须为 raw ,这是约定好的,如图 1-8 所示。
图 1-7音乐播放中界面图 1-8创建 raw 目录二、布局布局很简单,如下所示。
【文件 1-6】activity_main.xml1.<LinearLayout xmlns:android="/apk/res/android" 2. xmlns:tools="/tools" 3. android:layout_width="match_parent" 4. android:layout_height="match_parent" 5. android:orientation="vertical"6.tools:context=".MainActivity" >247.8.<TextView9.android:layout_width="wrap_content"10.android:layout_height="wrap_content"11.android:layout_gravity="center_horizontal"12.android:text="音乐播放器"13.android:textColor="#ff0000"14.android:textSize="28sp" />15.16.<LinearLayout17.android:layout_width="match_parent"18.android:layout_height="wrap_content"19.android:orientation="horizontal">20.21.<Button22.android:id="@+id/bt_play"23.android:layout_width="0dp"24.android:layout_height="wrap_content"25.android:layout_weight="1"26.android:onClick="play"27.android:text="播放" />28.29.<Button30.android:id="@+id/bt_pause"31.android:layout_width="0dp"32.android:layout_height="wrap_content"33.android:layout_weight="1"34.android:onClick="pause"35.android:text="暂停" />36.37.<Button38.android:id="@+id/bt_stop"39.android:layout_width="0dp"40.android:layout_height="wrap_content"41.android:layout_weight="1"42.android:onClick="stop"43.android:text="停止" />44.</LinearLayout>45.<ProgressBar46.android:layout_width="match_parent"47.android:layout_height="wrap_content"48.style="?android:attr/progressBarStyleHorizontal"49.android:id="@+id/pb"50./>51.</LinearLayout>25三、代码在该案例中使用到了两个类,一个是自定义的Service,用于播放音乐。
广州xx 学院Android 程序设计 实验报告专业班级 计算机181 实验日期__ 2021.5.18_ _ 姓 名 xx 学 号201xx 实验名称 Service 编程 指导老师__ xx _(报告内容包括:实验目的、实验设备及器材、实验步骤、实验数据、图表及曲线处理、实验小结等)。
1. 实验目的(1) 了解如何创建服务;(2) 掌握服务的两种启动方式;(3) 掌握如何使用本地服务通信。
2. 实验要求(1) 使用服务通信,实现音乐播放器功能,实现音乐的播放、暂停、继续播放、退出。
3. 实验步骤(1)导入音乐文件和界面图片之后,开始创建布局,代码如下,效果图如图1-1所示。
<ImageViewandroid :id ="@+id/iv_music"android :layout_width ="240dp"android :layout_height ="240dp"android :layout_gravity ="center_horizontal" android :layout_margin ="15dp"android :src ="@drawable/music"/><SeekBarandroid :id ="@+id/sb"android :layout_width ="match_parent"android :layout_height ="wrap_content" /><RelativeLayoutandroid :layout_width ="match_parent"android :layout_height ="wrap_content"android:paddingLeft="8dp"android:paddingRight="8dp"><TextViewandroid:id="@+id/tv_progress"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="00:00" /><TextViewandroid:id="@+id/tv_total"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:text="00:00" /></RelativeLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/btn_play"android:layout_width="0dp"android:layout_height="40dp"android:layout_margin="8dp"android:layout_weight="1"android:background="@drawable/btn_bg_selector"android:text="播放音乐" /><Buttonandroid:id="@+id/btn_pause"android:layout_width="0dp"android:layout_height="40dp"android:layout_margin="8dp"android:layout_weight="1"android:background="@drawable/btn_bg_selector"android:text="暂停播放" /><Buttonandroid:id="@+id/btn_continue_play"android:layout_width="0dp"android:layout_height="40dp"android:layout_margin="8dp"android:layout_weight="1"android:background="@drawable/btn_bg_selector"android:text="继续播放" /><Buttonandroid:id="@+id/btn_exit"android:layout_width="0dp"android:layout_height="40dp"android:layout_margin="8dp"android:layout_weight="1"android:background="@drawable/btn_bg_selector"android:text="退出" /></LinearLayout>图1-1 界面布局效果图(2)创建背景选择器btn_bg_selector.xml关键代码如下:<selector xmlns:android="/apk/res/android"><item android:state_pressed="true" ><shape android:shape="rectangle"><corners android:radius="3dp"/><solid android:color="#d4d4d4"/></shape></item><item android:state_pressed="false" ><shape android:shape="rectangle"><corners android:radius="3dp"/><solid android:color="#ffffff" /></shape></item></selector>(3)创建MusicService服务关键代码如下所示:public class MusicService extends Service {private MediaPlayer player;private Timer timer;public MusicService() {}@Overridepublic IBinder onBind(Intent intent) {return new MusicControl();}@Overridepublic void onCreate() {super.onCreate();player = new MediaPlayer();//创建音乐播放器对象}public void addTimer() { //添加计时器用于设置音乐播放器中的播放进度条if (timer == null) {timer = new Timer(); //创建计时器对象TimerTask task = new TimerTask() {@Overridepublic void run() {if (player == null) return;int duration = player.getDuration(); //获取歌曲总时长int currentPosition = player.getCurrentPosition();//获取播放进度Message msg = MainActivity.handler.obtainMessage();//创建消息对象//将音乐的总时长和播放进度封装至消息对象中Bundle bundle = new Bundle();bundle.putInt("duration", duration);bundle.putInt("currentPosition", currentPosition);msg.setData(bundle);//将消息发送到主线程的消息队列MainActivity.handler.sendMessage(msg);}};//开始计时任务后的5毫秒,第一次执行task任务,以后每500毫秒执行一次timer.schedule(task, 5, 500);}}class MusicControl extends Binder {public void play() {try {player.reset();//重置音乐播放器//加载多媒体文件player = MediaPlayer.create(getApplicationContext(),R.raw.music);player.start();//播放音乐addTimer(); //添加计时器} catch (Exception e) {e.printStackTrace();}}public void pausePlay() {player.pause(); //暂停播放音乐}public void continuePlay() {player.start(); //继续播放音乐}public void seekTo(int progress) {player.seekTo(progress);//设置音乐的播放位置}}@Overridepublic void onDestroy() {super.onDestroy();if (player == null) return;if (player.isPlaying()) player.stop();//停止播放音乐player.release(); //释放占用的资源player = null; //将player置为空}}(4)编写界面交互代码关键代码如下:public class MainActivity extends AppCompatActivity implementsView.OnClickListener{private static SeekBar sb;private static TextView tv_progress, tv_total;private ObjectAnimator animator;private MusicService.MusicControl musicControl;MyServiceConn conn;Intent intent;private boolean isUnbind = false;//记录服务是否被解绑@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);init();}private void init() {tv_progress = (TextView) findViewById(_progress);tv_total = (TextView) findViewById(_total);sb = (SeekBar) findViewById(R.id.sb);findViewById(R.id.btn_play).setOnClickListener(this);findViewById(R.id.btn_pause).setOnClickListener(this);findViewById(R.id.btn_continue_play).setOnClickListener(this);findViewById(R.id.btn_exit).setOnClickListener(this);intent = new Intent(this, MusicService.class);//创建意图对象conn = new MyServiceConn();//创建服务连接对象bindService(intent, conn, BIND_AUTO_CREATE); //绑定服务//为滑动条添加事件监听sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, booleanfromUser) { //滑动条进度改变时,会调用此方法if (progress == seekBar.getMax()) { //当滑动条滑到末端时,结束动画animator.pause(); //停止播放动画}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {//滑动条开始滑动时调用}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) { //滑动条停止滑动时调用//根据拖动的进度改变音乐播放进度int progress = seekBar.getProgress();//获取seekBar的进度musicControl.seekTo(progress); //改变播放进度}});ImageView iv_music = (ImageView) findViewById(R.id.iv_music);animator = ObjectAnimator.ofFloat(iv_music, "rotation", 0f, 360.0f);animator.setDuration(10000); //动画旋转一周的时间为10秒animator.setInterpolator(new LinearInterpolator());animator.setRepeatCount(-1); //-1表示设置动画无限循环}4.运行结果开始播放如图4-1所示图4-15.实验小结通过此次实验,让我了解到了Android中的服务创建,比如下载文件、播放音乐等功能,其中让我学到了一个背景选择器,可以通过这个选择器动态呈现按钮的背景颜色。
MainActivity.java类package com.example.xservice;import android.os.Bundle;import android.app.Activity;import android.content.Intent;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MainActivity extends Activity {private Button btn1,btn2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);btn1=(Button)findViewById(R.id.btn1);btn2=(Button)findViewById(R.id.btn2);btn1.setOnClickListener(listener);btn2.setOnClickListener(listener);}private OnClickListener listener=new OnClickListener() {@Overridepublic void onClick(View v) {Intent intent=new Intent(MainActivity.this,Myservice.class); //启动服务要先传递一个intentswitch (v.getId()) {case R.id.btn1:startService(intent);//启动服务break;case R.id.btn2:stopService(intent);//终止服务break;default:break;}}};@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);return true;}}Myservice.java类package com.example.xservice;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.util.Log;//服务要在AndroidManifest。
Android多媒体功能是开发音乐播放器应用的核心。
本文将从如何选择适当的媒体功能开始,讨论如何实现音乐播放、音乐列表和音乐控制等功能。
1. 选择适当的媒体功能在开发音乐播放器应用之前,首先要选择适合项目需求的媒体功能库。
Android提供了多种媒体库,如MediaPlayer、ExoPlayer和远程媒体库等。
根据项目需求,选择支持音频格式、媒体管理和功能扩展的媒体库。
2. 音乐播放功能的实现音乐播放是音乐播放器应用的核心功能。
在Android中,可以使用MediaPlayer或ExoPlayer来实现音乐播放。
首先,初始化MediaPlayer或ExoPlayer,并设置音乐文件的路径。
然后,通过调用start()方法开始播放音乐。
3. 音乐列表的展示与管理为了更好地管理和展示音乐列表,可以使用RecyclerView来实现。
首先,创建一个音乐列表的数据集合,并绑定到RecyclerView适配器。
接着,自定义RecyclerView的布局,可以添加音乐的封面、标题和艺术家等信息。
最后,通过点击音乐列表中的项,获取选中的音乐文件路径,并切换到对应的音乐播放。
4. 音乐控制功能的实现音乐控制是为了方便用户播放、停止、暂停和调整音乐播放进度等操作。
通过使用MediaSession和MediaController类,可以实现这些功能。
首先,创建一个MediaSession实例,并设置相关的回调方法,如onPlay、onPause、onStop和onSeek等。
然后,创建一个MediaController实例,将其与MediaSession进行绑定。
最后,通过MediaController可以方便地控制音乐播放器的各种操作。
5. 音乐播放器界面设计良好的用户界面设计可以提升用户体验。
在音乐播放器应用中,可以使用ViewPager和Fragment来实现多个界面的切换。
可以包括音乐播放界面、音乐列表界面和设置界面等。
AndroidStudio实现⾳乐播放器Androidstudio⾳乐播放器,供⼤家参考,具体内容如下实现⽬的:利⽤⼴播在myapplication中原本button点我暂停按钮是灰⾊⽆法点击的,此时发送⼀条短信给⾃⼰的安卓⼿机,按钮变成⿊⾊,⾳乐开始播放,此时点击点我暂停按钮,⾳乐停⽌。
结果截图:发送短信给⾃⼰后:,点我暂停按钮变成⿊⾊,并开始播放⾳乐:此时点击点我暂停按钮,⾳乐暂停⼴播Android 应⽤与 Android 系统和其他 Android 应⽤之间可以相互收发⼴播消息,这与发布-订阅设计模式相似。
这些⼴播会在所关注的事件发⽣时发送。
举例来说,Android 系统会在发⽣各种系统事件时发送⼴播,例如系统启动或设备开始充电时。
再⽐如,应⽤可以发送⾃定义⼴播来通知其他应⽤它们可能感兴趣的事件(例如,⼀些新数据已下载)。
⼴播消息本⾝会被封装在⼀个Intent对象中,该对象的操作字符串会标识所发⽣的事件(例如android.intent.action.AIRPLANE_MODE )。
该 Intent 可能还包含绑定到其 extra 字段中的附加信息。
例如,飞⾏模式 intent 包含布尔值 extra 来指⽰是否已开启飞⾏模式。
xml⽂件<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/loading"><Buttonandroid:text="BUTTON"android:layout_marginTop="@android:dimen/app_icon_size"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:onClick="send"/></LinearLayout>mainactivity.java⽂件package com.example.myapplication;import androidx.annotation.NonNull;import androidx.appcompat.app.AppCompatActivity;import androidx.core.app.ActivityCompat;import androidx.core.content.ContextCompat;import android.Manifest;import android.content.Intent;import android.content.pm.PackageManager;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.Toast;public class MainActivity extends AppCompatActivity {private Button btnStop;private boolean isCast; //是否为⼴播激活@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(this,new String[]{"android.permission.RECEIVE_SMS"},1);}btnStop=findViewById(R.id.btnStop);Intent intent = getIntent(); //获取⼴播意图对象isCast = intent.getBooleanExtra("iscast", false); //默认值为falsebtnStop.setEnabled(isCast); //设置停⽌按钮可⽤和单击监听if(isCast) Toast.makeText(this, "正在播放⾳乐...", Toast.LENGTH_SHORT).show();btnStop.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v){//显式服务调⽤意图(⾮绑定式)Intent intent=new Intent(MainActivity.this, MyAudioService.class);//在Activity组件⾥,停⽌⾳乐播放服务stopService(intent);isCast=false;btnStop.setEnabled(isCast);// finish(); //销毁本活动}});}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode){case 1:if(grantResults[0]!=PackageManager.PERMISSION_GRANTED){Toast.makeText(this, "未授权,⽆法实现预定的功能!", Toast.LENGTH_SHORT).show();finish();}else{Toast.makeText(this, "请发⼀条短信验证...", Toast.LENGTH_SHORT).show();}}}}SmsReceiver.java⽂件编写⼴播接收者程序package com.example.myapplication;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;/*本⼴播接收者程序分别调⽤了应⽤的主Activity程序和播放⾳乐的服务程序*/public class SmsReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Intent serviceIntent = new Intent(context, MyAudioService.class);//在⼴播组件⾥,通过上下⽂对象启动⾳乐播放服务组件context.startService(serviceIntent);//新建调⽤Activity组件的意图Intent activityIntent = new Intent(context, MainActivity.class);activityIntent.putExtra("iscast", true); //携带数据//新建栈⽤来存放被启动的Activity(当已经存在时,只做移动处理)activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//在⼴播组件⾥,通过上下⽂对象启动Activity组件context.startActivity(activityIntent);}}MyAudioService.java⽂件package com.example.myapplication;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.os.IBinder;public class MyAudioService extends Service {MediaPlayer mediaPlayer;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {mediaPlayer = MediaPlayer.create(this, R.raw.liyue);//创建⾳乐服务。
Android使用Service播放音乐res/layout/main.xmlMusicService.javapackage com.zeph.android.service;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.os.IBinder;public class MusicService extends Service { private MediaPlayer mMediaPlayer;@Overridepublic IBinder onBind(Intent arg0) {return null;}@Overridepublic void onCreate() {super.onCreate();mMediaPlayer = MediaPlayer.create(this, R.raw.music01); }@Overridepublic void onDestroy() {super.onDestroy();mMediaPlayer.stop();mMediaPlayer.release();}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);int operate = intent.getIntExtra("operate", 3);switch (operate) {case 0:if (!mMediaPlayer.isPlaying()) {mMediaPlayer.start();}break;case 1:if (mMediaPlayer.isPlaying()) {mMediaPlayer.pause();}break;case 2:if (mMediaPlayer.isPlaying()) {mMediaPlayer.stop();mMediaPlayer = MediaPlayer.create(this, R.raw.music01);}break;default:break;}}}ServiceTestActivity.javapackage com.zeph.android.service;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class ServiceTestActivity extends Activity {private Button playButton;private Button pauseButton;private Button stopButton;private Button stopService;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.main);playButton = (Button) findViewById(R.id.playButton); pauseButton = (Button) findViewById(R.id.pauseButton); stopButton = (Button) findViewById(R.id.stopButton); stopService = (Button) findViewById(R.id.stopService);playButton.setOnClickListener(newButtonOnClickListener());pauseButton.setOnClickListener(new ButtonOnClickListener());stopButton.setOnClickListener(new ButtonOnClickListener());stopService.setOnClickListener(new ButtonOnClickListener());}public class ButtonOnClickListener implements OnClickListener {@Overridepublic void onClick(View view) {Intent intent = new Intent();intent.setClass(getApplicationContext(), MusicService.class);if (view == playButton) {intent.putExtra("operate", 0);startService(intent);} else if (view == pauseButton) {intent.putExtra("operate", 1);startService(intent);} else if (view == stopButton) {intent.putExtra("operate", 2); startService(intent);} else if (view == stopService) { stopService(intent);}}}}。
Android应用开发从入门到精通140图6.3 服务的生命周期方法的调用情况6.3 服务的启动Service的启动有两种方式,context.startService()和context.bindService(),能启动service的组件有Activity、service、content provide,根据启动方式的不同将其分为以下两类。
(1)采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。
如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。
采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
(2)采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。
这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。
如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会多次被调用)。
如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。
不同的启动方式,对于Service的onCreate的方法只会被调用一次,如果先调用的是bindService()方法,那么startService()的时候就直接运行Service的onStart()方法,如果先调用的是startService(),那么bindService()的时候就直接运行onBind()方法。
Android应用开发--MP3简单音乐播放器点击列表会进入播放的Activity,在这个Activity会接收到从前面的Activity传来的数据,在通过这些数据来启动服务来播放音乐,整个过程很简单,需要注意的是我们要接收的数据是哪些内容,还有我们向Service要传什么样的数据,这是根据自己的开发思路和需求来决定的,等一下你们会看到小鬼到底往Service传了些什么东西,然而这些数据到底起什么作用,需要慢慢去体会,因为这是需要一点一点去调试的。
好了,下面贴一下整个Activity的实现代码,主要是播放的各种状态的实现,因为这个音乐播放器并没有完全开发完,所以朋友们需要弄清楚这一点。
如果对代码的实现有不清楚的,可以给小鬼留言,小鬼有空一定给大家解答。
效果如下:代码如下:package com.anjovo.as.chapter10.exam01。
import java.io.IOException。
import android.media.AudioManager。
import android.media.MediaPlayer。
import .Uri。
import android.os.Bundle。
import android.app.Activity。
import android.content.Intent。
import android.view.ContextMenu。
import android.view.ContextMenu.ContextMenuInfo。
import android.view.Menu。
import android.view.MenuItem。
import android.view.SubMenu。
import android.view.View。
import android.widget.Button。
import android.widget.ImageView。
北京尚学堂提供关于startService的基本使用概述及其生命周期可参见博客《Android中startService的使用及Service生命周期》。
本文通过播放背景音乐的简单示例,演示startService的基本使用流程。
系统界面如下:界面上面就两个按钮,”播放音乐并退出Activity” 和“停止播放音乐”。
我们在该示例中,通过操纵Activity的按钮控制MusicService播放或停止播放音乐。
我将一个名为music.mp3的放到资源目录/res/raw文件夹下面,这样我们在程序中就可以通过R.raw.music引用该音乐文件,放入/res/raw文件夹中的资源文件会保持原来的面貌不会被编译成二进制。
MusicService是用于播放背景音乐的Service,其代码如下所示:package com.ispring.startservicedemo;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.os.IBinder;import android.widget.Toast;import java.io.IOException;public class MusicService extends Service {private MediaPlayer mediaPlayer = null;private boolean isReady = false;@Overridepublic void onCreate() {//onCreate在Service的生命周期中只会调用一次super.onCreate();//初始化媒体播放器mediaPlayer = MediaPlayer.create(this, R.raw.musi c);if(mediaPlayer == null){return;}mediaPlayer.stop();mediaPlayer.setOnErrorListener(new MediaPlayer.OnEr rorListener() {@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {mp.release();stopSelf();return false;}});try{mediaPlayer.prepare();isReady = true;} catch (IOException e) {e.printStackTrace();isReady = false;}if(isReady){//将背景音乐设置为循环播放mediaPlayer.setLooping(true);}}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {//每次调用Context的startService都会触发onStartComman d回调方法//所以onStartCommand在Service的生命周期中可能会被调用多次if(isReady && !mediaPlayer.isPlaying()){//播放背景音乐mediaPlayer.start();Toast.makeText(this, "开始播放背景音乐", Toast.LEN GTH_LONG).show();}return START_STICKY;}@Overridepublic IBinder onBind(Intent intent) {//该Service中不支持bindService方法,所以此处直接返回nu llreturn null;}@Overridepublic void onDestroy() {//当调用Context的stopService或Service内部执行stopSe lf方法时就会触发onDestroy回调方法super.onDestroy();if(mediaPlayer != null){if(mediaPlayer.isPlaying()){//停止播放音乐mediaPlayer.stop();}//释放媒体播放器资源mediaPlayer.release();Toast.makeText(this, "停止播放背景音乐", Toast.LEN GTH_LONG).show();}}}MusicActivity的代码如下所示:package com.ispring.startservicedemo;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;public class MusicActivity extends Activity implements But ton.OnClickListener {@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(yout.activity_music);}@Overridepublic void onClick(View v) {if(v.getId() == R.id.btnStart){//播放背景音乐Intent intent = new Intent(this, MusicService.cl ass);startService(intent);//退出当前Activitythis.finish();}else if(v.getId() == R.id.btnStop){//停止播放音乐Intent intent = new Intent(this, MusicService.cl ass);stopService(intent);}}}当我们单击了按钮”播放音乐并退出Activity”之后,我们首先通过Activity的startService启动MusicService,然后我们立即调用了Activity的finish方法销毁了当前的Activity。
可能大家会问为什么要销毁当前的Activity?我们此处之所以调用Activity的finish方法不是从功能的角度出发的,而是从理解代码运行的角度故意这么写的: 执行完Activity的finish 方法之后,当前的Activity就销毁了,在界面上看起来就是当前UI消失了,应用程序退出了,但稍等片刻你会听到背景音乐响起。
这从侧面印证了Service的一个特性: Service与Activity等一样,也是一种基本的应用程序组件,Service 无需依赖任何的Activity便可独自在没有任何UI界面的情况下悠闲地在Android后台默默运行。
调用了startService之后,Android Framework接收到了intent信息,第一次会先创建MusicService的实例,执行MusicService 的onCreate回调方法,onCreate在Service的生命周期中只会调用一次,我们在其onCreate方法中将R.raw.music初始化为媒体播放器,并调用媒体播放器的prepare方法。
然后我们将播放器设置为循环播放状态。
需要注意的是,在实际生产环境中,我们应该注册播放器的setOnPreparedListener并调用prepareAsync()方法,为了简化代码起见,我们只调用了播放器的同步方法prepare()。
调用了onCreate方法后,Android会自动回调其onStartCommand方法,其实每次调用Context的startService都会触发onStartCommand回调方法,所以onStartCommand在Service的生命周期中可能会被调用多次。
所以我们在MusicService 的onStartCommand中做了判断,判断播放器是否是在播放中,如果当前播放器没有播放我们才调用播放器的start方法播放背景音乐。
当我们单击了按钮”播放音乐并退出Activity”之后,MusicService启动起来,播放背景音乐,但是Activity却销毁了,程序的UI界面不见了。
为了能够停止播放背景音乐,我们需要再次单击应用程序图标,重新打开MusicActivity,然后单击界面上的”停止播放音乐”按钮,此时我们会调用Activity的stopService方法,Android Framework接收到要停止服务的intent之后会回调MusicService的onDestroy方法,在该方法中我们停止播放音乐并释放媒体播放器资源。
本文只是通过播放背景音乐这一简单示例演示通过startService启动Service基本使用流程,代码没有进行优化,希望对大家学习Service有所帮助。
出版:北京尚学堂网址:QQ群:516745661。