首页 > 代码库 > Android -Services 使用简介

Android -Services 使用简介

Android Services 四大组件之一,主要用于后台长时间运行。没有界面。这里讲解两种services的启动还有AIDL通信方式。

1.startservices

a.建立继承services的类,复写方法(本地服务)

 

public class MyServices extends Service  {    private static final String TAG="TestTag";    @Override    public IBinder onBind(Intent arg0) {        // TODO Auto-generated method stub        return null;    }    @Override    public void onCreate() {        Log.i(TAG, "onCreate");        super.onCreate();    }    @Override    public void onStart(Intent intent, int startId) {        Log.i(TAG, "onStart");        super.onStart(intent, startId);    }    @Override    public void onDestroy() {        Log.i(TAG, "onDestroy");        super.onDestroy();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.i(TAG, "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }}

b.声明AndroidManifest

<service android:name=".MyServices"/>

 

c.启动关闭

switch(v.getId()){                case R.id.btnStart:                    startService(intent);                    break;                case R.id.btnStop:                    stopService(intent);                    break;  }

 

后记:

服务生命周期:context.startService() ->onCreate()- >onStart()- >onStartCommand()->Service running ->context.stopService()  ->onDestroy() ->Service stop

如果Service还没有运行,则android先调用onCreate()然后调用onStartCommand(),每次调用startService(Intent)的时候,都会调用执行onStartCommand();
如果Service已经运行,则只调用onStartCommand()。

2.bindservices

服务链接(ServiceConnection)或直接获取Service中状态和数据信息 
服务链接能够获取Service的对象,因此绑定Service的组件可以调用Service中的实现的函数 
使用Service的组件通过Context.bindService()建立服务链接,通过Context.unbindService()停止服务链接 
如果在绑定过程中Service没有启动,Context.bindService()会自动启动Service 
同一个Service可以绑定多个服务链接,这样可以同时为多个不同的组件提供服务

a.创建BindService继承Service

public class BindService extends Service {    private static final String TAG="BindService";    private BindServiceX myBinderServiceX=new BindServiceX();    public class BindServiceX extends Binder{        public BindService getBindService() {            return BindService.this;        }    }    @Override    public IBinder onBind(Intent arg0) {        // TODO Auto-generated method stub        Log.i(TAG, "onBind");        return myBinderServiceX;    }    @Override    public void onCreate() {        Log.i(TAG, "onCreate");        super.onCreate();    }    @Override    public boolean onUnbind(Intent intent) {        Log.i(TAG, "onUnbind");        return super.onUnbind(intent);    }    @Override    public void onDestroy() {        Log.i(TAG, "onDestroy");        super.onDestroy();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.i(TAG, "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }    public void ShowLog(){        Log.i(TAG, "BindService=>ShowLog");    }}

b.声明AndroidManifest

<service android:name=".BindService"/>

c.启动使用

public void onClick(View v) {            Intent intentBind = new Intent(MainActivity.this, BindService.class);            switch (v.getId()) {                case R.id.btnStartBindService:                    bindService(intentBind, conn, Context.BIND_AUTO_CREATE);                    break;                case R.id.btnStopBindService:                    if (isConn) {                        unbindService(conn); //不可以多次调用                        isConn=false;                    }                    break;            }

后记:

AndroidServiceActivity绑定方法,Context.BIND_AUTO_CREATE表明只要绑定存在,就自动建立Service;同时也告知Android系统,这个Service的重要程度与调用者相同,除非考虑终止调用者,否则不要关闭这个Service。

如果service没被创建,那么调用一次onCreate(),然后调用onBind(),多次绑定时,不会多次调用onBind()。

通过unbindService()函数取消绑定Servcie时,onUnbind()函数将被调用, 
如果onUnbind()函数的返回true,则表示在调用者绑定新服务时, 
onRebind()函数将被调用

取消绑定仅需要使用unbindService()方法,并将ServiceConnnection传递给unbindService()方法需注意的是,unbindService()方法成功后,系统并不会调用onServiceDisconnected(),因为onServiceDisconnected()仅在意外断开绑定时才被调用

3.AIDL IPC通信 services

Android系统中,各个应用都运行在自己的进程中,进程之间一般无法直接进行通信,为了实现进程通信(interprocess communication,简称IPC),android提供了AIDL Service;  

Android需要AIDL(Android Interface Definition Language)来定义远程接口,这种接口定义语言并不是一种真正的变成语言,只是定义两个进程之间的通信接口 

与Java接口相似,但是存在如下几点差异  

  • AIDL定义接口的源代码必须以.aidl结尾  

  • AIDL用到的数据类型,除了基本类型、String、List、Map、CharSequence之外,其它类型全部都需要导包,即使它们在同一个包中也需要导包; 

 AIDL的步骤:

a.创建AIDL文件

package com.example.zcx.servicesdemo;// Declare any non-default types here with import statements//interface ICat {//    /**//     * Demonstrates some basic types that you can use as parameters//     * and return values in AIDL.//     *///    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,//            double aDouble, String aString);//}interface ICat {    String getColor();    double getWeight();}

b.服务端编写

public class AidlService extends Service {    String[] colors = new String[] { "红色", "黄色", "黑色" };    double[] weights = new double[] { 2.3, 3.1, 1.58 };    private String color;    private double weight;    private CatBinder catBinder;    Timer timer = new Timer();    @Override    public void onCreate() {        super.onCreate();        catBinder = new CatBinder();        timer.schedule(new TimerTask() {            @Override            public void run() {                // 随机地改变service组件内的color,weight属性的值                int rand = (int) (Math.random() * 3);                color = colors[rand];                weight = weights[rand];                System.out.println("---------" + rand);            }        }, 0, 800);    }    @Override    public IBinder onBind(Intent arg0) {        /**         * 返回CatBinder对象,在绑定本地Service情况下,         * 该catBinder会直接传给客户端的ServiceConnected对象的ServiceConnected         * ()方法的第二个参数;在绑定远程Service的情况下         * ,只将catBinder对象的代理传给客户端的ServiceConnected对象的ServiceConnected()方法的第二个参数         */        return catBinder;    }    @Override    public void onDestroy() {        timer.cancel();    }    /**     * 继承Stub,也就是实现了ICat接口,并实现了IBinder接口     *     * @author pengcx     *     */    public class CatBinder extends ICat.Stub {        @Override        public String getColor() throws RemoteException {            return color;        }        @Override        public double getWeight() throws RemoteException {            return weight;        }    }}

androidmanifest:

<service android:name=".AidlService" android:process=":remote">            <intent-filter>                <action android:name="org.crazyit.aidl.AIDL_SERVICE" />            </intent-filter></service>

c.客户端使用

首先需要建立aidl,注意要在相同的包名下,否则报错: java.lang.SecurityException: Binder invocation to an incorrect interface

// ICat.aidlpackage com.example.zcx.servicesdemo;// Declare any non-default types here with import statements//interface ICat {//    /**//     * Demonstrates some basic types that you can use as parameters//     * and return values in AIDL.//     *///    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,//            double aDouble, String aString);//}interface ICat {    String getColor();    double getWeight();}

编写客户端:

public class MainActivity extends AppCompatActivity {    private ICat catService;    private Button getButton;    private EditText colorEditText, weightEditText;    private ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceDisconnected(ComponentName name) {            catService = null;        }        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            // 获取远程Service的onBinder方法返回的对象代理            catService = ICat.Stub.asInterface(service);            Log.d("zcx","catService");        }    };    public static Intent getExplicitIntent(Context context, Intent implicitIntent) {        // Retrieve all services that can match the given intent        PackageManager pm = context.getPackageManager();        List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);        // Make sure only one match was found        if (resolveInfo == null || resolveInfo.size() != 1) {            return null;        }        // Get component info and create ComponentName        ResolveInfo serviceInfo = resolveInfo.get(0);        String packageName = serviceInfo.serviceInfo.packageName;        String className = serviceInfo.serviceInfo.name;        ComponentName component = new ComponentName(packageName, className);        // Create a new intent. Use the old one for extras and such reuse        Intent explicitIntent = new Intent(implicitIntent);        // Set the component to be explicit        explicitIntent.setComponent(component);        return explicitIntent;    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        getButton = (Button) findViewById(R.id.getbutton);        colorEditText = (EditText) findViewById(R.id.coloredittext);        weightEditText = (EditText) findViewById(R.id.weightedittext);        // 创建所需要绑定的Service的Intent        Intent intent = new Intent();        intent.setAction("org.crazyit.aidl.AIDL_SERVICE");        //intent.setPackage(getPackageName());        Intent eintent = new Intent(getExplicitIntent(this,intent));        Log.e("zcx","eintent = "+eintent);        // 绑定远程的服务        Log.e("zcx"," "+bindService(eintent, conn, Service.BIND_AUTO_CREATE));        getButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                // 获取并显示远程service的状态                try {                    colorEditText.setText(catService.getColor());                    weightEditText.setText(catService.getWeight() + "");                } catch (RemoteException e) {                    e.printStackTrace();                }            }        });    }    @Override    protected void onDestroy() {        super.onDestroy();        // 解除绑定        this.unbindService(conn);    }}

 

Android -Services 使用简介