(service)服務詳解
阿新 • • 發佈:2019-01-09
##01_start開啟服務的生命週期(重點)
-
服務的特點:
-
生命週期的方法:
onCreate: 初始化service的例項物件;
onStartCommand:開啟服務;
onDestroy:銷燬例項物件之前呼叫這個方法做掃尾工作;
onResume、onPause、onStop、onRestart等生命週期的都沒有,因為沒有介面;
##02_bind方式開啟服務的生命週期(重點)
使用的方法:
bindService:繫結服務、開啟服務;
unbindService:解除繫結的服務、停止服務;
特點:
1、第一次繫結服務時,先建立一個服務物件oncreate,然後繫結服務onBind; 2、解除繫結的服務時,先解除繫結服務,然後銷燬服務的例項物件; 3、服務只能被繫結一次,多次繫結不會執行任何操作; 4、服務只能解除一次,如果多次解除繫結程式會丟擲異常; 5、當介面關閉時,服務就被解除綁定了;
推薦的混合開啟服務的方式:
1、startService:使用這種方式開啟服務,可以讓服務長期執行在後臺;
2、bindService:繫結服務,為了呼叫服務裡面的業務邏輯方法;
3、unbindService:解除繫結,為了不再呼叫服務裡面的業務邏輯方法;
4、stopService:停止服務,不再使用服務物件;
##03_為什麼要引入bindservice的API
目的:為了讓應用程式能夠呼叫服務裡面的業務邏輯方法;
##04_繫結服務呼叫服務方法的過程
步驟: 1、在服務的類裡面寫中間人的內部類,讓它IBinder介面,目的是為onBind返回中間人這個型別: 2、在中間人內部寫一個方法,在這個方法裡面呼叫服務處的業務邏輯方法: 3、在activity中繫結服務成功時,得到中間人的物件; 4、在activity中呼叫中間人的方法,就相當於間接地呼叫服務的業務邏輯方法:
程式碼:
TestService.java:
package com.itheima.testservice; import java.io.FileDescriptor; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; import android.os.RemoteException; import android.widget.Toast; public class TestService extends Service { /** * 應用程式繫結服務物件時會呼叫這個方法 * 繫結服務 */ @Override public IBinder onBind(Intent intent) { System.out.println("--------onBind-----------"); //繫結服務時返回中間人物件 return new MyBinder(); } /** * * 解除繫結的服務時呼叫這個方法 */ @Override public boolean onUnbind(Intent intent) { System.out.println("--------onUnbind-----------"); return super.onUnbind(intent); } @Override public void onCreate() { super.onCreate(); System.out.println("--------onCreate-----------"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("--------onStartCommand-----------"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); System.out.println("--------onDestroy-----------"); } /** * 服務的業務邏輯方法 */ public void methodInService() { System.out.println("=======methodInService=================="); Toast.makeText(this, "tishi", 0).show(); } /** * 1、中間人 * @author Administrator * */ public class MyBinder extends Binder{ //2、在中間人內部寫一個方法,在這個方法裡面呼叫服務處的業務邏輯方法: public void callMethodInService(){ //呼叫服務的業務邏輯方法 methodInService(); } } }
MainActivity.java:
package com.itheima.testservice;
import com.itheima.testservice.TestService.MyBinder;
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 extends Activity {
private Intent intent;
private MyConn conn;
private MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start(View view) {
intent = new Intent(this, TestService.class);
startService(intent);
}
public void stop(View view) {
stopService(intent);
}
public void call(View view){
//4、在activity中呼叫中間人的方法,就相當於間接地呼叫服務的業務邏輯方法:
myBinder.callMethodInService();
}
public void bind(View view) {
//intent = new Intent(this, TestService.class);
conn = new MyConn();
//intent 開啟service使用的intent
//MyConn 應用程式與服務之間建立的連線
//開啟服務時如果服務物件不存在,就會自動建立一個服務物件
bindService(intent,conn, BIND_AUTO_CREATE);
}
public void unbind(View view) {
//解除繫結的服務
unbindService(conn);
}
private class MyConn implements ServiceConnection {
/**
* 繫結服務成功會呼叫這個方法 讓應用程式與service之間建立一個連線,就是通訊的通道
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyBinder) service;
}
/**
* 服務的連線崩潰的時候呼叫這方方法
*/
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
##05_繫結服務抽取介面(重點)
介面的作用:對外暴露功能,隱藏實現的細節;
步驟:
1、在工程裡面新增一個介面,裡面寫一個方法,對外開放的方法:
2、讓中間人實現這個介面,為了讓中間人具有介面的角色(型別),中間人需要實現接口裡面的方法;
3、在activity中繫結服務成功時得到介面型別的物件;
4、在activity中呼叫介面型別的中間人的方法;
程式碼:
IService.java:
package com.itheima.testservice.service;
public interface IService {
public void callMethodInService();
}
TestService.java:
package com.itheima.testservice;
import com.itheima.testservice.service.IService;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.view.View;
import android.widget.Toast;
public class TestService extends Service {
/**
* 應用程式繫結服務物件時會呼叫這個方法
* 繫結服務
*/
@Override
public IBinder onBind(Intent intent) {
System.out.println("--------onBind-----------");
//繫結服務時返回中間人物件
return new MyBinder();
}
/**
*
* 解除繫結的服務時呼叫這個方法
*/
@Override
public boolean onUnbind(Intent intent) {
System.out.println("--------onUnbind-----------");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("--------onCreate-----------");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("--------onStartCommand-----------");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("--------onDestroy-----------");
}
/**
* 服務的業務邏輯方法
*/
public void methodInService() {
System.out.println("=======methodInService==================");
Toast.makeText(this, "tishi", 0).show();
}
public void eat(){
System.out.println("=======eat==================");
}
public void nj(){
System.out.println("=======nj==================");
}
public void xsn(){
System.out.println("=======xsn==================");
}
/**
* 1、中間人
* @author Administrator
*
*/
private class MyBinder extends Binder implements IService{
// //2、在中間人內部寫一個方法,在這個方法裡面呼叫服務處的業務邏輯方法:
// public void callMethodInService(){
// //呼叫服務的業務邏輯方法
// methodInService();
// }
public void callEat(){
eat();
}
public void callXsn(){
xsn();
}
/**
* 2、實現介面中的方法,在這方法裡面呼叫服務的業務邏輯方法
*/
@Override
public void callMethodInService() {
//呼叫服務的業務邏輯方法
methodInService();
}
}
}
MainActivity.java:
package com.itheima.testservice;
import com.itheima.testservice.service.IService;
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 extends Activity {
private Intent intent;
private MyConn conn;
// private MyBinder myBinder;
private IService myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start(View view) {
intent = new Intent(this, TestService.class);
startService(intent);
}
public void stop(View view) {
stopService(intent);
}
public void call(View view) {
// 4、在activity中呼叫中間人的方法,就相當於間接地呼叫服務的業務邏輯方法:
myBinder.callMethodInService();
}
public void bind(View view) {
//intent = new Intent(this, TestService.class);
conn = new MyConn();
// intent 開啟service使用的intent
// MyConn 應用程式與服務之間建立的連線
// 開啟服務時如果服務物件不存在,就會自動建立一個服務物件
bindService(intent, conn, BIND_AUTO_CREATE);
}
public void unbind(View view) {
// 解除繫結的服務
unbindService(conn);
}
private class MyConn implements ServiceConnection {
/**
* 繫結服務成功會呼叫這個方法 讓應用程式與service之間建立一個連線,就是通訊的通道
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// myBinder = (MyBinder) service;
//3、在activity中繫結服務成功時得到介面型別的物件;
myBinder = (IService) service;
/**
* 服務的連線崩潰的時候呼叫這方方法
*/
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
##06_服務的應用場景
應用場景:天氣預報、股票軟體,檢測網路狀態提交資料;
##07_利用服務註冊廣播接收者
使用程式碼註冊廣播接收者的目的:有些操作比較頻繁的廣播事件,如果使用配置檔案來註冊,每次在接收廣播事件的時候都需要讀取配置,這樣比較耗時並且佔用的資源比較大。如果使用程式碼註冊廣播接收者會比較省時和節省資源。
模版程式碼:
//1、建立廣播接收者的物件
ScreenBroadcastReceiver receiver = new ScreenBroadcastReceiver();
//2、建立IntentFilter
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.SCREEN_OFF");
filter.addAction("android.intent.action.SCREEN_ON");
//3、註冊廣播接收者
registerReceiver(receiver, filter);
##08_遠端服務aidl的寫法(重點)
遠端服務:在同一個裝置安裝的另一個應用程式,在這應用程式中有一個服務在執行。
本地服務:服務的類是寫在當前應用程式裡面的。
在本地的應用程式中呼叫另一個工程裡面的服務的方法。
aidl:Android Interface Definition Language 安卓的介面定義語言;
aidl格式的檔案都是對外開放的共享檔案,可以把它拷貝到其他工程裡使用;
IPC:Inter Process communication程序間的通訊;
步驟:
1、在遠端工程裡面新增一個介面,裡面寫一個方法,對外開放的方法:
2、讓中間人實現這個介面,為了讓中間人具有介面的角色(型別),中間人需要實現接口裡面的方法:
修改IService介面的副檔名為aidl,為了寫一個對外開放的共享檔案,讓中間人繼承Stub;
3、在本地應用程式的activity中繫結服務成功時得到介面型別的物件:
在本地工程中建立了一個與遠端服務工程一樣的包,把aidl檔案拷貝到這個包裡;
4、在本地應用程式activity中繫結服務成功時得到IService介面型別的中間人物件:
遠端服務:
package com.itheima.remoteservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.itheima.remoteservice.IService.Stub;
public class TestService extends Service {
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
public void methodInService(){
System.out.println("----------methodInService----------");
}
private class MyBinder extends Stub{
/**
* 實現介面中的方法
*/
@Override
public void callMethodInService() {
//呼叫了服務的業務邏輯方法
methodInService();
}
}
}
本地應用程式程式碼:
package com.itheima.localapp;
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.os.RemoteException;
import android.view.View;
import com.itheima.remoteservice.IService;
import com.itheima.remoteservice.IService.Stub;
public class MainActivity extends Activity {
private Intent intent;
private MyConn conn;
private IService myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start(View view) {
intent = new Intent();
intent.setAction("com.itheima.remoteservice.REMOTESERVICE");
startService(intent);
}
public void bind(View view) {
conn = new MyConn();
bindService(intent, conn, BIND_AUTO_CREATE);
}
public void unbind(View view) {
unbindService(conn);
}
public void stop(View view) {
stopService(intent);
}
public void call(View view){
try {
//呼叫介面的方法,間接地呼叫服務的業務邏輯方法
myBinder.callMethodInService();
} catch (RemoteException e) {
e.printStackTrace();
}
}
private class MyConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//得到IService介面型別的物件
myBinder = Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
}
}