【Android学习笔记】再探Android(安卓)Service
16lz
2021-12-04
引言:初学Android的时候,对Service是草草了之,现在反过来复习,才发现自己有很多知识没有掌握,在这里总结一下。Service是Android的四大组件之一,是Android中实现程序后台运行最合适的解决方案之一,非常适合被用于去执行那些不需要和用户界面交互而且要求长期运行的任务。
1、创建一个Service
- 服务中常用的几个方法分别是onCreate()、onStartCommand()、onDestroy()
public class MyService extends Service { @Override public IBinder onBind(Intent intent) { return null; } //每次服务启动时都会调用 @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } //在服务第一次创建的时候调用,放只需要执行一次的代码 @Override public void onCreate() { super.onCreate(); } //服务销毁的时候调用 @Override public void onDestroy() { super.onDestroy(); }}
- 在AndroidManifest.xml注册Service
<service android:name=".MyService" android:enabled="true" android:exported="true"></service>
2、启动和停止Service
//启动服务@Overridepublic void onClick(View v) { startService(new Intent(MainActivity.this, MyService.class));}//停止服务 @Overridepublic void onClick(View v) { stopService(new Intent(MainActivity.this,MyService.class));}
3、绑定Service
- 注意:startService()、stopService()和bindService()、unbindService()是成对出现的方法,startService()后,执行stopService()即可停止服务,bindService()后,执行unbindService()也可接除与服务的绑定;但是如果startService()后,接着调用bindService(),想要停止服务,必须先执行stopService(),再调用unbindService()。
@Overridepublic void onClick(View v) { bindService(new Intent(MainActivity.this,MyService.class), MainActivity.this, Context.BIND_AUTO_CREATE);}@Overridepublic void onClick(View v) { unbindService(MainActivity.this);}
- 还需要在启动Service的Activity里重写两个方法
@Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i("miomin", "服务连接成功");}@Override public void onServiceDisconnected(ComponentName name) { Log.i("miomin", "服务连接关闭");}
4、Service的生命周期
- 下图可以看到,使用startService()启动Service和bindService()启动Service,所经历的生命周期是不同的。
想要更详细的了解Service生命周期,可以参考这篇博文,Activity和Service的生命周期(图)
5、跨应用启动和板吊顶Service
Android5.0以后,禁止使用隐式Intent启动Service,必须使用显式意图,对于跨引用启动,我们必须指明被作为启动对象的Service的完整包名。
//使用包名构造显示意图private Intent intent = new Intent();intent.setComponent(new ComponentName("scu.miomin.com.learnaidl", "scu.miomin.com.learnaidl.AppService"));switch (id) { case R.id.btnStartService: startService(intent); break; case R.id.btnStopService: stopService(intent); break; case R.id.btnBindService: bindService(intent, MainActivity.this,Context.BIND_AUTO_CREATE); break; case R.id.btnUnbindService: unbindService(MainActivity.this); break;}
6、与Service通信
(1)进程内部使用Binder通信
创建一个专门的Binder对象来构造Service与Activity的通信通道,在onServiceConnected()回调中接受由目标Service的unbind()方法返回的Binder对象,可以直接对Binder对象的方法进行操作,可以传入参数,返回数据等等;如果需要实现Service实时返回下载进度的功能,可以在Service中构建回调,具体的可以参考如下例子,相信大家都看得懂。
- MyService.java
public class MyService extends Service { // 控制任务是否执行 private boolean serviceRunning = false; private String data = "this is default message"; public void setCallback(Callback callback) { mCallback = callback; } @Override public IBinder onBind(Intent intent) { return new MyBinder(); } public class MyBinder extends Binder { public void setData(String newData) { MyService.this.data = newData; } public MyService getMyService() { return MyService.this; } } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override public void onCreate() { super.onCreate(); serviceRunning = true; new Thread() { @Override public void run() { int i = 0; while (serviceRunning) { i++; String str = i + ":" + data; if (mCallback != null) mCallback.onDataChange(str); Log.i("miomin", str); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } @Override public void onDestroy() { super.onDestroy(); serviceRunning = false; } private Callback mCallback; public interface Callback { void onDataChange(String date); }}
- MainActivity.java
public class MainActivity extends AppCompatActivity implements ServiceConnection { EditText etData; private MyService.MyBinder myBinder; private TextView tvOut; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.startService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startService(new Intent(MainActivity.this, MyService.class)); } }); findViewById(R.id.stopService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(new Intent(MainActivity.this, MyService.class)); } }); findViewById(R.id.bindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { bindService(new Intent(MainActivity.this, MyService.class), MainActivity.this, Context.BIND_AUTO_CREATE); } }); findViewById(R.id.unbindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { unbindService(MainActivity.this); } }); etData = (EditText) findViewById(R.id.etData); findViewById(R.id.btnSyncData).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (myBinder != null) { myBinder.setData(etData.getText().toString()); } } }); tvOut = (TextView) findViewById(R.id.tvOut); } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i("miomin", "服务连接成功"); myBinder = (MyService.MyBinder) service; myBinder.getMyService().setCallback(new MyService.Callback() { @Override public void onDataChange(String date) { Message message = Message.obtain(); Bundle bundle = new Bundle(); bundle.putString("data", date); message.setData(bundle); handler.sendMessage(message); } }); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); tvOut.setText(msg.getData().getString("data")); } }; @Override public void onServiceDisconnected(ComponentName name) { Log.i("miomin", "服务连接关闭"); } @Override protected void onDestroy() { super.onDestroy(); unbindService(MainActivity.this); }}
(2)使用AIDL跨进程与Service通信
- 引言:在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想跨进行通信的话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。而为了方便编码,Android系统提供了AIDL工具来处理这项工作。
- AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。
AIDL接口文件,和普通的接口内容没有什么特别,只是它的扩展名为.aidl。如果想要使用AIDL进行跨进程通信,需要在两个工程的src文件夹下建立一模一样的AIDL文件,并且保证包名相同。
1、创建AIDL文件
interface IAppServiceAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); void setData(String data); List<Car> getAllCar(); }
2、在Service中实现AIDL中定义的接口
- 注意:在实现接口前,需要先ReBuild。
@Overridepublic IBinder onBind(Intent intent) { return new IAppServiceAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public void setData(String data) throws RemoteException { AppService.this.data = data; } @Override public List<Car> getAllCar() throws RemoteException { return null; } };}
3、在需要跨进程操作Service的Activity中接受Binder对象
@Overridepublic void onServiceConnected(ComponentName name, IBinder service) { IAppServiceAidlInterface AIDLBinder = IAppServiceAidlInterface.Stub.asInterface(service);}
更多相关文章
- IPC—进程间通信的基础概念--《Android开发艺术探索》阅读笔记—
- Android(安卓)Service的生命周期及使用!
- Android(安卓)Binder机制之 ServiceManager的启动
- 深入理解Android-Init理解
- Android(安卓)doc 之应用程序基础
- 用Xamarin 实现园友的 :Android浮动小球与开机自启动
- Activity启动流程详解
- Android(安卓)消息推送
- Android(安卓)串口通信