Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 02 Started Service--之被啟動的服務

Android 02 Started Service--之被啟動的服務

編輯:關於Android編程

 

正文

 

 

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 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的內容如下:


    
    
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後一定能重啟。



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved