Service是安卓非常重要的一个部分,Activity主要是用来显示界面,但是它并不能长期运行,而且,当系统的内存比较少的时候,系统很可能就会把Activity给杀死。而Service主要用来解决这个问题,它可以长期在后台运行,比如说:后台下载、音乐播放、推送服务等,都是用Service在后台默默进行的。
而Service有两种方式,一种是启动Service,一种是绑定Service。对于启动Service这种方式,Activity和Service无法实现交互,也就是说Service只是启动起来,但是无法给Activity返回信息。而绑定方式的则可以正常和Activity交互。我们这里只介绍绑定Service。
首先,我们先创建一个工程叫做:BindService,并创建一个类TestService,让它继承自Service,此时,我们发现需要重写一个onBind的方法,返回一个IBinder的对象,这个I就是Interface的缩写,也就是IBinder是一个接口,它有很多方法,如果直接写的话需要把这些方法都补充全,不过它有一个叫Binder的实现类,我们创建一个类直接继承自Binder就好了。
package com.example.kalen.bindservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
public class TestService extends Service{
MyBinder binder = new MyBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public class MyBinder extends Binder {
}
}
Service也是安卓的基本组件,我们需要在manifest文件里对它进行注册,在AndroidManifest.xml中添加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=".TestService"/>
</application>
写到这块之后我们再回到Activity那块来尝试绑定这个服务。绑定服务需要使用bindService这个方法。先看看bindService需要的参数。
bindService(Intent service, ServiceConnection conn, int flags)
这里第一个参数是一个Intent类型,和startActivity需要的Intent类似,我们需要设置绑定哪一个Service,需不需要传些参数(通过putExtra)。
第二个参数中,ServiceConnection是一个接口类型,它有两个方法,一个是onServiceConnected,onServiceDisconnected。其中onServiceConnected可以拿到我们在Service中写的onBind方法返回过来的对象。拿到这个对象,我们就可以对Service进行一些操作了。
第三个参数其实就是个flag,一般用BIND_AUTO_CREATE,也就是绑定并创建这个Service。
先完成一下MainActivity,如下:
package com.example.kalen.bindservice;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
TestService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setClass(MainActivity.this, TestService.class);
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("绑定TestService成功");
myBinder = (TestService.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, BIND_AUTO_CREATE);
}
}
现在,相当于绑定了一个空的服务,它什么都不做。我们现在给它加点功能,让Service记录一下绑定成功到现在的一共过去了多少秒。
这里首先在MyBinder中创建一个整型变量,然后创建一个线程,让这个整形变量每秒钟+1。(其实可以直接获取创建的时间戳,然后和当前时刻的时间戳相减,这里主要以模拟为目的)
package com.example.kalen.bindservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
public class TestService extends Service{
MyBinder binder = new MyBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
binder.setSecond(binder.getSecond() + 1);
try {//睡眠1秒
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
return binder;
}
public class MyBinder extends Binder {
private int second = 0;
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
}
}
最后,我们在MainActivity中添加一个Button,点击之后获取秒数。
package com.example.kalen.bindservice;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
TestService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setClass(MainActivity.this, TestService.class);
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("绑定TestService成功");
myBinder = (TestService.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, BIND_AUTO_CREATE);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (myBinder != null) {
Toast.makeText(MainActivity.this,
myBinder.getSecond() + "秒",
Toast.LENGTH_SHORT).show();
}
}
});
}
}
当我们回到主页,打开其他应用时,TestService仍然会继续在后台运行,读者可以试试直接在Activity里创建一个线程获取秒数,看看当我们打开其他应用后再打开BindService会怎么样?
除了绑定同一个程序的Service之外,还可以绑定其他程序的Service,如果读者感兴趣可以看看AIDL。
- 目录
- 上一节:ListView与BaseAdapter
- 下一节:Android权限机制