今天晚上把service的用法整理一下,service在Android中的地位仅次于activity,其重要性可见一斑。下面主要从四个部分分别讲解: 分别是startService,bindservice(两个基础用法。通过log查看生命周期)messenger和aidl(Android IPC机制主要也是通过service与binder来实现的) 编写activityInfo类来管理这四个测试的activity类,方便activity之间的跳转,简化代码
package com.example.servicetest; public class ActivityInfo { private String name; private Class clazz; public ActivityInfo(String name, Class clazz) { super(); this.name = name; this.clazz = clazz; } public String getName() { return name; } public Class getClazz() { return clazz; } public void setName(String name) { this.name = name; } public void setClazz(Class clazz) { this.clazz = clazz; } }测试主类 MainActivity代码:
package com.example.servicetest; import java.util.Arrays; import java.util.List; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; public class MainActivity extends Activity { private ListView mListView; private final List<ActivityInfo> mData = Arrays.asList(new ActivityInfo( "StartService", ActivityStartService.class), new ActivityInfo( "bindService", ActivityBindService.class), new ActivityInfo( "Menssenger", ActivityMessenger.class), new ActivityInfo("aidl", ActivityAidl.class)); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化view,个人的风格而已 initView(); } private void initView() { mListView = (ListView) findViewById(R.id.lv_activity_main); //为listview设置adapter mListView.setAdapter(new MyAdapter(this, mData)); mListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { Intent intent = new Intent(); //通过前面设计的activityInfo得到要跳转的activity的class intent.setClass(MainActivity.this, mData.get(arg2).getClazz()); startActivity(intent); } }); } }listView的adapter实现很简单,继承自baseAdapter,使用viewholder去优化listview,想必大家都了解。 (1)通过startService(Intent intent)的方式开启服务
package com.example.servicetest; 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 ActivityStartService extends Activity implements OnClickListener { private Button mButtonStart, mButtonStop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_layout); initView(); } private void initView() { mButtonStart = (Button) findViewById(R.id.btn_start_service); mButtonStop = (Button) findViewById(R.id.btn_stop_service); mButtonStart.setOnClickListener(this); mButtonStop.setOnClickListener(this); } @Override public void onClick(View arg0) { switch (arg0.getId()) { case R.id.btn_start_service: //开启service startService(new Intent(ActivityStartService.this, StartService.class)); break; //停止service case R.id.btn_stop_service: stopService(new Intent(ActivityStartService.this, StartService.class)); break; default: break; } } }service的实现:
package com.example.servicetest; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class StartService extends Service { private final String TAG = "StartService"; @Override public void onCreate() { Log.e(TAG, "-----oncreate----"); super.onCreate(); } @Override public void onDestroy() { Log.e(TAG, "-----onDestroy----"); super.onDestroy(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "----onStartCommand----"); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent arg0) { Log.e(TAG, "----onBind----"); return null; } @Override public void onRebind(Intent intent) { Log.e(TAG, "----onReBind----"); super.onRebind(intent); } @Override public boolean onUnbind(Intent intent) { Log.e(TAG, "----onUnbind----"); return super.onUnbind(intent); } }(2)bindService的启动过程,需要注意的是通过bindService启动service时,当service正常结束的时候,是不会调用onServiceDisconnected方法的,即使手动调用了unBindService()方法。
package com.example.servicetest; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; 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; public class ActivityBindService extends Activity implements OnClickListener { private Button mButtonBind, mButtonUnBind; private final String TAG = "ActivityBindService"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_layout); initView(); } private void initView() { mButtonBind = (Button) findViewById(R.id.btn_start_service); mButtonUnBind = (Button) findViewById(R.id.btn_stop_service); mButtonBind.setOnClickListener(this); mButtonUnBind.setOnClickListener(this); } @Override public void onClick(View arg0) { switch (arg0.getId()) { case R.id.btn_start_service: bindService( new Intent(ActivityBindService.this, StartService.class), mConnection, BIND_AUTO_CREATE); break; case R.id.btn_stop_service: unbindService(mConnection); break; default: break; } } private final ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName arg0) { Log.e(TAG, "----onServiceDisconnected----"); } @Override public void onServiceConnected(ComponentName arg0, IBinder arg1) { Log.e(TAG, "----onServiceConnected----"); } }; }(3)messenger使用service进行IPC通信: messenger主要是使用了Ibinder机制,其本质也是使用了aidl,但是他的好处是不用手工编写aidl文件,也不用理会aidl的生成过程。使用么三messege 和 Handler进行消息进行传递通信。因为handler是线程安全而且是一对一的通信,所以当Android IPC是一对一的时候,可以考虑使用messenger代替aidl去实现进程间通信
package com.example.servicetest; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.Handler.Callback; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class ActivityMessenger extends Activity implements OnClickListener { private final String TAG = "ActivityMessenger"; private Button mButton, mButton2; private Messenger iMessenger; private final Handler mHandler = new Handler(new Callback() { @Override public boolean handleMessage(Message arg0) { switch (arg0.what) { case RemoteService.MSG_FROM_CLIENT: String msg = arg0.getData().getString("rsp"); Log.e(TAG, msg); break; default: break; } return false; } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_layout); initView(); } private void initView() { mButton = (Button) findViewById(R.id.btn_start_service); mButton.setOnClickListener(this); mButton2 = (Button) findViewById(R.id.btn_stop_service); mButton2.setOnClickListener(this); } @Override public void onClick(View arg0) { switch (arg0.getId()) { case R.id.btn_start_service: bindService( new Intent(ActivityMessenger.this, RemoteService.class), mConnection, BIND_AUTO_CREATE); break; case R.id.btn_stop_service: unbindService(mConnection); break; default: break; } } private final ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName arg0) { Log.e(TAG, "----onServiceDisconnected----"); } @Override public void onServiceConnected(ComponentName arg0, IBinder arg1) { Log.e(TAG, "----onServiceConnected----"); //初始化messenger iMessenger = new Messenger(arg1); //设置message的类型 Message message = Message.obtain(null, RemoteService.MSG_FROM_CLIENT); Bundle bundle = new Bundle(); bundle.putString("msg", "msg from client"); message.setData(bundle); //这一句很重要,表明该消息的回复消息处理的handler为上面定义的mHandler。 message.replyTo = new Messenger(mHandler); try { iMessenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } } }; }下面看看RemoteService类:
package com.example.servicetest; import android.app.Service; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Handler.Callback; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; public class RemoteService extends Service { public static final int MSG_FROM_CLIENT = 0X0001; private final String TAG = "RemoteService"; private Messenger iMessenger; private final Handler mHandler = new Handler(new Callback() { @Override public boolean handleMessage(Message arg0) { switch (arg0.what) { case RemoteService.MSG_FROM_CLIENT: //获得服务进程传递过来的msg String msg = arg0.getData().getString("msg"); Log.e(TAG, msg); /** *注意前面设置过msg的replyTo为客户端定义的mHandler */ iMessenger = arg0.replyTo; Bundle bundle = new Bundle(); bundle.putString("rsp", "rsp from server"); Message message = Message.obtain(null, RemoteService.MSG_FROM_CLIENT); message.setData(bundle); try { iMessenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } break; default: break; } return false; } }); @Override public IBinder onBind(Intent arg0) { return new Messenger(mHandler).getBinder(); } }(4)最后就是aidl方式,aidl是处理Android进程间通信的,可以实现一对多的通信,下面通过一个相加求和的例子来讲解 下面是aidl文件,在两个app项目中,需要设置包名一模一样,会在gen包下生成对应的Java文件
package com.example.servicetest; /** *注意书写规范 *interface 没有 public private 的修饰 *方法也没有public private的修饰 */ interface AIDLSum{ double sum(double d1, double d2); } package com.example.servicetest; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class ActivityAidl extends Activity implements OnClickListener { private Button mButton; private final String TAG = "ActivityAidl"; private AIDLSum mAidlService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_layout); initView(); } private void initView() { mButton = (Button) findViewById(R.id.btn_start_service); mButton.setOnClickListener(this); } @Override public void onClick(View arg0) { switch (arg0.getId()) { case R.id.btn_start_service: bindService(new Intent(ActivityAidl.this, AIDLService.class), mConnection, BIND_AUTO_CREATE); break; default: break; } } private final ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName arg0) { } @Override public void onServiceConnected(ComponentName arg0, IBinder arg1) { Log.e(TAG, "----onServiceConnected----"); //asInterface函数可以在gen的aidl对应的java文件中查看 mAidlService = AIDLSum.Stub.asInterface(arg1); double sum; try { sum = mAidlService.sum(2.0, 5.0); Log.e(TAG, sum + ""); } catch (RemoteException e) { e.printStackTrace(); } } }; @Override protected void onDestroy() { super.onDestroy(); unbindService(mConnection); }; }最后看看AIDLService.java文件:
package com.example.servicetest; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class AIDLService extends Service { private final String TAG = "AIDLService"; @Override public IBinder onBind(Intent arg0) { Log.e(TAG, "----onBind----"); return stub; } //这里是处理逻辑的核心部分,就是实现了aidl中的interface中的接口函数 private final AIDLSum.Stub stub = new AIDLSum.Stub() { @Override public double sum(double d1, double d2) throws RemoteException { return d1 + d2; } }; }以上就是service的四种使用场景。希望有所帮助
————————————–向死而生——————————— 梅花香自苦寒来