文章目录
Android中服务(service)的基本用法
服务是什么
服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。
不过需要注意的是,服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。
另外,也不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞住的情况。
定义一个服务
首先看一下如何在项目中定义一个服务。新建一个ServiceTest项目,然后右击com.example.servicetest→New→Service→Service,会弹出如图所示的窗口:
可以看到,这里我们将服务命名为MyService,Exported属性表示是否允许除了当前程序之外的其他程序访问这个服务,Enabled属性表示是否启用这个服务。将两个属性都勾中,点击Finish完成创建。
现在观察MyService中的代码,如下所示:
java
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
可以看到,MyService是继承自Service类的,说明这是一个服务。目前MyService中可以算是空空如也,但有一个onBind()方法特别醒目。这个方法是Service中唯一的一个抽象方法,所以必须要在子类里实现。我们会在后面的小节中使用到onBind()方法,目前可以暂时将它忽略掉。
既然是定义一个服务,自然应该在服务中去处理一些事情了,那处理事情的逻辑应该写在哪里呢?这时就可以重写Service中的另外一些方法了,如下所示:
java
public class MyService extends Service {
...
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
可以看到,这里我们又重写了onCreate()、onStartCommand()和onDestroy()这3个方法,它们是每个服务中最常用到的3个方法了。其中onCreate()方法会在服务创建的时候调用,onStartCommand()方法会在每次服务启动的时候调用,onDestroy()方法会在服务销毁的时候调用。通常情况下,如果我们希望服务一旦启动就立刻去执行某个动作,就可以将逻辑写在onStartCommand()方法里。而当服务销毁时,我们又应该在onDestroy()方法中去回收那些不再使用的资源。
另外需要注意,每一个服务都需要在AndroidManifest.xml文件中进行注册才能生效,不知道你有没有发现,这是Android四大组件共有的特点。不过相信你已经猜到了,智能的Android Studio早已自动帮我们将这一步完成了。打开AndroidManifest.xml文件瞧一瞧,代码如下所示:
xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.servicetest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
</service>
</application>
</manifest>
这样的话,就已经将一个服务完全定义好了。
启动和停止服务
定义好了服务之后,接下来就应该考虑如何去启动以及停止这个服务。启动和停止的方法当然你也不会陌生,主要是借助Intent来实现的,下面就让我们在ServiceTest项目中尝试去启动以及停止MyService这个服务。
首先修改activity_main.xml中的代码,如下所示:
xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/start_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Service" />
<Button
android:id="@+id/stop_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Stop Service" />
</LinearLayout>
这里我们在布局文件中加入了两个按钮,分别是用于启动服务和停止服务的。
然后修改MainActivity中的代码,如下所示:
java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startService = (Button) findViewById(R.id.start_service);
Button stopService = (Button) findViewById(R.id.stop_service);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_service:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent); //启动服务
break;
case R.id.stop_service:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent); //停止服务
break;
default:
break;
}
}
}
可以看到,这里在onCreate()方法中分别获取到了Start Service按钮和Stop Service按钮的实例,并给它们注册了点击事件。然后在Start Service按钮的点击事件里,我们构建出了一个Intent对象,并调用startService()方法来启动MyService这个服务。在Stop Serivce按钮的点击事件里,我们同样构建出了一个Intent对象,并调用stopService()方法来停止MyService这个服务。startService()和stopService()方法都是定义在Context类中的,所以我们在活动里可以直接调用这两个方法。注意,这里完全是由活动来决定服务何时停止的,如果没有点击Stop Service按钮,服务就会一直处于运行状态。那服务有没有什么办法让自已停止下来呢?当然可以,只需要在MyService的任何一个位置调用stopSelf()方法就能让这个服务停止下来了。
那么接下来又有一个问题需要思考了,我们如何才能证实服务已经成功启动或者停止了呢?最简单的方法就是在MyService的几个方法中加入打印日志,如下所示:
java
public class MyService extends Service {
...
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService", "onCreate executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyService", "onDestroy executed");
}
}
现在可以运行一下程序来进行测试了,程序的主界面如图所示:
点击一下Start Service按钮,观察logcat中的打印日志,如图所示:
MyService中的onCreate()和onStartCommand()方法都执行了,说明这个服务确实已经启动成功了,并且你还可以在Settings→Developer options→Running services中找到它,如图所示:
然后再点击一下Stop Service按钮,观察logcat中的打印日志,如图所示:
由此证明,MyService确实已经成功停止下来了。
话说回来,虽然我们已经学会了启动服务以及停止服务的方法,不知道你心里现在有没有一个疑惑,那就是onCreate()方法和onStartCommand()方法到底有什么区别呢?因为刚刚点击Start Service按钮后两个方法都执行了。
其实onCreate()方法是在服务第一次创建的时候调用的,而onStartCommand()方法则在每次启动服务的时候都会调用,由于刚才我们是第一次点击Start Service按钮,服务此时还未创建过,所以两个方法都会执行,之后如果你再连续多点击几次Start Service按钮,你就会发现只有onStartCommand()方法可以得到执行了。
如果对你有帮助,就一键三连呗(点赞+收藏+关注),我会持续更新更多干货~~