Android Service 详解(包含AIDL)


Service简介

简介

这里写图片描述

生命周期

Service的生命周期比Activity的简单, 只有3个:

  • 创建服务: onCreate()
  • 启动服务: onStart()
  • 销毁服务: onDestroy()

其中 onCreate() 和 onDestroy() 只能被调用一次, onStart() 可以被调用多次. 使用start和bind两种方式启动Service的生命周期略有不同:

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

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

生命周期图:
这里写图片描述

两种启动方式的注意事项:
这里写图片描述

代码测试:
全套的生命周期Log:

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:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.xm.servicesimple">

    <application>
        ...
        <service android:name=".service.MyService" />
    </application>

</manifest>

通过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:
无响应

注意:

  1. ServiceConnection 中的: onServiceDisconnected() 不是在 unBind() 时调用, 而是在Service被异常结束时才调用.
  2. 在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个文件修改:

  1. 创建aidl文件
  2. 创建Service
  3. 在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, 来接收请求:
        <service android:name=".MyService">
            <intent-filter>
                <action android:name="org.xm.AIDLService" />
            </intent-filter>
        </service>

注意: "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");

获取系统服务

系统自带的一些服务:
这里写图片描述
这里写图片描述
获取系统服务的方法:
这里写图片描述


猜你喜欢

转载自blog.csdn.net/tanghongchang123/article/details/79885403