這片文章對service總結的不錯,
什麼是服務
服務是一個沒有可視化界面的組件,它可以在後臺長期運行並進行各種操作。
服務的創建
我們只需要繼承Service類並實現相應的方法即可創建服務
要想啓動服務,還得在AndroidManifest中註冊服務
服務類的示例代碼
package com.whathecode.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class ExtendsionService extendsService
{
/**
* 當服務第一次被創建的時候調用此方法
*/
@Override
publicvoid onCreate()
{
super.onCreate();
Toast.makeText(getBaseContext(),"服務被創建了", Toast.LENGTH_SHORT).show();
}
/**
* 當通過startService方法啓動服務時此方法被調用
*/
@Override
publicint onStartCommand(Intent intent,int flags, int startId)
{
Toast.makeText(getBaseContext(),"服務被啓動了", Toast.LENGTH_SHORT).show();
returnsuper.onStartCommand(intent, flags, startId);
}
@Override
publicIBinder onBind(Intent intent)
{
returnnull;
}
@Override
publicvoid onDestroy()
{
super.onDestroy();
}
}
使用startService啓動服務
主界面的邏輯代碼:
package com.whathecode.servicedemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extendsActivity
{
Intent service =null;
@Override
protectedvoid onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//創建服務
service =new Intent(this, ExtendsionService.class);
}
publicvoid start(View view)
{
//啓動服務
startService(service);
}
publicvoid stop(View view)
{
//停止服務
stopService(service);
}
}
註冊服務:
1
|
< service android:name="com.whathecode.servicedemo.BackgroundService"></ service > |
運行效果:
注意:
當我們第一次點擊啓動服務按鈕的時候,onCreate方法和onStartCommand方法依次執行,
但在第二次點擊啓動服務按鈕的時候,這個服務已經處於運行狀態,onCreate方法不再執行第二次,
而onStartCommand方法總是在調用startService啓動服務的時候執行。
onDestroy方法在stopService方法被調用後執行。
除了使用startService方法啓動服務外,我們還可以使用Bind的方式啓動服務。
前者和後者的不同在於:
服務的生命週期不依賴於啓動者。服務被啓動後一直在後臺運行直到調用stopService被停止。
使用Bind方式啓動服務,服務的生命週期依賴於啓動者。即服務在啓動者退出後自動銷燬。
使用Bind方式啓動服務
主要使用bindService方法啓動服務,unbindService方法銷燬服務。
使用此方式啓動服務的好處是,bind定成功的時候服務返回一個IBinder對象,
我們可以通過在服務類裏面實現這個對象,從而訪問服務裏面的具體方法。
從而達到和服務溝通的目的。
注意:
我們不能以直接實例化服務的方式調用裏面的方法。
另外:
如果在退出服務的時候沒有解綁,那麼程序就會拋出異常IllegalArgumentException異常。
因此,每次調用bindService啓動服務,完成後需要退出服務都需要使用unbindService 解綁。
示例代碼:
package com.whathecode.servicedemo;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
public class MainActivity extendsActivity
{
Intent service =null;
IReceptionist rpst;
/**
* bindService和unbindService方法使用的參數
*/
privateServiceConnection conn = newServiceConnection()
{
//此方法在服務連接被意外終止的時候被調用,
@Override
publicvoid onServiceDisconnected(ComponentName name)
{
}
//當服務被連接上的時候自動調用這個方法,第二個參數是服務類onBind方法中返回的對象
@Override
publicvoid onServiceConnected(ComponentName name, IBinder service)
{
rpst = (IReceptionist) service;
rpst.callExtendsionNumber();
}
};
@Override
protectedvoid onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//創建服務
service =new Intent(this, ExtendsionService.class);
}
publicvoid start(View view)
{
//啓動服務
startService(service);
}
publicvoid stop(View view)
{
//停止服務
stopService(service);
}
publicvoid bind(View view)
{
//綁定服務
bindService(service, conn , BIND_AUTO_CREATE);
}
publicvoid unBind(View view)
{
//解綁服務
unbindService(conn);
}
}
繼承ServiceBinder對象,並實現自定義接口:
通過這個方式,我們可以暴露只需要的方法,實現代碼的保護。
IReceptionist接口代碼:
package com.whathecode.servicedemo;
public interface IReceptionist
{
publicvoid callExtendsionNumber();
}
ExtendsionService服務類代碼:
package com.whathecode.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class ExtendsionService extendsService
{
privatestatic final String TAG = "ExtendsionService";
/**
* 當服務第一次被創建的時候調用此方法
*/
@Override
publicvoid onCreate()
{
super.onCreate();
Toast.makeText(getBaseContext(),"服務被創建了", Toast.LENGTH_SHORT).show();
}
/**
* 當通過startService方法啓動服務時此方法被調用
*/
@Override
publicint onStartCommand(Intent intent,int flags, int startId)
{
Toast.makeText(getBaseContext(),"服務被啓動了", Toast.LENGTH_SHORT).show();
returnsuper.onStartCommand(intent, flags, startId);
}
@Override
publicIBinder onBind(Intent intent)
{
returnnew ServiceBinder();
}
@Override
publicvoid onDestroy()
{
Toast.makeText(getBaseContext(),"服務被銷燬了", Toast.LENGTH_SHORT).show();
Log.d(TAG,"服務被銷燬了");
super.onDestroy();
}
publicvoid putExtendsion()
{
Toast.makeText(getBaseContext(),"正在幫你轉接分機", Toast.LENGTH_SHORT).show();
}
/**
*
* 繼承Binder並實現IReceptionist接口
* 繼承Binder類的目的是onBind方法中需要返回這個類型的對象
*
* 實現IReceptionist接口是暴露方法的需要
*/
privateclass ServiceBinder extends Binder implements IReceptionist
{
publicvoid callExtendsionNumber()
{
putExtendsion();
}
privatevoid otherMethod()
{
}
}
}
運行效果:
注意看上圖,我們在按下返回鍵的時候,Activity被銷燬,由它啓動的服務也跟着被銷燬。
這樣的服務貌似作用不大,有沒有辦法在退出Activity的時候不退出服務呢?
答案是有的:Android允許我們先啓動一個服務,然後再調用bindService綁定到服務,
這樣,我們既可以達到和服務溝通的目的,也可以使服務長期在後臺運行。
看下圖:
通過下面的圖,就可以更清楚地理解上面代碼的工作原理: