第一种Service
定义
- 安卓四大组件之一,级别和activity相当
- 长时间运行在后台,不可见的,没有界面的组件
- 运行在主线程中的
- 可以跨进程调用
为什么要使用Service
- 大部分病毒利用了Service的特点,可以在后台完成预设的功能;
- 作为Android工程师,至少需要了解Service是如何在后台完成预设功能。
两种启动方式
- startService
- bindService
使用startService方式启动Service的步骤
- 新建类继承Service
- 重写onCreate方法
- 实现onBind抽象方法
- 重写onStartCommand方法
- 重写onDestory方法
- 在AndroidManifest中注册Service
- 在有Context环境中通过startService启动Service
- 在有Context环境中通过stopService停止Service
使用startService方式启动Service的总结(优缺点)
- onCreat只执行一次 运行在主线程,耗时操作需另开子线程
- 通过Intent传参,在onStatCommand中接收参数
- 无法获得Service参数,不能直接操作Service的属性的方法
- 调用stopService方法,Service会执行
- 优点:使用简单
- 缺点:无法获得Service参数,不能直接操作Service的属性的方法
代码展示
avtivity_main:
<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="com.homework.activity.serviceactivity.MainActivity">
<Button
android:id="@+id/start_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Service" />
<Button
android:id="@+id/stop_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Stop Service" />
</LinearLayout>
MyService:
public class MyService extends Service {
//1,创建时启动,只执行一次
@Override
public void onCreate() {
super.onCreate();
//打印获得子线程名
Log.e("Service"+Thread.currentThread().getName(), "onCreate()……");
}
//2,执行很多次
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//打印获得子线程名
Log.e("Service"+Thread.currentThread().getName(),"onStartCommand() ……");
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
//打印获得子线程名
Log.e("Service" + Thread.currentThread().getName(), i + "***");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
//3
@Override
public void onDestroy() {
super.onDestroy();
Log.e("Service", "onDestroy() ……");
}
//4
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
MainActivity:
public class MainActivity extends Activity implements View.OnClickListener {
private Button startBtn;
private Button stopBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startBtn=findViewById(R.id.start_btn);
stopBtn=findViewById(R.id.stop_btn);
startBtn.setOnClickListener(this);
stopBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_btn:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.stop_btn:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
default:
break;
}
}
}
使用bindService方式启动Service的步骤
- 新建类继承Service
- 重写onCreatr方法
- 实现onBind抽象方法(需要返回一个bind子类对象)
- 重写onUnbind方法
- 重写onDestory方法
- 在AndroidManifest中注册Service(使用标签注册 )
- 在有Context环境中通过ServiceConnection
- 在有Context环境中通过bindService绑定Service
- 在有Context环境中通过unbindService解绑Service
使用bindService方式启动Service的总结(优缺点)
在Context上下文调用此方法即可触发绑定Service,此方法需要三个参数。
- Intent对象,用于传参;
- ServiceConnection接口对象;
- flag标识,代表如何绑定Service,常用的flag是Context.BIND_AUTO_CREATE,代表Service不存在时创建。
优点:想要获得Service对象,并操作它的属性和方法,需要使用bindService;
缺点:使用bindService启动Service步骤比较繁琐。
代码展示:
activity_main:
<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="com.homework.activity.bindservice.MainActivity">
<Button
android:id="@+id/bind_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定按钮"/>
<Button
android:id="@+id/unbind_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="解绑按钮"/>
<Button
android:id="@+id/to_lisi_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="前往李四页面"/>
</LinearLayout>
MainActivity:
//新建MainService继承Service
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private String TAG="MainActivity";
private Button bindbtn;
private Button unbindbtn;
private Button tolistbtn;
//创建ServiceConnection,实现两个方法,onServiceConnected,onServiceDisconnected
//在onServiceConnected中,转换为Guanjia类型,调用getService,拿到TextService对象,TextService.fly运行
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG,"onServiceConnected");
//通过管家的中介作用,拿到MyService对象
Myservice myservice = ((Myservice.Guanjia)service).getServiceObject();
myservice.fly();
// System.out.println("connected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG,"onServiceDisconnected");
// System.out.println("onDisConnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindID();
// 从5.0开始,谷歌要求必须使用显示intent启动service
}
private void bindID() {
bindbtn = findViewById(R.id.bind_btn);
unbindbtn = findViewById(R.id.unbind_btn);
tolistbtn=findViewById(R.id.to_lisi_btn);
bindbtn.setOnClickListener(this);
unbindbtn.setOnClickListener(this);
tolistbtn.setOnClickListener(this);
}
//设置监听,Intent,联系Guanjia,bindService(intent,serviceconnectio,自动连接)
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.bind_btn:
Intent intent=new Intent(this,Myservice.class);
bindService(intent, serviceConnection,BIND_AUTO_CREATE);
break;
case R.id.unbind_btn:
unbindService(serviceConnection);
break;
case R.id.to_lisi_btn:
Intent intent1=new Intent(this,LisiActivity.class);
startActivity(intent1);
break;
}
}
}
MyService:
//创建Guanjia得到当前Service对象
public class Myservice extends Service {
private String TAG="Myservice";
private Guanjia guanjia=new Guanjia();
public class Guanjia extends Binder{
//作用:得到当前Service的对象
public Myservice getServiceObject(){
return Myservice.this;
}
}
//定义fly方法,打log(开飞机)
public void fly(){
Log.e(TAG,"打飞机");
}
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG,"执行onBind方法...");
return guanjia;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG,"执行onUnBind方法...");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG,"执行onCreate方法");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG,"执行onDestroy方法");
}
}
第二种Service,IntentService
使用IntentService的总结(与Service的区别)
- 继承于Service并处理异步任务的一个类
- 在IntentService内有一个工作线程来执行耗时操作//重点区别
- 此线程无需我们控制和维护
- 当多次启动时,会以队列的形式,逐一执行
- 当执行完耗时操作后,此Service会自动停止
使用IntentService方式启动Service的步骤
- 新建类继承IntentService
- 实现父类的构造方法
- 重写onHandleIntent方法
- 重写Oncreat方法
- 重写onDestory方法
- 在AndroidManifest中注册Service
- 在有Context环境中实现ServiceConnection接口
- 在有Context环境中通过startService绑定Service
- 在有Context环境中通过stopService解绑Service
onHandleIntent
- 需要执行的耗时操作放在此方法中执行
- 此方法会新开线程,不会在main线程中执行
//bindServise跳转到IntentService页面
activity_lisi:
<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="com.homework.activity.bindservice.LisiActivity">
<Button
android:id="@+id/list_bind_btn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="绑定Service"/>
<Button
android:id="@+id/list_unbind_btn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="解绑Service"/>
</LinearLayout>
MyIntentService:
public class MyIntentService extends IntentService{
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public MyIntentService(String name) {
super(name);
}
public MyIntentService(){
super("");//当前线程名
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
Log.e("MyIntentService",i+"***");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
LisiActivity:
public class LisiActivity extends AppCompatActivity implements View.OnClickListener{
private Button bindBtn;
private Button unBindBtn;
private String TAG="ListActicity";
private ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG,"onServiceConnected*****************");
Myservice myservice=((Myservice.Guanjia) service).getServiceObject();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG,"onServiceDisconnected*******************");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lisi);
bindID();
}
private void bindID() {
bindBtn=findViewById(R.id.list_bind_btn);
unBindBtn=findViewById(R.id.list_unbind_btn);
bindBtn.setOnClickListener(this);
unBindBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.list_bind_btn:
// Intent intent=new Intent(this,Myservice.class);
// bindService(intent,connection,BIND_AUTO_CREATE);
Intent intent=new Intent(this,MyIntentService.class);
startService(intent);
break;
case R.id.list_unbind_btn:
unbindService(connection);
break;
}
}
}