重温Android 四大组件之 Service
目录
一、Service是什么?
1.Service是一个应用组件,它用来在后台完成一个时间跨度比较大的工作且没有关联任何界面
2.一个Service可以完成下面这些工作:
3.服务的特点:
4. 源码
二 、Service的分类
1.Local Service(本地服务)
2.Remote Service(远程服务)
三、 定义Service
1.定义一个类继承于Service类
2.在AndroidManifest.xml中配置Service
四、启动与停止Service
1.方式一:一般启动
context.startService(Intent intent)contstopService(lntent intent)
2.方式二:绑定启动
bindService(Intent intent,ServiceConnection connection)unbindService(ServiceConnection connection)
五、代码示例
1. 本地服务
(1) activity_main.xml 中定义两组按钮
(2) 自定义Service 类, 并实现onBind 方法, 以及重写其它生命周期相关方法(onCreate / onStartCommand/ onUnbind/ onDestroy)
(3) AndroidManifest 中声明service
(4) Activity 中处理Button 点击事件
(5) 启动或停止服务的 日志输出:
(6) 绑定或解绑服务的 日志输出:
一、Service是什么?
1.Service是一个应用组件,它用来在后台完成一个时间跨度比较大的工作且没有关联任何界面
2.一个Service可以完成下面这些工作:
访问网络
播放音乐
文件1O操作
大数据量的数据库操作
3.服务的特点:
Service在后台运行,不用与用户进行交互即使应用退出,服务也不会停止.
在默认情况下,Service运行在应用程序进程的主线程(UI线程)中,如果需要在Service中处理一些网络连接等耗时的操作,那么应该将
这些任务放在分线程中处理,避兔阻塞用户界面
4. 源码
Service 类是一个抽象类, 继承了ContextWrapper, 即Context 类里定义的方法也可以用到 (Activity 也是ContextWrapper 的子类)
public abstract class Service extends ContextWrapper implements ComponentCallbacks2,
ContentCaptureManager.ContentCaptureClient {
二 、Service的分类
1.Local Service(本地服务)
Service对象与Serive的启动者在同个进程中运行,两者的通信是进程内通信
2.Remote Service(远程服务)
Service对象与Service的启动者不在同一个进程中运行,这时存在一个进程间通信的问题,Android专门为此设计了AlDL来实现进程间通信
3. 前台service 、后台service
一般用得多的是后台service
三、 定义Service
1.定义一个类继承于Service类
public class MyLocalService extends Service {
2.在AndroidManifest.xml中配置Service
<application
...>
<service android:name=".MyLocalService"/>
</application>
四、启动与停止Service
1.方式一:一般启动
context.startService(Intent intent)
context.stopService(lntent intent)
2.方式二:绑定启动
bindService(Intent intent,ServiceConnection connection)
unbindService(ServiceConnection connection)
区别:看Service启动后是否与启动者有关联?
Service对象经历的生命周期是否相同?
五、代码示例
1. 本地服务
实例如图:
(1) activity_main.xml 中定义两组按钮
分别为 启动服务 、停止服务 和 绑定服务、解绑服务, 界面很简单
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="60dp"
android:textSize="30sp"
android:text="1. 测试启动本地服务" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="启动服务"
android:onClick="startService"
android:textSize="20sp"/>
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="停止服务"
android:onClick="stopService"
android:textSize="20sp"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="60dp"
android:textSize="30sp"
android:text="2. 测试绑定本地服务" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="绑定服务"
android:onClick="bindService"
android:textSize="20sp"/>
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="解绑服务"
android:onClick="unbindService"
android:textSize="20sp"/>
</LinearLayout>
</LinearLayout>
(2) 自定义Service 类, 并实现onBind 方法, 以及重写其它生命周期相关方法(onCreate / onStartCommand/ onUnbind/ onDestroy)
package com.example.servicetest1;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class MyLocalService extends Service {
private final static String TAG = "MyLocalService";
@Override
public void onCreate() {
super.onCreate();
log("onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
log("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
log("onDestroy");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
log("onBind");
return new Binder();
}
@Override
public boolean onUnbind(Intent intent) {
log("onUnbind");
return super.onUnbind(intent);
}
private void log(String msg){
Log.d(TAG, msg);
}
}
(3) AndroidManifest 中声明service
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyLocalService"/>
</application>
(4) Activity 中处理Button 点击事件
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
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.widget.Toast;
public class MainActivity extends AppCompatActivity {
private final static String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view) {
log("startService ");
Intent intent = new Intent(this, MyLocalService.class);
startService(intent);
}
public void stopService(View view) {
log("stopService ");
Intent intent = new Intent(this, MyLocalService.class);
stopService(intent);
}
private void log(String msg) {
Log.d(TAG, msg);
}
private ServiceConnection mConnection = null;
public void bindService(View view) {
log("bindService ");
Intent intent = new Intent(this, MyLocalService.class);
if (mConnection == null) {
mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
log("onServiceConnected ");
}
@Override
public void onServiceDisconnected(ComponentName name) {
log("onServiceDisconnected ");
}
};
}
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
public void unbindService(View view) {
log("unbindService ");
if (mConnection != null) {
unbindService(mConnection);
mConnection = null;
Toast.makeText(this, "unbind service", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onDestroy() { // 似乎是多余的
super.onDestroy();
log("onDestroy ");
if (mConnection != null) {
log("onDestroy - need unbind service");
unbindService(mConnection);
mConnection = null;
}
}
}
(5) 启动或停止服务的 日志输出:
//第一次点击启动
2020-11-26 12:42:27.305 D/MainActivity: startService
2020-11-26 12:42:27.312 D/MyLocalService: onCreate
2020-11-26 12:42:27.312 D/MyLocalService: onStartCommand
//第二次点击启动
2020-11-26 12:42:31.241 D/MainActivity: startService
2020-11-26 12:42:31.244 D/MyLocalService: onStartCommand
//点击停止
2020-11-26 12:42:34.118 D/MainActivity: stopService
2020-11-26 12:42:34.122 D/MyLocalService: onDestroy
可以看到, 在启动时, Service 会调用 onCreate / onStartCommand, 而已经启动情况下,再调启动,仅会执行onStartCommand;
停止时, Service 会调用 onDestroy
(6) 绑定或解绑服务的 日志输出:
//点击绑定
2020-11-26 12:47:46.372 D/MainActivity: bindService
2020-11-26 12:47:46.379 D/MyLocalService: onCreate
2020-11-26 12:47:46.380 D/MyLocalService: onBind
2020-11-26 12:47:46.383 D/MainActivity: onServiceConnected
//点击解绑
2020-11-26 12:51:48.959 D/MainActivity: unbindService
2020-11-26 12:51:48.984 D/MyLocalService: onUnbind
2020-11-26 12:51:48.985 D/MyLocalService: onDestroy
//绑定的时候,退出Activity
2020-11-26 12:53:12.285 I/ViewRootImpl@665f8ac[MainActivity]: dispatchDetachedFromWindow
2020-11-26 12:53:12.304 D/MyLocalService: onUnbind
2020-11-26 12:53:12.304 D/MyLocalService: onDestroy
在绑定的时候, 会调用 onCreate /onBind, 客户端会回调 onServiceConnected
解绑的试试,会先调用 onUnBind, 再调用 onDestroy.
此外,在绑定的时候,退出Activity, 似乎会自动解绑服务?? (不需要在Activity onDestroy 时, 手动调用解绑服务??, 不会报 leak service connection ??)