Android Service总结03 之被启动的服务 -- Started Service

版本

版本说明

发布时间

发布人

V1.0

添加了Service的介绍和示例

2013-03-17

Skywang


1 Started Service介绍

Started Service,即被启动的服务。它是2种常见服务之一,另一种是Bound Service。Started Service常被用在执行进程的某个后台操作,如通过该服务来实现文件下载等功能。

实现步骤和使用方法

(01) 创建一个Started Service类,该类要继承于Service。

(02) 在Started Service类中实现以下接口:
onStartCommand():必须实现!在其中启动服务提供的功能。例如,若该服务是在后台下载文件,则在该函数中启动一个新的线程(Thread),在线程中实现下载功能。当客>户端通过startService()启动函数时,系统会自动执行服务对应的onStartCommand()函数。
onBind():必须实现!返回null即可。onBind()是"Bound Service"中用到的函数,在"Started Service"服务不会执行onBind();但必须实现它,因为onBind()是Service类
的抽象方法。
onCreate():可以不用实现,视用户需求而定。当服务被创建时,系统会自动调用该函数。一般在该函数中进行初始化工作,例如:新建线程。
onDestroy():可以不用实现,视用户需求而定。当服务被销毁时,系统会自动调用该函数。一般在该函数中进行清除工作,例如,终止并回收线程。

(03) 客户端通过startService()启动服务。

(04) 客户端通过endService()结束服务。

下面以实际例子来说明“Started Service”的实现方式。


2 Service示例

采用Service来实现“Android Service总结02 IntentService介绍及实例”中的示例,即:编写一个activity,包含2个按钮和1个进度条,2个按钮分别是开始按钮、结束按钮。点击“开始”按钮:进度条开始加载;“开始”变成“重启”按钮;显示“结束”按钮(默认情况,“结束”按钮是隐藏状态)。

BaseServiceTest包括了两个主要的类:

StartServiceImpl.java —— Service的子类。当服务被启动时,它会并新建一个线程,每隔200ms将一个数字+2,并通过广播发送出去。

StartServiceTest.java —— 调用StartServiceImpl的Activity。

StartServiceImpl.java的内容如下

package com.skywang.service;import android.os.IBinder;import android.app.Service;import android.content.Intent;import android.util.Log;import java.lang.Thread;/** * @desc 服务:每隔200ms将一个数字+2并通过广播发送出去 * @author skywang * */public class StartServiceImpl extends Service {    private static final String TAG = "skywang-->StartServiceImpl";        // 发送的广播对应的action    private static final String COUNT_ACTION = "com.skywang.service.startservice.COUNT_ACTION";        // 线程:用来实现每隔200ms发送广播    private static CountThread mCountThread = null;    // 数字的索引    private static int index = 0;        @Override    public void onCreate() {        Log.d(TAG, "onCreate");        super.onCreate();    }        @Override    public void onDestroy() {        Log.d(TAG, "onDestroy");        // 终止服务        if ( mCountThread != null) {            mCountThread.interrupt();            mCountThread = null;        }        super.onDestroy();    }        @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.d(TAG, "onStartCommand");                // 非首次运行服务时,执行下面操作        // 目的是将index设为0        if ( mCountThread != null) {            Log.d(TAG, "mCountThread != null");            index = 0;            return START_STICKY;        }                Log.d(TAG, "start thread");        // 首次运行时,创建并启动线程        mCountThread = new CountThread();        mCountThread.start();                return START_STICKY;    }        @Override    public IBinder onBind(Intent intent) {        Log.d(TAG, "onBind");        return null;    }        private class CountThread extends Thread {        @Override         public void run() {            index = 0;            try {                while (true) {                    // 将数字+2,                    index += 2;                                                            // 将index通过广播发送出去                    Intent intent = new Intent(COUNT_ACTION);                    intent.putExtra("count", index);                    sendBroadcast(intent);//                    Log.d(TAG, "CountThread index:"+index);                                        // 若数字>=100 则退出                    if (index >= 100) {                        if ( mCountThread != null) {                            mCountThread = null;                        }                        return ;                    }                                        // 修改200ms                    this.sleep(100);                }            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

StartServiceTest.java的内容如下

package com.skywang.service;import android.os.Bundle;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.view.View;import android.widget.Button;import android.widget.ProgressBar;import android.util.Log;public class StartServiceTest extends Activity {    private static final String TAG = "skywang-->StartServiceTest";    private static final String COUNT_ACTION = "com.skywang.service.startservice.COUNT_ACTION";    private CurrentReceiver mReceiver;    private Button mStart = null;    private Button mStop = null;    private Intent mIntent = null;    private Intent mServiceIntent = null;     private ProgressBar mProgressBar = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.start_service_test);                mStart = (Button) findViewById(R.id.start);        mStart.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View arg0) {                Log.d(TAG, "click start button");                // 显示“结束”按钮                mStop.setVisibility(View.VISIBLE);                // 将“开始”按钮更名为“重启”按钮                mStart.setText(R.string.text_restart);                // 启动服务,用来更新进度                if (mServiceIntent == null)                     mServiceIntent = new Intent("com.skywang.service.StartService");                startService(mServiceIntent);            }        });                mStop = (Button) findViewById(R.id.stop);        mStop.setOnClickListener(new View.OnClickListener() {                        @Override            public void onClick(View view) {                Log.d(TAG, "click stop button");                if (mServiceIntent != null) {                    // 结束服务。                    stopService(mServiceIntent);                    mServiceIntent = null;                }            }        });        mStop.setVisibility(View.INVISIBLE);                mProgressBar = (ProgressBar) findViewById(R.id.pbar_def);        // 隐藏进度条        mProgressBar.setVisibility(View.INVISIBLE);                // 动态注册监听COUNT_ACTION广播        mReceiver = new CurrentReceiver();        IntentFilter filter = new IntentFilter();        filter.addAction(COUNT_ACTION);        this.registerReceiver(mReceiver, filter);    }    @Override      public void onDestroy(){          super.onDestroy();            if(mIntent != null)            stopService(mIntent);                if(mReceiver != null)            this.unregisterReceiver(mReceiver);    }        /**     * @desc 更新进度条     * @param index     */    private void updateProgressBar(int index) {        int max = mProgressBar.getMax();        if (index < max) {            mProgressBar.setProgress(index);            mProgressBar.setVisibility(View.VISIBLE);        } else {            // 隐藏进度条            mProgressBar.setVisibility(View.INVISIBLE);            // 隐藏“结束”按钮            mStop.setVisibility(View.INVISIBLE);            // 将“重启”按钮更名为“开始”按钮            mStart.setText(R.string.text_start);        }//        Log.d(TAG, "progress : "+mProgressBar.getProgress()+" , max : "+max);    }        /**     * @desc 广播:监听COUNT_ACTION,获取索引值,并根据索引值来更新进度条     * @author skywang     *     */    private class CurrentReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context context, Intent intent) {            String action  = intent.getAction();            if (COUNT_ACTION.equals(action)) {                int index = intent.getIntExtra("count", 0);                updateProgressBar(index);            }        }    }}

layout文件start_service_test.xml的内容如下

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent"    >        <LinearLayout        android:orientation="horizontal"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        >        <Button            android:id="@+id/start"              android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:text="@string/text_start"            />        <Button            android:id="@+id/stop"              android:layout_width="wrap_content"             android:layout_height="wrap_content"            android:text="@string/text_stop"            />            </LinearLayout>    <ProgressBar        android:id="@+id/pbar_def"        android:layout_width="match_parent"        android:layout_height="wrap_content"        style="@android:style/Widget.ProgressBar.Horizontal"        android:max="100"        android:progress="0"        /></LinearLayout>

manifest内容如下

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.skywang.service"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="11"        android:targetSdkVersion="17" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name="com.skywang.service.StartServiceTest"            android:screenOrientation="portrait"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>                <service android:name=".StartServiceImpl">            <intent-filter>                <action android:name="com.skywang.service.StartService" />            </intent-filter>        </service>    </application></manifest>

点击下载源代码

效果图


3 补充说明

在示例中,我们自定义了onStartCommand()的返回值。Android API文档中说明它的返回值,可以有以下4种:

START_STICKY

如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。

START_NOT_STICKY

“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。

START_REDELIVER_INTENT

重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。

START_STICKY_COMPATIBILITY

START_STICKY的兼容版本,但不保证服务被kill后一定能重启。



更多service内容:

1Android Service总结01 目录

2Android Service总结02 service介绍

3Android Service总结03 之被启动的服务 -- Started Service

4Android Service总结04 之被绑定的服务 -- Bound Service

5Android Service总结05 之IntentService

6Android Service总结06 之AIDL

   

参考文献:
1,Android API文档:http://developer.android.com/guide/components/services.html 2,Android Service被关闭后自动重启,解决被异常kill 服务:http://blog.csdn.net/by317966834/article/details/7591502


更多相关文章

  1. 第九篇 ANDROID包管理服务机制与架构
  2. 【Android(安卓)系统开发】 Android(安卓)系统启动流程简介
  3. android Java代码的启动
  4. android创建桌面快捷方式(启动目标非项目的启动页)
  5. Android(安卓)AM命令行启动程序的方法
  6. 基于Apache mina 的android 客户端tcp长连接实现
  7. Android(安卓)API 28 访问服务器失败 提示CLEARTEXT
  8. android dialog
  9. android定义圆形按钮Shape,选中改变颜色

随机推荐

  1. android不是内部或外部命令,也不是可运行
  2. Android
  3. Android(安卓)之 shape和selector用法介
  4. 为什么iOS平台更容易吸引开发者?
  5. TextView中的文字添加阴影效果及Style的
  6. 27:活用Android的Message Queue(2/3)
  7. android中json的序列化与反序列化
  8. Android之Service设置android:process作
  9. 说说 Android(安卓)的常见 UI 控件
  10. Android深入浅出之Audio 第一部分 AudioT