標籤:
Service是Android系統的服務元件,適用於開發沒有使用者介面且長時間在後台啟動並執行功能
Service簡介
因為手機硬體效能和螢幕尺寸的限制,通常Android系統僅允許一個應用程式處於啟用狀態並顯示在手機螢幕上,而暫停其他處於未啟用狀態的程式。因此,Android系統需要一種後台服務機制,允許在沒有使用者介面的情況下,使程式能夠長時間在後台運行,實現應用程式的後台服務功能。在實際應用中,有很多應用需要使用Service,比如MP3播放器要求在關閉播放器介面後,仍然能夠後台保持音樂持續播放。
下面我將Service基礎知識簡單歸納為以下6點:
- 1.Service適用於什麼功能?
Service使用於無須使用者幹預,且有規則地運行或長期啟動並執行後台共功能。
- 2.Service的特點
Service沒有使用者介面,相比於其他應用程式更加有利於降低系統資源的消耗。Service比Activity具有更高優先順序,在資源緊張時,Service不會被Android系統優先終止。即使Service被系統終止,在系統資源恢複後Service也將自動回複運行狀態,因此可以認為Service是在系統中可以穩定長期啟動並執行組件。
- 3.Service的用處
1.實現後台服務功能2.可用於處理序間通訊
- 4.Service的生命週期
完整的生命週期從onCreate()開始到onDestroy()結束,在onCreate()中完成Service的初始化工作,在onDestroy()中釋放所有佔用的資源。可以粗略的認為活動生命週期以onDestroy()標誌結束。
- 5.通過啟動方式使用Service
實現
通過Context.startService()啟動Service,通過Context.stopService()停止Seivice。Context指其他組件,因此Service一定是由其它組件啟動的,但停止過程可以通過其他組件或自身完成。
特點
啟動Service的組件無法擷取Service的對象執行個體,因此也無法調用Service中的任何函數,也不能擷取Service中的任何狀態和資料資訊。所以以啟動方式的Service需要具備自管理的能力。
- 6.通過綁定方式使用Service
實現
在其他組件中調用Context.bindService()建立服務串連,調用Context.unbindService()停止服務串連。如果在綁定過程中Service未啟動,Context.bindService()會自動啟動Service。
特點
其他組件可以擷取Service的執行個體對象並調用Service中的函數,可以擷取Service中的狀態和資料資訊。同一個Service可以和被多個組件綁定服務串連,即同一個Service可以同時為多個元件服務。
本地服務
概念: 本地服務的調用者和服務都在同一個程式中,是不需要跨進程就可以實現服務的調用。
以下為一個設計到本地服務的簡單Demo,包括啟動方式和綁定方式的使用。主介面
項目結構
RandomService.java(啟動方式)完整代碼:
package com.example.servicedemo;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.support.annotation.Nullable;import android.widget.Toast;/** * Created by yinghao on 2016/5/6. */public class RandomService extends Service { /* onStartCommand 取代 onStart 但在 super.onStartCommand(intent, flags, startId); 方法中調用了 onStart()方法(為了相容) */ private Thread workThread; @Override public void onCreate() { super.onCreate(); Toast.makeText(this, "調用onCreate()", Toast.LENGTH_SHORT).show(); workThread = new Thread(null, backgroundWork, "workThread"); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); Toast.makeText(RandomService.this, "onStart()", Toast.LENGTH_SHORT).show(); if (!workThread.isAlive()) { workThread.start(); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(RandomService.this, "onStartCommand()", Toast.LENGTH_SHORT).show(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Toast.makeText(this, "調用onDestroy()", Toast.LENGTH_SHORT).show(); workThread.interrupt(); super.onDestroy(); } private Runnable backgroundWork = new Runnable() { @Override public void run() { try { while (!Thread.interrupted()) { double randomDouble = Math.random(); MainActivity.UpdateGUI(randomDouble); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } }; /** * Service 被綁定後調用的函數,能夠返回Service對象執行個體 */ @Nullable @Override public IBinder onBind(Intent intent) { return null; }}
MathService.java(綁定方式)完整代碼:
package com.example.servicedemo;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.support.annotation.Nullable;import android.widget.Toast;/** * Created by yinghao on 2016/5/6. */public class MathService extends Service { /** * 以綁定形式使用此Service 擷取Service執行個體 */ private final IBinder mBinder = new LocalBinder(); public class LocalBinder extends Binder{ MathService getService() { return MathService.this; } } @Nullable @Override public IBinder onBind(Intent intent) { Toast.makeText(MathService.this, "本地綁定", Toast.LENGTH_SHORT).show(); return mBinder; } @Override public boolean onUnbind(Intent intent) { Toast.makeText(MathService.this, "取消本地綁定:MathService", Toast.LENGTH_SHORT).show(); return super.onUnbind(intent); } public long add(long a, long b) { return a + b; }}
MainActivity.java完整代碼:
package com.example.servicedemo;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Handler;import android.os.IBinder;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import com.example.simplerandomservicedemo.R;public class MainActivity extends AppCompatActivity { private Button mStartButton; private Button mStopButton; private static TextView mLabelTextVie; private static Handler handler = new Handler(); private static double random; /** * Handler 將Runnable對象 傳遞給 介面線程的隊列中 * 使其能更新UI */ public static void UpdateGUI(double refreshDouble) { random = refreshDouble; handler.post(RefreshLable); } public static Runnable RefreshLable = new Runnable() { @Override public void run() { mLabelTextVie.setText(String.valueOf(random)); } }; private MathService mathService; private boolean isBound = false; private TextView sum; private Button bindButton; private Button unbindButton; private Button addButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** * Handler */ final Intent intent = new Intent(this,RandomService.class); mStartButton = (Button) findViewById(R.id.start); mStopButton = (Button) findViewById(R.id.stop); mLabelTextVie = (TextView) findViewById(R.id.tv_label); mStartButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startService(intent); } }); mStopButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(intent); } }); /** * bind Service */ sum = (TextView) findViewById(R.id.tv_result); bindButton = (Button) findViewById(R.id.bind); unbindButton = (Button) findViewById(R.id.unbind); addButton = (Button) findViewById(R.id.add); final Intent serviceIntent = new Intent(MainActivity.this, MathService.class); bindButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!isBound) { bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE); isBound = true; } } }); unbindButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isBound) { unbindService(mConnection); //若把上面取消綁定改為下面的關閉Service 則無法再次綁定成功// stopService(serviceIntent); mathService = null; isBound = false; } } }); addButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mathService == null) { sum.setText("未綁定服務"); return; } long a = Math.round(Math.random() * 100); long b = Math.round(Math.random() * 100); long result = mathService.add(a, b); String msg = String.valueOf(a)+"+"+String.valueOf(b)+"="+result; sum.setText(msg); } }); } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mathService = ((MathService.LocalBinder) service).getService(); } @Override public void onServiceDisconnected(ComponentName name) { mathService = null; } };}
Android Service 後台服務之本地服務