Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Service 詳解(包含AIDL)

Android Service 詳解(包含AIDL)

編輯:關於Android編程

博客參照< < Android開發全程實錄> >的例子 , 以及其他博客, 希望能給學習Android Service的小伙伴一個比較詳細的解釋與實踐

Service簡介

簡介

這裡寫圖片描述

生命周期

Service的生命周期比Activity的簡單, 只有3個:

創建服務: onCreate() 啟動服務: onStart() 銷毀服務: onDestroy()

其中 onCreate() 和 onDestroy() 只能被調用一次, onStart() 可以被調用多次. 使用start和bind兩種方式啟動Service的生命周期略有不同:

start方式: onCreate() -> onStartCommand() -> onStart() -> onDestroy()

bind方式: onCreate() -> onBind() -> onUnbind() -> onDestroy()

生命周期圖:
這裡寫圖片描述

兩種啟動方式的注意事項:
這裡寫圖片描述

代碼測試:
全套的生命周期Log:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> public class MyService extends Service { private final String TAG = this.getClass().getSimpleName(); public MyService() { } @Override public IBinder onBind(Intent intent) { Log.e(TAG, "onBind"); return null; } @Override public boolean onUnbind(Intent intent) { Log.e(TAG, "onUnbind"); return super.onUnbind(intent); } @Override public void onCreate() { Log.e(TAG, "onCreate"); super.onCreate(); } @Override public void onStart(Intent intent, int startId) { Log.e(TAG, "onStart"); super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); } }

別忘記注冊service:




    
        ...
        
    

通過Start方式開啟

case R.id.btn_start_service:
    Intent intent1 = new Intent(MainActivity.this, MyService.class);
    startService(intent1);
    break;
case R.id.btn_stop_service:
    Intent intent2 = new Intent(MainActivity.this, MyService.class);
    stopService(intent2);
    break;

service第一次啟動:
onCreate() -> onStartCommand() -> onStart()

再次啟動:
onStartCommand() -> onStart()

關閉Service:
onDestroy()

再次onStart():
onCreate() -> onStartCommand() -> onStart()

通過Bind方式開啟

如果通過bind方式, 除非調用過unbindService(), 否則service的生命周期和context相同, 在context被銷毀時, service自動被銷毀.
使用bind方法要復雜一點, 首先 需要一個 ServiceConnection對象, 當綁定時需要獲得一個連接, 連接可以返回一個 IBinder接口, 可通過 IBinder接口獲取 綁定Service的實例.
MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private final String TAG = this.getClass().getSimpleName();
    private Button mBtnStartServce;
        private Button mBtnStopServce;
    private Button mBtnBindServce;
    private Button mBtnUnbindServce;
    private Button mBtnDoSomeThing;
    private boolean isBind;
    private MyService mBindService;


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

        mBtnStartServce = (Button) findViewById(R.id.btn_start_service);
        mBtnStopServce = (Button) findViewById(R.id.btn_stop_service);
        mBtnBindServce = (Button) findViewById(R.id.btn_bind_service);
        mBtnUnbindServce = (Button) findViewById(R.id.btn_unbind_service);
        mBtnDoSomeThing = (Button) findViewById(R.id.btn_do_something);
        mBtnStartServce.setOnClickListener(this);
        mBtnStopServce.setOnClickListener(this);
        mBtnBindServce.setOnClickListener(this);
        mBtnUnbindServce.setOnClickListener(this);
        mBtnDoSomeThing.setOnClickListener(this);
        isBind = false;
    }

    ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.e(TAG, "onServiceConnected:" + componentName.toString());
            mBindService = ((MyService.MyBinder) iBinder).getService();
            isBind = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.e(TAG, "onServiceDisconnected");
            mBindService = null;
            isBind = false;
        }
    };

    @Override
    public void onClick(View view) {
        Intent intent = new Intent(MainActivity.this, MyService.class);
        switch (view.getId()) {
            case R.id.btn_start_service:
                startService(intent);
                break;
            case R.id.btn_stop_service:
                stopService(intent);
                break;
            case R.id.btn_bind_service:
                bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
                isBind = true;
                break;
            case R.id.btn_unbind_service:
                if (isBind) {
                    unbindService(mServiceConnection);
                    isBind = false;
                    mBindService = null;
                }
                break;
            case R.id.btn_do_something:
                if(mBindService!=null){
                    mBindService.doSomeThing();
                }
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
    }
}

MyService.java

public class MyService extends Service {
    private final String TAG = this.getClass().getSimpleName();

    public class MyBinder extends Binder {
        public MyService getService() {
            return MyService.this;
        }
    }

    public void doSomeThing() {
        Log.e(TAG, "doSomeThing");
    }

    public MyService() {
        Log.e(TAG, "MyService");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        return new MyBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
    }
}

service第一次啟動:
onCreate() -> onBind() -> onServiceConnected()

繼續點擊bind:
無響應

點擊 unbind:
onUnbind() -> onDestroy()

繼續點擊 unbind:
無響應

注意:

ServiceConnection 中的: onServiceDisconnected() 不是在 unBind() 時調用, 而是在Service被異常結束時才調用. 在Activity的 onDestroy() 方法中, 最好加上 unBinderService(), 避免因程序結束沒有接觸servcie綁定拋出異常
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
    }

AIDL遠程服務

簡介

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

總之, AIDL是Android中通過Service獲取統一接口, 進行進程間通信的的一種方法

AIDL代碼實例

寫兩個App, 一個作為Server端, 一個作為Client端. 在Server啟動服務, 在Client端綁定Server端的服務, 並獲取數據.
其實AIDL也是用bind方法綁定Service, 與前面不同的就是需要server端和cient端都定義統一的接口, 然後可以從client端得到server端的binder對象, 進而完成進程間通信.

Server端

Server端主要有3個文件修改:

創建aidl文件 創建Service

在manifest中添加 intent-filter
如下圖:
這裡寫圖片描述

創建AIDL文件, 我這裡使用的是AndroidStudio, 直接在在 package上右鍵即可New AIDL文件.
這裡寫圖片描述

AIDLService.aidl 文件

package org.xm;

interface AIDLService {
    String getServiceName();
}
注意這裡的包名是: org.xm, 而不應該是你創建aidl時點擊的package 的name, 大家自行修改.

創建Service文件
MyService.java

package org.xm.server;


public class MyService extends Service {
    private static final String TAG = "MainActivity";

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        return binder;
    }

    private AIDLService.Stub binder = new AIDLService.Stub() {

        @Override
        public String getServiceName() throws RemoteException {
            return "ServiceName";
        }

    };

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }
}

特別注意這裡要返回的binderAIDLService.Stub對象, 而不是AIDLService對象.
這裡寫圖片描述
然後我們在MainActivity啟動時啟動Service, 關閉時關閉Service:

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

        Intent intent = new Intent(MainActivity.this, MyService.class);
        startService(intent);
    }

    @Override
    protected void onDestroy() {
        Intent intent = new Intent(MainActivity.this, MyService.class);
        stopService(intent);
        super.onDestroy();
    }
最後在manifest文件中添加 intent-filter, 來接收請求:
        
            
                
            
        

注意: "org.xm.AIDLService"最好是填寫Service的名稱, 後面bind的時候發送請求需要用到這裡字段, 如果匹配上才能成功綁定.
到這裡Server端就寫完了.

Client端

Client端其實很簡單了:
1. 定義和Server端相同的aidl接口
2. 執行基本的綁定步驟, 創建connection, 然後綁定 service
這裡寫圖片描述
- AIDLService.aidl 與Server端的完全一致:

package org.xm;

interface AIDLService {
    String getServiceName();
}
在MainActivity中寫兩個按鈕, 綁定Service和獲取Service的返回值
package org.xm.client;
//...
import org.xm.AIDLService;

public class MainActivity extends AppCompatActivity {

    //...


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

        //...

        mBtnBindService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent("org.xm.AIDLService");
                intent.setPackage("org.xm.server");
                bindService(intent, mConnection, BIND_AUTO_CREATE);
            }
        });

        mBtnGetValue.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mAidlService != null) {
                    try {
                        Log.e(TAG, "result:" + mAidlService.getServiceName());
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mConnection);
    }

    private AIDLService mAidlService = null;
    ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.e(TAG, "onServiceConnected");
            mAidlService = AIDLService.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mAidlService = null;
        }
    };
}

注意:

在綁定的代碼中, 記得使用下面的方法:

Intent intent = new Intent("org.xm.AIDLService");
intent.setPackage("org.xm.server");
bindService(intent, mConnection, BIND_AUTO_CREATE);

1. 這種方法綁定不能成功

Intent intent = new Intent(MainActiity.this, AIDLService.class);
//Intent intent = new Intent(MainActiity.this,AIDLService.Stub.class);
intent.setPackage("org.xm.server");
bindService(intent, mConnection, BIND_AUTO_CREATE);

2. Service Intent must be explicit: Intent ....錯誤

一定要使用 intent.setPackage("org.xm.server");

獲取系統服務

系統自帶的一些服務:
這裡寫圖片描述
這裡寫圖片描述
獲取系統服務的方法:
這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved