• Android--绑定服务调用服务的方法


    Service依照其启动的方式,可分为两种:
    1、Started
    Started的Service。通过在Application里用startService(Intent intent)方法来启动。这样的类型的Service一经启动。会在后面无休止地执行,即使启动它的Activity被Destroy掉。要停止此类型的Service,可在Service中调用stopSelf()或在Application中调用stopService(Intent intent),要不然就仅仅能等Android系统在系统资源紧张的时候把它杀掉。



    2、Bound

    Bound的Service。通过在Application里调用bindService()方法来启动。

    该类型的Service与Application绑定在一起,一旦绑定的全部Application消失了,Android会Detroy掉该Service。也能够主动调用unbindService()方法来解绑Service。


    有时候我们想在Activity中获知Service的状态,比如一个音乐播放器。Service负责音乐播放,Activity负责显示当前歌曲名和播放进度。

    能够用Broadcast。这个也不失为一个解决方法。

    但假设能够获取Service实例,那么就能够调用Service中自己定义的一些方法来获取Service状态了。

    首先要明白的是,第一种类型的Service是无能为力的。

    由于Activity与Service之间并没有相关联的接口。即使这个Service是在Activity里start的,一旦start,两者不再有关联。

    一、本地Service调用。

    假设Activity与Service在同一应用程序中。两者间的交互就属于本地Service调用。

    可通过bindService实现。详细操作例如以下:

    1、自己定义子类MyService。继承Service类
    2、在MyService类中,自己定义内部类MyBinder,继承Binder类

    在内部类中,依据须要交互的数据,创建一些方法,以便Activity可通过这些方法得到Service中的一些数据。或者干脆通过一个方法返回Service实例。

    public class MyBinder extends Binder  
    {  
    public MyService getServiceInstance()  
    {  
    return MyService.this;  
    }  
    }  
    3、在Service类中,new一个MyBinder私有成员。并在onBind()方法中return一个MyBinder实例。

    之所以这样做,是由于Service一旦绑定,就会回调onBind()方法,并返回一个Binder对象给Activity。详细看下一个步骤。


    4、在Activity中覆写ServiceConnection接口中的onServiceConnected(ComponentName name, IBinder service)方法,

    当中的service參数就是MyService类中onBind()方法返回的MyBinder对象,调用MyBinder对象的自己定义方法getServiceInstance()可得到Service实例。

    以下是一个DEMO:

    import android.os.Bundle;
    import android.os.IBinder;
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.view.Menu;
    import android.view.View;
    
    public class MainActivity extends Activity {
    
    	MusicInterface mi;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent intent = new Intent(this, MusicService.class);
            //混合调用
            //为了把服务所在进程变成服务进程
            startService(intent);
            //为了拿到中间人对象
            bindService(intent, new MusicServiceConn(), BIND_AUTO_CREATE);
        }
    
        class MusicServiceConn implements ServiceConnection{
    
    		@Override
    		public void onServiceConnected(ComponentName name, IBinder service) {
    			// TODO Auto-generated method stub
    			mi = (MusicInterface) service;
    		}
    
    		@Override
    		public void onServiceDisconnected(ComponentName name) {
    			// TODO Auto-generated method stub
    			
    		}
        	
        }
    
        //開始播放button
        public void play(View v){
        	mi.play();
        }
        //暂停播放button
        public void pause(View v){
        	mi.pause();
        }
    }
    

    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    
    public class MusicService extends Service{
    	@Override
    	public IBinder onBind(Intent intent) {
    		// TODO Auto-generated method stub
    		return new MusicController();
    	}
    	
    	
    	//必须继承binder。才干作为中间人对象返回
    	class MusicController extends Binder implements MusicInterface{
    		public void play(){
    			MusicService.this.play();
    		}
    		public void pause(){
    			MusicService.this.pause();
    		}
    	}
    	
    	public void play(){
    		System.out.println("播放音乐");
    	}
    	
    	public void pause(){
    		System.out.println("暂停播放");
    	}
    
    	
    }
    public interface MusicInterface {
    
    	void play();
    	void pause();
    }

    二、跨进程Service调用

    跨进程Service调用。即在当前应用程序中。调用还有一个应用程序中的Service。

    由于Android中,每一个应用程序都执行于自己的进程中,拥有独立的Dalvik虚拟机实例,因而称为跨进程调用(Inter-Process Comunication)。

    可通过AIDL服务来实现。

    AIDL(Android Interface Definition Language),是Android定义的一种类似Java的语言。

    主要用于定义跨进程调用时。服务端跟client用于数据交互的接口。

    AIDL服务并不支持全部的Java数据类型。它仅仅支持下面的几种类型:
    1、Java的简单类型(int, char, boolean等)。无需import
    2、String和CharSequence。无需import
    3、List和Map。无需import(应当注意的是:List和Map的元素类型必须是AIDL支持的)
    4、AIDL自己主动生成的接口。须要import
    5、实现android.os.Parcelable接口的类。须要import

    建立简单的AIDL服务的过程例如以下:
    (一)服务端步骤:
    1、在服务端创建AIDL文件IMyAidl.aidl
    AIDL与Java代码非常相近,演示样例代码例如以下:(注意:aidl文件后缀名为.aidl)

    interface IMyAidl
    {
    void print();
    }
    创建完aidl文件后,ADT会自己主动调用aidl命令生成对应的Java文件。

    可查看gen目录下是否有一个名为IMyAidl.java的文件。

    假设没有,说明.aidl文件有误。

    2、继承Service类,在子类中。将AIDL接口暴露出来。
    这一步类似于本地Service调用,则通过onBind(Intent intent)方法返回一个IBinder对象。
    演示样例代码例如以下:

    public class MyService extends Service
    {
    private AidlBinder mBinder;
    //Stub类是上一步骤中,aidl命令生成的Java代码中的一个类
    //该类实现了IBinder接口和IMyAidl接口
    //能够通过继承该类,然后在onBind()方法中返回AidlBinder对象
    //如此一来。就可以通过AidlBinder对象对AIDL文件里定义的方法进行调用
    public class AidlBinder extends Stub
    {
    @Override
    public void print()
    {
    System.out.println("Hello world!")//实现AIDL文件里的接口函数
    }
    }
    @Override
    public void onCreate()
    {
    mBinder = new AidlBinder();//启动服务时即创建Binder对象
    }
    
    @Override
    public IBinder onBind(Intent intent)
    {
    return mBinder;//返回Binder对象,让client获得Binder对象
    }
    }
    3、配置AndroidManifest.xml文件

    <!-- 自己定义訪问Service所需的权限 -->
    <permission android:protectLevel="normal" android:name="thomas.permission.AIDL_SERVICE"/>
    
    <service android:name="com.thomas.aidlserver.MyService" android:exported="true"
    android:permission="thomas.permission.AIDL_SERVICE">
    <!-- IntentFilter属性是不可缺少的 -->
    <!-- 如此一来,client才干通过该action远程调用服务端的Service -->
    <intent-filter>
    <action android:name="com.thomas.aidlserver.action.AIDL_SERVICE"/>
    </intent-filter>
    </service>
    (二)client步骤:
    1、创建AIDL文件
    client也要创建AIDL文件,并且是跟服务端全然一样的AIDL文件。
    复制服务端AIDL文件就可以。

    应当注意的是:AIDL文件的包名一定要跟服务端的一致。


    假设client没有该包。应创建一个包,并将AIDL文件放到包下。

    2、跨进程调用Service
    client跨进程调用Service的方法与本地调用Service的方法差点儿相同,也是通过bindService()。
    应当注意的是。调用成功后。通过ServiceConnection接口中的onServiceConnected(ComponentName name, IBinder service)方法得到服务端onBind()方法传递过来的Binder对象。

    将该对象类型转化为AIDL文件里声明的接口类型,就可以调用该接口中定义的方法。
    演示样例代码例如以下:

    private IMyAidl mAidl;
    mServiceCon = new ServiceConnection()
    {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service)
    {
    //将IBinder类型转化为IMyAidl类型。
    mAidl = IMyAidl.Stub.asInterface(service);
    }
    @Override
    public void onServiceDisonnected(ComponentName name){}
    }
    //远程Service绑定,当中Intent的action參数是服务端在
    //AndroidManifest.xml文件里<service>标签下的<intent-filter>指定的字符串
    bindService(new Intent("com.thomas.aidlserver.action.AIDL_SERVICE"),
    mServiceCon, Service.BIND_AUTO_CREATE);
    mAidl.print();//调用AIDL文件里声明的方法

    3、配置AndroidManifest.xml文件

    <!-- 请求訪问远程Service所需的权限,该权限定义于服务端的AndroidManifest.xml文件里 -->
    <uses-permission android:name="thomas.permission.AIDL_SERVICE"/>








  • 相关阅读:
    poj----1330Nearest Common Ancestors(简单LCA)
    Tarjan--LCA算法的个人理解即模板
    hdu----(4545)魔法串(LCS)
    hdu---(1325)Is It A Tree?(并查集)
    hdu----(1599)最大子矩阵(几何/dp)
    hdu---(1054)Strategic Game(最小覆盖边)
    整理的一些模版LCS(连续和非连续)
    hdu---(4310)Hero(贪心算法)
    hdu----(4308)Saving Princess claire_(搜索)
    hdu------(4302)Holedox Eating(树状数组+二分)
  • 原文地址:https://www.cnblogs.com/yfceshi/p/7222089.html
Copyright © 2020-2023  润新知