先来一点基础知识:
Service 是android的四大组件之一,与Activity同属于一个级别,它是运行在后台进行服务的组件(例如在后台播放的音乐,播放音乐的同时并不影响其他操作)。Service与Activity不同,Service没有界面。
Service虽然在后台运行,但是却与Activity一样运行在主程序中,因此不可在Service中进行耗时的操作。如果需要耗时操作的时候,可以开启子线程来操作。
Service的两种用法及其生命周期:
1.startService 开启服务
2.bindService 绑定服务
上图是这两种用法的生命周期图:
1、启动方式:onCreate()->onStartCommand()->onStop()->onDestroy()
2、绑定方式:onCreate()->onBind()->onUnBind()->onDestroy()
启动服务:一般从活动中调用 startService() ==> 服务调用 onCreate()(创建时只调用一次)==>onStartCommand() (可调用多次)
停止服务:一般从活动中调用 stopService() ==> 服务调用 onDestroy() (只调用一次) 或 直接在服务中调用stopSelf()来停止,如果有绑定服务,得先解绑,才能停止服务
使用方法一:启动服务
例子:服务与Activity的交互
1.在MainActivity中设置两个Button,分别启动服务和停止服务。
1 import android.content.Intent; 2 import android.os.Bundle; 3 import android.support.v7.app.ActionBarActivity; 4 import android.view.Menu; 5 import android.view.MenuItem; 6 import android.view.View; 7 8 public class MainActivity extends ActionBarActivity { 9 int number=38; 10 @Override 11 protected void onCreate(Bundle savedInstanceState) { 12 super.onCreate(savedInstanceState); 13 setContentView(R.layout.activity_main); 14 } 15 16 public void doButton(View v) { 17 Intent intent=new Intent(); 18 switch (v.getId()) { 19 case R.id.button1: 20 intent.setAction("com.robin.testservice2.action"); 21 intent.putExtra("number", number); 22 startService(intent);//启动服务 23 number++; 24 break; 25 26 case R.id.button2: 27 intent.setAction("com.robin.testservice2.action"); 28 stopService(intent);//停止服务 29 break; 30 default: 31 break; 32 } 33 } 34 }
2.建一个Service的子类----这是在执行每两秒cnt自动减1的操作,其代码如下:
1 import android.app.Service; 2 import android.content.Intent; 3 import android.media.MediaPlayer; 4 import android.os.IBinder; 5 import android.util.Log; 6 7 public class MyService extends Service{ 8 protected static final String TAG = "robin debug"; 9 MediaPlayer mp; 10 Thread printThread; 11 int cnt=-1; 12 boolean active=false; 13 @Override 14 public IBinder onBind(Intent intent) { 15 return null; 16 } 17 18 @Override 19 public void onCreate() { 20 Log.e(TAG,"service create"); 21 super.onCreate(); 22 } 23 24 @Override 25 public int onStartCommand(Intent intent, int flags, int startId) { 26 Log.e(TAG,"service start command"); 27 cnt=intent.getIntExtra("number", -1); 28 active=true; 29 printThread=new Thread(){ 30 @Override 31 public void run() { 32 while(active){ 33 cnt--; 34 try { 35 Thread.sleep(2000); 36 } catch (InterruptedException e) { 37 e.printStackTrace(); 38 } 39 Log.e(TAG,"progress value--------->"+cnt); 40 } 41 } 42 }; 43 printThread.start(); 44 return super.onStartCommand(intent, flags, startId); 45 } 46 47 @Override 48 public void onDestroy() { 49 active=false; 50 super.onDestroy(); 51 Log.e(TAG,"service destroy"); 52 } 53 }
布局文件
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" > 5 6 <TextView 7 android:id="@+id/textView1" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:text="@string/hello_world" /> 11 12 <Button 13 android:id="@+id/button1" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:layout_alignLeft="@+id/textView1" 17 android:layout_below="@+id/textView1" 18 android:layout_marginLeft="47dp" 19 android:layout_marginTop="24dp" 20 android:text="启动服务" 21 android:onClick="doButton"/> 22 23 <Button 24 android:id="@+id/button2" 25 android:layout_width="wrap_content" 26 android:layout_height="wrap_content" 27 android:layout_alignLeft="@+id/button1" 28 android:layout_below="@+id/button1" 29 android:layout_marginTop="60dp" 30 android:text="停止服务" 31 android:onClick="doButton"/> 32 33 </RelativeLayout>
以上的操作过程为,在Activity界面点击启动服务(startService(intent);)--->在MyService 中会执行
使用方法二:绑定服务
例子:Service与Activity之间进行通信
先来看看方法之间的调用顺序/过程:
上图中的代码:
ICount.java 类:
1 package com.robin.testservice3; 2 3 4 public interface ICount { //描述需要的行为(功能) 5 public int getCount(); 6 public void setCount(int cnt); 7 }
MainActivity.java
1 package com.robin.testservice3; 2 3 import android.content.ComponentName; 4 import android.content.Intent; 5 import android.content.ServiceConnection; 6 import android.os.Bundle; 7 import android.os.IBinder; 8 import android.support.v7.app.ActionBarActivity; 9 import android.view.Menu; 10 import android.view.MenuItem; 11 import android.view.View; 12 import android.widget.TextView; 13 14 public class MainActivity extends ActionBarActivity { 15 private ICount count; 16 private class MyConn implements ServiceConnection{ 17 18 @Override 19 public void onServiceConnected(ComponentName name, IBinder binder) { 20 count=(ICount) binder; 21 } 22 23 @Override 24 public void onServiceDisconnected(ComponentName name) { 25 count=null; 26 } 27 } 28 MyConn conn=new MyConn(); 29 TextView txt; 30 @Override 31 protected void onCreate(Bundle savedInstanceState) { 32 super.onCreate(savedInstanceState); 33 setContentView(R.layout.activity_main); 34 Intent service=new Intent("com.robin.testservice3.action"); 35 bindService(service, conn, BIND_AUTO_CREATE); 36 txt=(TextView)findViewById(R.id.result); 37 } 38 39 @Override 40 public boolean onCreateOptionsMenu(Menu menu) { 41 getMenuInflater().inflate(R.menu.main, menu); 42 return true; 43 } 44 45 @Override 46 public boolean onOptionsItemSelected(MenuItem item) { 47 int id = item.getItemId(); 48 if (id == R.id.action_settings) { 49 return true; 50 } 51 return super.onOptionsItemSelected(item); 52 } 53 54 public void doButton(View view ){ 55 switch (view.getId()) { 56 case R.id.button1: 57 txt.setText("来自service子线程的计数值:"+count.getCount()); 58 break; 59 case R.id.button2: 60 count.setCount(1000); 61 break; 62 default: 63 break; 64 } 65 } 66 @Override 67 protected void onDestroy() { 68 unbindService(conn); 69 super.onDestroy(); 70 } 71 }
MyService.java
1 package com.robin.testservice3; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.os.Binder; 6 import android.os.IBinder; 7 import android.util.Log; 8 9 public class MyService extends Service{ 10 protected static final String TAG = "robin debug"; 11 private boolean active=false; 12 private int cnt=0; 13 private class MyBinder extends Binder implements ICount{ 14 15 @Override 16 public int getCount() { 17 return cnt; 18 } 19 @Override 20 public void setCount(int cnt) { 21 MyService.this.cnt=cnt; 22 } 23 } 24 MyBinder binder=new MyBinder(); 25 26 @Override 27 public IBinder onBind(Intent intent) { 28 return binder; 29 } 30 31 @Override 32 public void onCreate() { 33 new Thread(new Runnable() { 34 35 @Override 36 public void run() { 37 active=true; 38 while(active){ 39 cnt++; 40 try { 41 Thread.sleep(2000); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 Log.e(TAG,"service thread :cnt----->"+cnt); 46 47 } 48 } 49 }).start(); 50 super.onCreate(); 51 } 52 @Override 53 public void onDestroy() { 54 Log.e(TAG,"service call onDestroy"); 55 active=false; 56 super.onDestroy(); 57 } 58 }
布局文件:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:id="@+id/LinearLayout1" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:orientation="vertical"> 7 8 <TextView 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:text="测试绑定使用service" /> 12 13 <Button 14 android:id="@+id/button1" 15 android:layout_width="wrap_content" 16 android:layout_height="wrap_content" 17 android:text="读service端子线程的计数值" 18 android:onClick="doButton"/> 19 20 <Button 21 android:id="@+id/button2" 22 android:layout_width="wrap_content" 23 android:layout_height="wrap_content" 24 android:text="修改service端子线程的计数值" 25 android:onClick="doButton"/> 26 27 <TextView 28 android:id="@+id/result" 29 android:layout_width="wrap_content" 30 android:layout_height="wrap_content" 31 android:text="TextView" /> 32 33 </LinearLayout>