[Android] Service初步應用

本篇將介紹Service的初步應用,利用Button來開始或取消Service的動作。

Service,可用於後台執行的程式,可不開啟Activity,並執行一些動作,如網路上下載、音樂撥放等等...通常可再搭配Notify功能,當Service完成某項任務時,利用Notify可彈出提醒視窗。而Service又分為綁定型與非綁定型Service,其綁定型需依附於Activity,如果Activity終止,則Service也會終止,非綁定的則否。本篇則是以非綁定Service做範例。

圖為一個非綁定型Service的Lifecycle,當啟用開Service時,需調用stopService()才能使該Service進入onDestroy()內終止該Service。

以下將示範利用一個Activity介面,點擊Button開始Service或停止Service,由於此示範為獨立式Service非綁定式Service,因此在Start Service後,關閉應用程式,Service依然在背景上執行,需再開啟應用程式將其Service stop才可停止。

 private Intent samIntent;
    private Button startbtn,stopbtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        samIntent=new Intent(MainActivity.this,samService.class); //使用Intent,由MainActivity對SamService
        startbtn=(Button)findViewById(R.id.startbtnID);
        stopbtn=(Button)findViewById(R.id.stopbtnID);
        startbtn.setOnClickListener(new btnclicklistener());
        stopbtn.setOnClickListener(new btnclicklistener());
    }

首先將所需的Button與 Intent定義出來,開啟Service的方式需建立一個Intent來開啟,以上綁定ID與Click綁定後,接著再ClickListener內加入以下

class btnclicklistener implements View.OnClickListener{

        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.startbtnID:
                    startService(samIntent);
                    break;

                case R.id.stopbtnID:
                    stopService(samIntent);
                    break;
            }
        }
    }

onClick內判斷是否為Start Button或Stop Button,並使用startService(Intent)或stopService(Intent)來開啟Service或關閉Service。

接著再另外新增一個Class如下圖

,並繼承於Service ,接著建立一個Handler給要呼叫Runnable時使用,並建立一個Runnable 名為 showTime,其function會Log出目前的時間

public class samService extends Service{

    private Handler handler1=new Handler();
    private Runnable showTime=new Runnable() {
        @Override
        public void run() {
         Log.i("mylog",new Date().toString()); //Log出目前時間
            handler1.postDelayed(this,1000);   //使此Runnable每1秒重Run一次
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate(){
        Log.i("samLog","Enter onCreate()");
        super.onCreate();
        Log.i("samLog", "Leave onCreate()");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("samLog","Enter onStartCommand()");
        handler1.post(showTime);     //開啟此Service時,執行showTime
        return Service.START_STICKY; //一個返回值,如果此Service被異常終止時,將嘗試重新開啟此Service
    }

    @Override
    public void onDestroy() {                    //除非調用stopService(),否則不會進入此區塊
        Log.i("samLog","Enter onDestroy()");
        super.onDestroy();
        handler1.removeCallbacks(showTime);     //利用removeCallbacks()停止handler.post(showTime)
        Log.i("samLog","Leave onDestroy()");
    }
}

接著在onStartCommand內使用handler1.post(showTime)啟用Runnable,其中onStartCommand內的 return Service.START_STICKY,當該Service被異常刪除時,將會重新啟動該Service,

因此除非調用stopService(),否則該Service將不會進到 onDestroy()區塊。