Android Service全解析(一)

Service全解析(一)

==1.Service基本介绍==
==2.启动模式下的Service==
==3.绑定模式下的Service==

==4.与Remote Service数据交互==

  首先看一下Service的生命周期,启动模式(startService()/stopService)下的生命周期为:
onCreate() —-> onStartCommand() —-> onDestroy() ;
绑定模式下:onCreate() —-> onBind() —->onBind() —-> onDestroy() ;
  启动模式下不会执行onStartCommand()方法,所以逻辑处理放在onCreate()中。
需要注意的一点是5.0版本以上的隐式启动,Intent需要setPackage,否则会报错;


绑定模式下Service的onBind()方法会返回一个 Binder对象,在调用bindService()方法的地方得到这个Binder对象,从而实现与Service的交互。
Binder 继承 IBinder。

代码分析(省略了部分无关方法)

public class CountSumService extends Service {

    private ServiceBinder serviceBinder = new ServiceBinder();

    @Override
    public IBinder onBind(Intent intent) {
        Log.v("out","onBind()");
        return serviceBinder;
    }

    public void test(){
        Log.v("out","service test demo");
    }

    public class ServiceBinder extends Binder{
        public CountSumService getService(){
            return CountSumService.this;
        }
    }
}

Service内部创建了一个 了Binder的类,然后在onBind()方法中返回了这个类的实例,这个实例在创建ServiceConnection的onServiceConnected()方法中可以拿到。


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        setContentView(R.layout.activity_service_demo);
        conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.v("out",name.toString());
                IBinder temp = service;
                if(service!=null) {
                    countSumService = ((CountSumService.ServiceBinder) service).getService();
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                countSumService = null;
            }
        };
        mContext.bindService(new Intent(ServiceDemoActivity.this,CountSumService.class) ,conn,BIND_AUTO_CREATE);
        //countSumService.test();
        Log.v("out","断点");
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (countSumService==null){
                    if(countSumService!=null){
                        countSumService.test();
                    }
                }
            }
        }).start();
    }

创建ServiceConnection的onServiceConnected()方法得到Service中返回的Binder对象。
这里有一个坑:得到这个Binder对象是异步的不是同步的,所以你bindService()后不能直接得到binder对象,一般都是在onServiceConnected()方法中使用;如果非得在外面使用,可以像我这样开一个线程来获取。

Remote Service
上面讲的都是与本地Service交互,那么远程Service呢,与Remote Service交互涉及到IPC, 通常有这3种方式实现:
==1.广播==
==2.AIDL==
==3.Message==
这里主要讲后两张方法。
先看AIDL方式的实现:
(1)创建一个Remote Service,AndroidManifest.xml文件配置Service属性:两种方式,第一:android:process = “remote”,这种方式创建的Service会运行在一个新进程中,但是这一个新的进程是公有的,也就是说其他的应用也可以运行在这个进程中;第二:android:process=”:任意字符”,(注意:号)这样创建的是一个私有新程。
(2)与本地Service不同的地方在于,本地Service我们自己创建一个继承与Binder的类,而远程Service需要通过创建.aidl文件来自动为我们生成一个Binder类。
(3)下面介绍在AS中创建aidl文件:
 a.切换到Project状态
b.右键c/in/java目录,new —-> AIDL文件,生成的aidl文件会自动放到与java同级的AIDL文件夹下。

import com.wangliang160616.androidtest.model.student;
interface IMyAidlInterface {

    void setStuInfo(in student stu);
    void setAge(int age);

}

注意:import需要手动写。
你以为这就完了,too yang too simple
传递基本数据类型和String,CharSequence,List,Map这些是ok的,但是如果是自己定义的Model,比如我码中的student类,要跨进程传递,应该这样做:
(1)自定义的类继承Parcelable
(2)在你放这个model的包上右键new aidl,先随便起一个名字,等他自动生成后将名字改成与你这个Model同名的名字。
(3)Build –> make project ,AS自动生成java文件,这个java 文件在哪呢,资料上都说在gen目录下,但是在AS下面根本没有gen目录,在app/build/generate/source/aidl,题外话,R文件app/build/generate/source/r下面
(4)回到Service,onBind()方法返回根据AIDL文件自动生成的java类中的Stup对象即可。看代码:

public class RemoteService extends Service {

    private student data;
    private int age;

    private IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub(){

        @Override
        public void setStuInfo(student stu) throws RemoteException {
            if(stu!=null){
                data = stu;
            }
            Log.v("out","当前Service pid:"+android.os.Process.myPid());
            Log.v("out","姓名:"+data.getStuName()+"/id:"+data.getStuId());
        }

        @Override
        public void setAge(int age) throws RemoteException {
            data.setStuId(age);
            Log.v("out","姓名:"+data.getStuName()+"/id:"+data.getStuId());
        }
    };

    public RemoteService() {
    }

    @Override
    public IBinder onBind(Intent intent) throws UnsupportedOperationException{
        return  mBinder;
    }
}

(5)在activity中这样
IMyAidlInterface Service = IMyAidlInterface.Stub.asInterface(service);
得到Binder对象。

==还有有一种通过Messenger方式来通信的,在(二)中我会介绍这种方法。==

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值