Service最大的特點就是無界面後臺運行,不像Activity那樣可以與用戶交互。我們可以用Service用於後臺工作,比如說下載、播放音樂等等。當然服務也是要依賴於創建服務的進程才能工作的,而且服務並不會主動開啓線程
一、創建Service
1、創建Service
右鍵New–Service–Service,修改名稱後直接創建。之後可以重新它的一些常用方法
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
//服務被創建時調用
@Override
public void onCreate() {
super.onCreate();
Log.e("MyService", "onCreate: 服務已經被創建");
}
//服務被啓動時調用,服務只能被創建一次,但是可以被調用多次
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("MyService", "onStartCommand: 服務已經啓動");
return super.onStartCommand(intent, flags, startId);
}
//服務被銷燬時調用
@Override
public void onDestroy() {
super.onDestroy();
Log.e("MyService", "onDestroy: 服務已經銷燬");
}
}
也可以手動創建一個Java文件,然後繼承與Service類,再去AndroidManifest添加Service標籤
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ice.androidpractice17_service1">
<application
android:allowBackup="true"
......
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
</service>
<activity android:name=".MainActivity">
......
</activity>
</application>
</manifest>
2、layout佈局
就放兩個button好了,一個開啓服務,另一個關閉服務
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_startService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start_Service"/>
<Button
android:id="@+id/btn_stopService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop_Service"/>
</LinearLayout>
3、Java代碼
主要是開啓和停止服務
public class MainActivity extends AppCompatActivity implements View .OnClickListener{
private Button btn_startService,btn_stopService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_startService = findViewById(R.id.btn_startService);
btn_stopService = findViewById(R.id.btn_stopService);
btn_startService.setOnClickListener(this);
btn_stopService.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_startService:
Intent intent_start = new Intent(this,MyService.class);
startService(intent_start);//開啓服務
break;
case R.id.btn_stopService:
Intent intent_stop = new Intent(this,MyService.class);
stopService(intent_stop);//停止服務,也可以在Service裏任意位置調用stopSelf()停止服務
break;
}
}
}
二、連接Service與Activity通信
上面的代碼只是開啓和停止服務,但是更多的時候要與Activity進行通信,這時候就需要在Activity與Service建立連接
1、修改佈局
新添加兩個button,分別用於綁定和解綁服務
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
.......
<Button
android:id="@+id/btn_bindService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bind_Service"/>
<Button
android:id="@+id/btn_unbindService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="unbind_Service"/>
</LinearLayout>
2、新建一個內部類
我們在MyService新建一個內部類,用於處理自己的業務邏輯,並且在onBind()方法中將其return給Activity那邊
public class MyService extends Service {
public MyService() {
}
//新建一個繼承於Binder的內部類,用於實現自己的邏輯代碼
class PlayMusicBinder extends Binder {
public void startPlayMusic(){
Log.e("DownloadBinder", "startDownload: 開始播放音樂");
}
public int getProgress(){
Log.e("DownloadBinder", "getProgress: 當前播放進度是XX%" );
return 0;
}
}
private PlayMusicBinder mBinder = new PlayMusicBinder();//實例化內部類
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return mBinder;//返回新建的內部類,Activity連接服務時會接收
}
//服務被創建時調用
@Override
public void onCreate() {
super.onCreate();
Log.e("MyService", "onCreate: 服務已經被創建");
}
......
}
3、在Activity中調用
public class MainActivity extends AppCompatActivity implements View .OnClickListener{
private Button btn_startService,btn_stopService;
private Button btn_bindService,btn_unbindService;
//新建一個匿名的ServiceConnection類,重寫連接和斷開服務的兩個方法處理自己的邏輯代碼
private ServiceConnection connection = new ServiceConnection() {
//連接服務,接收MyService類返回的mBinder
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.e("ServiceConnection", "onServiceConnected: 服務已連接");
//新建一個playMusicBinder類去實現自己的邏輯
MyService.PlayMusicBinder playMusicBinder = (MyService.PlayMusicBinder) iBinder;
playMusicBinder.startPlayMusic();
playMusicBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e("ServiceConnection", "onServiceDisconnected: 服務已斷開" );
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_startService = findViewById(R.id.btn_startService);
......
btn_unbindService.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
......
//綁定服務
case R.id.btn_bindService:
Intent bindIntent = new Intent(this,MyService.class);
bindService(bindIntent,connection,BIND_AUTO_CREATE);
break;
//斷開綁定服務
case R.id.btn_unbindService:
unbindService(connection);
break;
default:
break;
}
}
}
提示:
通過上面的代碼,我們已經可以調用Service的自定義代碼了,但是還需要注意的是:
想要destroy()服務,必須要把stopService()和unbindService()都調用
還需要注意的是,上面的代碼是在主線程執行的,耗時任務,應該開啓子線程
如果覺得Service太難用,還可以使用IntentService,會自動開啓新線程並且完成任務之後會自動停止服務