一:service简介:
service是android的十大组件之一(Activity,ContentProvider,BroadCastReceivcr,Service),Service主要是负责在android的后台运行的, 检查位置信息等都是服务
二:service的启动方式和生命周期;
a) ,context.startService()的启动顺序
context.startService()-->onCreate()-->onStartCommand()-->服务运行-->context.stopService()-->onDestroy()-->服务销毁
程序是通过上下文启动的,启动的onCreate()和onDestroy()方法只执行一次,onStartCommand()可以多次启动 只需关闭一次
程序执行时,首先会检查该服务是否已经运行,如果运行,就直接调用onStartCommand(),否则就xian执行onCretae()-->onStartCommand();
b),绑定服务的启动顺序
context.bindservice()-->onCreate()-->onBind()-->服务绑定运行-->onUnbind()-->onDestroy()
绑定服务的启动 onBind()方法会返回一个Bind的实例,我们就直接可以在Activity中操作Service中的方法,所以我们一般都会使用绑定服务
c:service的生命周期
关键代码
package net.blogjava.mobile.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MyService extends Service { @Override//绑定返回的方法 public IBinder onBind(Intent intent) { return null; } @Override//创建服务的方法 public void onCreate() { Log.d("MyService", "onCreate"); super.onCreate(); } @Override//服务销毁的方法 public void onDestroy() { Log.d("MyService", "onDestroy"); super.onDestroy(); } @Override//服务启动的方法 public int onStartCommand(Intent intent, int flags, int startId) { Log.d("MyService", "onStart"); return super.onStartCommand(intent, flags, startId); } }
service的创建会经历三个阶段,也是一个从启动到销毁的过程,但是service的这个过程比Activity要简单的很多;
创建服务 onCretae();
启动服务onStartCommand();
销毁服务onDestory();
三:context.startService()的启动顺序的程序演示
1,创建xml文件
<Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView1" android:layout_below="@+id/textView1" android:onClick="controlclick" android:text="打开" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/button1" android:layout_alignBottom="@+id/button1" android:layout_marginLeft="55dp" android:layout_toRightOf="@+id/textView1" android:onClick="controlclick" android:text="关闭" />
2,Acvity界面 关键代码
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void controlclick(View v) { switch (v.getId()) { case R.id.button1: // 启动 intent = new Intent();//intent启动Srvice intent.setClass(MainActivity.this, Myservice.class);//清单注册 startService(intent);//启动 break; case R.id.button2: // 暂停 if (intent != null) { stopService(intent); } break; } }
3,服务类;
/** * * @author Administrator *服务 */ public class Myservice extends Service { private MediaPlayer player; @Override//绑定 public IBinder onBind(Intent intent) { return null; } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub return super.onUnbind(intent); } //@Override取消绑定 //public void unbindService(ServiceConnection conn) { // // TODO Auto-generated method stub // super.unbindService(conn); //} @Override//创建 public void onCreate() { // 创建多媒体 player = new MediaPlayer(); try { // 路径 player.setDataSource("mnt/sdcard2/kgmusic/download/陈洁仪 - 心动(live).mp3"); // 缓冲 player.prepare(); } catch (Exception e) { e.printStackTrace(); } super.onCreate(); } @Override//启动 public int onStartCommand(Intent intent, int flags, int startId) { // 播放 player.start(); return super.onStartCommand(intent, flags, startId); } @Override//销毁 public void onDestroy() { // 停止 player.stop(); // 清空缓存 player.release(); super.onDestroy(); } }
4,清单文件注册;
<service
android:name=".Myservice"></service>
四:绑定服务启动 --以音乐播放为例
public class MainActivity extends Activity { Boolean isplayer = false; Boolean islive=true; private myBind bind; // 服务返回的binder对象 private SeekBar seekbar; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获得进度条 seekbar=(SeekBar)this.findViewById(R.id.seekbar); //添加Seekbar的监听器 seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { public void onStopTrackingTouch(SeekBar seekBar) { int progress=seekBar.getProgress(); bind.setPlayer(progress); } public void onStartTrackingTouch(SeekBar seekBar) { //活动的时候停止播放 bind.puase(); } public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // TODO Auto-generated method stub } }); //使用handler线程更新数据 handler = new Handler(){ //重写handler线程的handleMessage方法 @Override public void handleMessage(Message msg) { if(msg.what==100){ //获得当前进度条和总进度条 int size= msg.arg1; int current=msg.arg2; seekbar.setMax(size);//设置进度条的最大长度 seekbar.setProgress(current);//设置长度条的当前长度 } } }; } @Override protected void onDestroy() { //解绑 this.unbindService(conn); islive=false; super.onDestroy(); } // 按钮的监听器 public void show(View v) { switch (v.getId()) { case R.id.imageButton1: // 上一首 break; case R.id.imageButton2: ImageButton btn = (ImageButton) v; if (!isplayer) {// 未播放 btn.setImageResource(android.R.drawable.ic_media_pause); isplayer = true; if (bind == null) { // 播放和暂停 // 使用Intent启动服务 Intent intent = new Intent(); intent.setClass(MainActivity.this, MusicSerivce.class); // 绑定服务 bindService(intent, conn, Context.BIND_AUTO_CREATE); } else { // 启动播放 bind.player(); } } else {// 播放过 btn.setImageResource(android.R.drawable.ic_media_play); isplayer = false; //暂停 bind.puase(); } break; case R.id.imageButton3: // 下一首 break; } } // 使用内部类操作连接 ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bind = (myBind) service; new myThread().start(); } @Override public void onServiceDisconnected(ComponentName name) { } }; //使用线程更新数据 class myThread extends Thread{ @Override public void run() { int size=0; while(islive){ //获得总进度 if(size==0) size= bind.getSize(); //获得当前的进度条 int current=bind.getCurrent(); //创建Message的对象 Message msg=handler.obtainMessage(); msg.what=100; msg.arg1=size; msg.arg2=current; //使用Handler发送Message对象的数据 handler.sendMessage(msg); try { Thread.sleep(100); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
服务类
public class MusicSerivce extends Service { private MediaPlayer player; private myBind binde; //使用构造方法初始化myBind对象 public MusicSerivce(){ binde = new myBind(); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return binde; } @Override public void onCreate() { super.onCreate(); // 创建播放流的类 player = new MediaPlayer(); // 获得播放的路径 try { // 设置数据 player.setDataSource("mnt/sdcard2/kgmusic/download/陈洁仪 - 心动(live).mp3"); // 设置缓冲 player.prepare(); player.start(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } //返回给Activity的类 class myBind extends Binder{ //播放 public void player(){ player.start(); } //暂停 public void puase(){ player.pause(); } //获得当前进度条 public int getCurrent(){ return player.getCurrentPosition(); } //获得总进度条 public int getSize(){ return player.getDuration(); } //设置播放位置 public void setPlayer(int i){ //seekTo();设置播放的时间 player.seekTo(i); player.start(); } } }
清单注册:
<service android:name="com.example.newer.music.MusicSerivce"></service>
权限;挂载和取消挂载权限,读取权限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
分析:
// 绑定服务
a,) bindService(intent, conn, Context.BIND_AUTO_CREATE);
由于ServiceConnection是一个接口,必须要实现这个接口;
// 使用内部类操作连接
ServiceConnection conn = new ServiceConnection() {
@Override//连接上服务
public void onServiceConnected(ComponentName name, IBinder service) {
bind = (myBind) service;
new myThread().start();
}
@Override//没有连接
public void onServiceDisconnected(ComponentName name) {
}
};
b),由于服务的onBind方法返回的是一个BInd所以也要实现这个接口:
//返回给Activity的类
class myBind extends Binder{
}
当服务将Bind返回时,Activity页面就可以操作Bind里面的方法
5,进程和声明
Android程序的生命周期是由Android系统控制和调度的
进程的优先级:前台进程 ,可见进程,服务进程, 后台进程,空进程
前台进程:需要显示给用户的信息,有一下存在 就不会消失
a 与用户正发生交互的。 b 它控制一个与用户交互的必须的基本的服务。 c 有一个正在调用生命周期的回调函数的service(如onCreate()、onStar()、onDestroy()) d 它有一个正在运行onReceive()方法的广播接收对象。
前台进程的优先级最高,几乎不会被杀死,只有当开启的前台进程非常多,Android内存资源出现不足的情况下,才会清除部分前台进程,保证主要的用户界面能够及时响应!
可见进程:
1)Activity不在前端显示,但也没有完全隐藏,能够看得到,但不与用户交互。比如弹出一个像对话框的Activity [API Demo中的例子]
2)如果一个进程包含一个服务,且这个服务正在被用户可见的Activity调用,此进程被视为可见进程
可见进程不会被杀死,除非为了保证前台进程的运行
服务进程:
包含已启动服务的进程
如:1)没有用户界面
<!--[if !supportLists]-->2)<!--[endif]-->在后台长期运行
服务进程只有在系统不能保证前台进程或可见进程运行所需要的资源的时候,才会强行清除!!
后台进程:
不包含任何已经启动的服务,且没有任何用户可见的Activity的进程
例如,打开浏览器后,直接按[主页键],这个时候浏览器进程变成一个后台进程
Android系统一般会存在较多的后台进程,在系统资源紧张的时候,系统会优先清除用户较长时间没有看见的后台进程!!
空进程:
1)空进程不包含任何活跃组件
2)空进程在系统资源紧张的时候会首先被清除
3)为了提高程序的启动速度,Android系统会保留部分空进程,在用户重新启动该程序的时候,空进程会被重新使用。
在浏览器打开输入数据后,然后关掉,下次再启动时,如何直接有数据
空进程存在的唯一理由就是保存程序的缓存数据,以提高程序启动的速度