Android App开发基础篇—四大组件之Service

    前言:应用开发中经常会遇到要求长期持续运行的任务,这些任务即使在程序被切换到后台,或者用户打开另一个应用,也能够保持正常运行。Android开发中通过Service提供了这类解决方案。

一、概念

    Service是Android中用于实现程序后台运行,以便执行一些无需用户界面且要求长期运行的任务的解决方案。Service无需用户界面,即使程序被切换到后台,或者用户打开另一个应用,程序仍可正常运行。注意,“后台运行”并非运行于子线程或独立进程,Service默认运行于UI线程(主线程)中,除非在Service中创建子线程,否则不要在Service中执行耗时操作。

二、Service的使用

    Android中有两种Service,一种是普通Service,一种叫做IntentService。下面分别进行介绍。

    2.1 普通Service

    (1)生命周期:与Activity一样,Service也具有生命周期。如下图:

图1 Service的生命周期

    如上图所示,Service的生命周期被分为了两种。这是因为Service具有两种启动方式:通过startService()方法启动,以及通过bindService()方法启动。下面来分别介绍:

    ● 通过startService()方法启动Service

    以startService()方法启动的Service,程序将能够在系统中保持长存。意思就是说,除非在代码中调用了stopService()或stopSelf()方法,或者Service所在进程被杀死,否则以startService()方法启动的Service,在启动后会一直保持运行状态,即使用户将程序切换到后台,或者用户打开另一个应用,程序也会持续运行。下面来看一下使用:

    首先,需要先创建一个Service,在项目中“File”—>"New",找到Service,创建即可(Eclipse中可能需要“File”—>"New"—>"Other"—>"Android"—>"Android Object")。创建好后,默认会有一个构造函数和一个onBind(Intent intent)方法,这里我们把onCreate()和onStartCommand()方法也加上,然后简单的打个日志测试一下生命周期的执行。代码如下所示:

package com.test.myapplication;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.util.Log;public class MyService extends Service {    public MyService() {    }    @Override    public IBinder onBind(Intent intent) {        // TODO: Return the communication channel to the service.        return null;    }    @Override    public void onCreate() {        Log.e("MyService", "onCreate: ===================="  );        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e("MyService", "onStartCommand: ===================="  );        return super.onStartCommand(intent, flags, startId);    }}

    接下来在Activity里面使用Service,同界面跳转一样,需要使用Intent来指定要使用的Service。这里在MainActivity里面添加两个按钮,分别测试启动Service和停止Service。代码如下:

activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.test.myapplication.MainActivity">            android:id="@+id/main_button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="开启Service"/>            android:id="@+id/main_button1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="停止Service"        android:layout_alignParentTop="true"        android:layout_toRightOf="@+id/main_button"        android:layout_toEndOf="@+id/main_button"        android:layout_marginLeft="18dp"        android:layout_marginStart="18dp" />    

MainActivity代码:
package com.test.myapplication;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //为了在Activity中对布局文件中的UI元素(控件、布局等)进行操作,需要        //使用findViewById()方法从布局文件中找到对应的UI元素,并将其关联到        //Activity中的一个对象。代码书写格式如下:        Button button = (Button) findViewById(R.id.main_button);        //布局中的Button按钮设置点击事件监听        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //实例化Intent对象                Intent intent = new Intent();                //通过Intent对象指定要启动的Service                intent.setClass(MainActivity.this, MyService.class);                //通过startService()启动Service                startService(intent);            }        });        findViewById(R.id.main_button1).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent();                intent.setClass(MainActivity.this, MyService.class);                stopService(intent);            }        });    }}

MainActivity代码:
package com.test.myapplication;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //为了在Activity中对布局文件中的UI元素(控件、布局等)进行操作,需要        //使用findViewById()方法从布局文件中找到对应的UI元素,并将其关联到        //Activity中的一个对象。代码书写格式如下:        Button button = (Button) findViewById(R.id.main_button);        //布局中的Button按钮设置点击事件监听        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //实例化Intent对象                   Intent intent = new Intent();                //通过Intent对象指定要启动的Service                intent.setClass(MainActivity.this, MyService.class);                //通过startService()启动Service                startService(intent);            }        });        findViewById(R.id.main_button1).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //实例化Intent对象。                   Intent intent = new Intent();                //指定要停止的Service                intent.setClass(MainActivity.this, MyService.class);                //停止Service                stopService(intent);            }        });    }}

    接下来,就可以分别点击两个按钮进行测试。当我们连续点击“开启Service”时,会发现onCreate()方法只调用了一次,而onStartCommand()方法每次点击的时候都会调用。如果我们点击了“停止Service”,然后再点击“开启Service”,会发现onCreate()会再次被调用。这就说明,以startService()方法启动Service的时候,onCreate()方法只会在Service第一次被创建的时候调用,其他时候只要Service没有因调用stopService()或stopSelf(),或者进程被杀死而停止,再次启动Service只会调用onStartCommand()方法。

    ● 通过bindService()方法启动Service

    bindService()方法会将Activity与Service绑定,被绑定 的Service会随着Activity的启动而启动,通过bindService()方法绑定Service后,可以在Activity里面调用Service里面的方法。下面来看使用步骤:

    首先,在项目里再添加一个SecondActivity,同时在MainActivity里面添加一个按钮跳转到SecondActivity。然后在SecondActivity的onCreate()的时候绑定Service,在onDestory()方法(即Activity关闭的时候)调用unbindService()方法解绑服务(必需)。SecondActivity代码如下:

SecondActivity代码:
package com.test.myapplication;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.Handler;import android.os.IBinder;import android.support.v7.app.AppCompatActivity;import android.util.Log;public class SecondActivity extends AppCompatActivity {    ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {           //Service绑定成功,并且方法参数中的“IBinder service”对象非空时调用,            //该参数的值是通过Service里面的onBind()方法返回            Log.e("SecondActivity", "onServiceConnected:============= ");        }        @Override        public void onServiceDisconnected(ComponentName name) {            //Service所在进程被杀死,Service连接断开时调用此方法。        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_second);        //实例化Intent对象          Intent intent = new Intent();        //设置要绑定的Service        intent.setClass(this, MyService.class);        //绑定Service。需要三个参数         //参数1intent对象         //参数2ServiceConnection对象         //参数3Context.BIND_AUTO_CREATE表示如果绑定的Service还未创建,则自动创建一个。         bindService(intent, conn, Context.BIND_AUTO_CREATE);    }    @Override    protected void onDestroy() {        super.onDestroy();        //在界面销毁的时候,需要调用unbindService()方法解绑         unbindService(conn);    }}

    要在Activity里面调用Service里面的方法,则需继续以下步骤:

    ● 创建一个类MyBinder,继承Binder类

    ● 在MyBinder类中添加需要调用的方法

    ● 在Service的onBind()方法中返回一个MyBinder类的对象

    ● 在Activity的onServiceConnected(ComponentName name,IBinder service)方法中,将参数中的service强转为MyBinder类型

    ● 通过强转后的MyBinder对象调用Service中的方法

 具体代码如下:

添加了MyBinder类的MyService代码:
package com.test.myapplication;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.util.Log;public class MyService extends Service {    public MyService() {    }    @Override    public IBinder onBind(Intent intent) {        return new MyBinder();    }    @Override    public void onCreate() {        Log.e("MyService", "onCreate: ====================");        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e("MyService", "onStartCommand: ====================");        return super.onStartCommand(intent, flags, startId);    }    public class MyBinder extends Binder {        public void test() {            Log.e("MyBinder", "test: =============");        }    }}

调用MyService中的方法的SecondActivity代码:

package com.test.myapplication;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.support.v7.app.AppCompatActivity;import android.util.Log;public class SecondActivity extends AppCompatActivity {    ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {
   //Service绑定成功,并且方法参数中的“IBinder service”对象非空时调用,   //该参数的值是通过Service里面的onBind()方法返回   Log.e("SecondActivity", "onServiceConnected:============= ");   //调用MyService里面的test()方法   MyService.MyBinder myBinder = (MyService.MyBinder) service;   myBinder.test();
} @Override public void onServiceDisconnected(ComponentName name) { // Service 所在进程被杀死, Service 连接断开时调用此方法。 } } ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState) ; setContentView(R.layout. activity_second) ; // 实例化 Intent 对象 Intent intent = new Intent() ; // 设置要绑定的 Service intent.setClass( this, MyService. class) ; // 绑定 Service 。需要三个参数 // 参数 1 intent 对象 // 参数 2 ServiceConnection 对象 // 参数 3 Context.BIND_AUTO_CREATE 表示如果系统中不存在服务,则自动创建一个。 bindService(intent , conn , Context. BIND_AUTO_CREATE) ; } @Override protected void onDestroy() { super.onDestroy() ; // 在界面销毁的时候,需要调用 unbindService() 方法解绑 unbindService( conn) ; }}

    2.2 IntentService

    Android中还有一种IntentService,与普通Service默认在UI线程运行不同,IntentService会将用户请求执行在一个子线程中,用户只需覆写onHandleIntent()方法,并在其中完成自己的耗时操作即可。需要注意的是,IntentService只能通过startService()来启动,且在任务执行完毕后会调用stopSelf自我销毁。因此,它适用于一些短期的耗时任务。IntentService代码如下:

package com.test.myapplication;import android.app.IntentService;import android.content.Intent;import android.util.Log;/** * An {@link IntentService} subclass for handling asynchronous task requests in * a service on a separate handler thread. * 

* TODO: Customize class - update intent actions, extra parameters and static * helper methods. */public class MyIntentService extends IntentService { public MyIntentService() { super("MyIntentService"); } //新建IntentService的时候会默认覆写几个方法, //我们只需在这个方法里面执行自己的操作即可 @Override protected void onHandleIntent(Intent intent) { int i = 0; while (i < 100) { i++; Log.e("MyIntentService", "onHandleIntent: ==============="+i); } }}


     后记:“后台运行”不等于“运行在子线程中”。普通Service默认运行在U线程中,不能在其中直接执行耗时操作。它的主要功能是用来执行一些可以在后台执行,无需用户交互界面的功能,比如后台下载,后台更新等。它有两种启动方式:startService和bindService。Android中另外提供了IntentService使程序能够默认将用户的请求执行在子线程中。IntentService只能通过startService进行启动,并且当任务执行完毕时,IntentService会调用stopSelf()方法自我销毁,它适用于一些短期的耗时任务。   

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. Android事件总线EventBus的用法详解
  5. Android中程序与Service交互的方式(二)-五种交互方式
  6. Android(安卓)WebView与JavaScript交互实现Web App
  7. Android处理输入事件的流程(一)
  8. 分析点击android桌面app图标启动应用程序的过程
  9. Android(安卓)AIDL Service调试方法

随机推荐

  1. Customize "share picture via" menu on
  2. category
  3. Android(安卓)View随手指移动
  4. fragment
  5. 获取Android唯一设备号
  6. Android监听组合键
  7. Android(安卓)AlertDialog example
  8. Android圆角图片封装类
  9. android study ------ HAL ---> light se
  10. Android程序示例