2013-12-30 18:16:11
1. Service和Activty都是从Context里面派生出来的,因此都可以直接调用getResource(),getContentResolver()等方法。
2. 启动Service有两种方式:
2.1 startService():该方法启动Service,访问者和Service之间没有关联,一旦启动,即使访问者退出,Service依然运行;
2.2 bindService():该方法启动Service,访问者和Service绑定在一起,一旦访问者退出,Service随即退出。
3. onCreate()只会被调用一次,onStartCommand()方法每次Service被启动时都会被调用。
4. 绑定本地Service并与之通信:
4.1 当程序通过startService()、stopService()来启动、停止Service时,Service和访问者之间无法进行通信和数据交换。
4.2 如果要实现访问者和Service之间通信、交换数据,那么需要使用bindService()和unBindService()来启动、停止Service。
5. 程序实例:
先来一张图:
MyService.java
1 package com.example.localservice; 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 private int i; 11 private MyBinder myBinder; 12 13 // Define our own Binder class 14 public class MyBinder extends Binder { 15 // Any methods you can defined. 16 public int getValue() { 17 return i; 18 } 19 } 20 21 @Override 22 public void onCreate() { 23 // Something the service doing. 24 super.onCreate(); 25 myBinder = new MyBinder(); 26 new Thread() { 27 public void run() { 28 while (true) { 29 try { 30 Thread.sleep(1000); 31 } catch (InterruptedException e) { 32 e.printStackTrace(); 33 } 34 i++; 35 } 36 }; 37 }.start(); 38 } 39 40 // Return our own Binder object. 41 @Override 42 public IBinder onBind(Intent intent) { 43 return myBinder; 44 } 45 46 @Override 47 public boolean onUnbind(Intent intent) { 48 Log.d("David", "intent = " + intent); 49 return super.onUnbind(intent); 50 } 51 52 @Override 53 public void onDestroy() { 54 Log.d("David", "-------onDestroy!"); 55 super.onDestroy(); 56 } 57 58 }
MainActivity.java
1 package com.example.localservice; 2 3 import android.app.Activity; 4 import android.content.ComponentName; 5 import android.content.Intent; 6 import android.content.ServiceConnection; 7 import android.os.Bundle; 8 import android.os.IBinder; 9 import android.util.Log; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.widget.Button; 13 import android.widget.Toast; 14 15 import com.example.localservice.MyService.MyBinder; 16 17 public class MainActivity extends Activity { 18 private MyBinder myBinder; 19 private Button btnBindService; 20 private Button btnUnbindService; 21 private Button btnGetValue; 22 23 ServiceConnection connection = new ServiceConnection() { 24 25 // Two call-back methods. 26 @Override 27 public void onServiceDisconnected(ComponentName name) { 28 Log.d("David", "ServiceDisconnected!"); 29 } 30 31 @Override 32 public void onServiceConnected(ComponentName name, IBinder service) { 33 Log.d("David", "ServiceConnected!"); 34 myBinder = (MyBinder) service; 35 } 36 }; 37 38 @Override 39 protected void onCreate(Bundle savedInstanceState) { 40 super.onCreate(savedInstanceState); 41 setContentView(R.layout.activity_main); 42 btnBindService = (Button) findViewById(R.id.btn_bind_service); 43 btnUnbindService = (Button) findViewById(R.id.btn_unbind_service); 44 btnUnbindService.setEnabled(false); 45 btnGetValue = (Button) findViewById(R.id.btn_get_value); 46 btnGetValue.setEnabled(false); 47 btnBindService.setOnClickListener(new OnClickListener() { 48 49 @Override 50 public void onClick(View v) { 51 Intent intent = new Intent("android.intent.action.DAVID"); 52 bindService(intent, connection, BIND_AUTO_CREATE); // Bind service with connection. 53 Log.d("David", "Bind service!"); 54 btnUnbindService.setEnabled(true); 55 btnGetValue.setEnabled(true); 56 } 57 }); 58 59 btnUnbindService.setOnClickListener(new OnClickListener() { 60 61 @Override 62 public void onClick(View v) { 63 if (connection != null) { 64 // stopService(new Intent("android.intent.action.DAVID")); 65 unbindService(connection); 66 Log.d("David", "Unbind service!"); 67 } 68 } 69 }); 70 71 btnGetValue.setOnClickListener(new OnClickListener() { 72 73 @Override 74 public void onClick(View v) { 75 if (myBinder == null) { 76 Toast.makeText(MainActivity.this, 77 "Please bind service first!", Toast.LENGTH_LONG) 78 .show(); 79 return; 80 } 81 Log.d("David", "Got value = " + myBinder.getValue()); 82 } 83 }); 84 } 85 86 }
代码和操作很简单,看button title即可。源码下载
遇到一个问题:先Bind service,然后点击第三个button,发现可以取到值,此时点击第二个button,unbind service,再点击第三个button发现还是能取到值,这个还得在研究研究,当然了,有知道答案的言语一声。
6. Android的远程调用
Android的远程调用和Java的RMI类似,一样都是先定义一个远程调用接口,然后为该接口提供一个实现类即可。与RMI不同的是,客户端访问Service时,Android并不是直接返回Serivce对象给客户端,而是将一个回调对象IBinder通过onBind()方法返回给客户端。
7. 本地调用Serivce,onBind()方法返回的是IBinder对象,远程调用返回的是IBinder对象的代理。
程序实例:Server端
IServer.aidl
1 package com.example.serviceserver; 2 3 interface IServer{ 4 String getColor(); 5 }
ServiceServer.java
1 package com.example.serviceserver; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.os.IBinder; 6 import android.os.RemoteException; 7 8 public class ServiceServer extends Service { 9 private int i; 10 private StringBuffer sBuffer = new StringBuffer("ServiceServer"); 11 private MyBinder myBinder; 12 13 public class MyBinder extends IServer.Stub { 14 15 @Override 16 public String getColor() throws RemoteException { 17 return sBuffer.toString(); 18 } 19 20 } 21 22 @Override 23 public void onCreate() { 24 super.onCreate(); 25 myBinder = new MyBinder(); 26 new Thread() { 27 public void run() { 28 while (true) { 29 try { 30 Thread.sleep(1000); 31 } catch (InterruptedException e) { 32 e.printStackTrace(); 33 } 34 sBuffer.append(i + ""); 35 i++; 36 } 37 }; 38 }.start(); 39 } 40 41 @Override 42 public IBinder onBind(Intent intent) { 43 return myBinder; 44 } 45 }
Client端:
IServer.aidl
1 package com.example.serviceserver; 2 3 interface IServer{ 4 String getColor(); 5 }
MainActivity.java
1 package com.example.serviceclient; 2 3 import android.app.Activity; 4 import android.content.ComponentName; 5 import android.content.Intent; 6 import android.content.ServiceConnection; 7 import android.os.Bundle; 8 import android.os.IBinder; 9 import android.os.RemoteException; 10 import android.util.Log; 11 import android.view.View; 12 import android.view.View.OnClickListener; 13 import android.widget.Button; 14 import android.widget.Toast; 15 16 import com.example.serviceserver.IServer; 17 18 public class MainActivity extends Activity { 19 private IServer myBinder; 20 private Button btnBindService; 21 private Button btnUnbindService; 22 private Button btnGetValue; 23 24 ServiceConnection connection = new ServiceConnection() { 25 26 // Two call-back methods. 27 @Override 28 public void onServiceDisconnected(ComponentName name) { 29 Log.d("David", "ServiceDisconnected!"); 30 } 31 32 @Override 33 public void onServiceConnected(ComponentName name, IBinder service) { 34 Log.d("David", "ServiceConnected!"); 35 myBinder = IServer.Stub.asInterface(service); 36 } 37 }; 38 39 @Override 40 protected void onCreate(Bundle savedInstanceState) { 41 super.onCreate(savedInstanceState); 42 setContentView(R.layout.activity_main); 43 btnBindService = (Button) findViewById(R.id.btn_bind_service); 44 btnUnbindService = (Button) findViewById(R.id.btn_unbind_service); 45 btnUnbindService.setEnabled(false); 46 btnGetValue = (Button) findViewById(R.id.btn_get_value); 47 btnGetValue.setEnabled(false); 48 btnBindService.setOnClickListener(new OnClickListener() { 49 50 @Override 51 public void onClick(View v) { 52 Intent intent = new Intent("android.intent.action.main.DAVID"); 53 bindService(intent, connection, BIND_AUTO_CREATE); // Bind 54 Log.d("David", "Bind service!"); 55 btnUnbindService.setEnabled(true); 56 btnGetValue.setEnabled(true); 57 } 58 }); 59 60 btnUnbindService.setOnClickListener(new OnClickListener() { 61 62 @Override 63 public void onClick(View v) { 64 if (connection != null) { 65 // stopService(new Intent("android.intent.action.DAVID")); 66 unbindService(connection); 67 Log.d("David", "Unbind service!"); 68 } 69 } 70 }); 71 72 btnGetValue.setOnClickListener(new OnClickListener() { 73 74 @Override 75 public void onClick(View v) { 76 if (myBinder == null) { 77 Toast.makeText(MainActivity.this, 78 "Please bind service first!", Toast.LENGTH_LONG) 79 .show(); 80 return; 81 } 82 try { 83 Log.d("David", "Got value = " + myBinder.getColor()); 84 } catch (RemoteException e) { 85 e.printStackTrace(); 86 } 87 } 88 }); 89 } 90 91 }
还是这个问题:先Bind service,然后点击第三个button,发现可以取到值,此时点击第二个button,unbind service,再点击第三个button发现还是能取到值。有知道的同学欢迎拍砖。
源码下载
先运行SeriviceServer,然后再启动ServiceClient,比较简单,留做笔记吧,希望对同学们有帮助。