您的位置:首页 > 移动开发 > Android开发

Android AIDL -通过一个比较完整的Demo快速运用

2012-12-26 10:21 597 查看
前端时间项目运用到AIDL,关于AIDL客户端以及AIDL服务端网络上没有一个比较完备的Demo.

而参考Demo无疑是一个比较快速的学习方法.因此,我写了一个Demo.

供大家参考,也非常欢迎大家对其中写的不好的地方进行指正.



好了,首先简述下基本功能:

在AIDL 客户端三个EditText中输入三个值,点击提交按钮,将这三个值传入到AIDL服务端进行处理.

服务端处理后会执行客户端的回调函数:在AIDL客户端界面进行刷新,并显示一个toast.



接下来看看代码结构:





需要注意的是,两个工程中com.harlan.demo.aidl包内部的文件必须保持一致.



(1)HarlanInfo.java:这是包中唯一的一个java文件,是一个数据结构,该类实现了Parcelable接口

package com.harlan.demo.aidl;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * 
 * <一句话功能简述>
 * Parcelable是Android特有的功能,效率比实现Serializable接口高
 * 
 * @author  Administrator
 * @version  [版本号, 2012-12-10]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class HarlanInfo implements Parcelable
{
    private String name;
    
    private int age;
    
    private String place;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }

    public String getPlace()
    {
        return place;
    }

    public void setPlace(String place)
    {
        this.place = place;
    }
    
    /**
     * <默认构造函数>
     */
    public HarlanInfo()
    {
        
    }
    
    /**
     * <默认构造函数>
     */
    public HarlanInfo(Parcel in)
    {
        //注意顺序
         name = in.readString();
        age = in.readInt();
        place = in.readString();
    }
    
    /**
     * seems meaningless
     * return 0;
     */
    @Override
    public int describeContents()
    {
        return 0;
    }

    /**
     * 将对象序列化为一个Parcel对象
     *  可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,
     *  再通过createFromParcel从流里读取对象
     *  注意:写的顺序和读的顺序必须一致。 
     */
    @Override
    public void writeToParcel(Parcel dest, int flags)
    {
        dest.writeString(name);
        dest.writeInt(age);
        dest.writeString(place);
    }
    
    /**
     * 实例化静态内部对象CREATOR实现接口Parcelable.Creator
     * public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写
     */
    public static final Parcelable.Creator<HarlanInfo> CREATOR = new Creator<HarlanInfo>(){

      //将Parcel对象反序列化为HarlanInfo   
        @Override
        public HarlanInfo createFromParcel(Parcel source)
        {
            HarlanInfo hlInfo = new HarlanInfo(source);
            return hlInfo;
        }

        @Override
        public HarlanInfo[] newArray(int size)
        {
            return new HarlanInfo[size];
        }
        
    };
    
}



(2)HarlanInfo.aidl :协同HarlanInfo.java文件"作战",缺一不可.

package com.harlan.demo.aidl;

parcelable HarlanInfo;



(3)ICallBack.aidl:

这是客户端回调方法的接口,在客户端实现其具体方法,在服务端调用执行.

package com.harlan.demo.aidl;
interface ICallBack{
	/**
	*callback of AIDLClient
	*handle by server
	**/
	void handleByServer(String param);
}



(4)ExecuteService.aidl:

这是从服务端获取数据方法的接口,在服务端实现其具体方法,在客户端调用执行.

参数info是由用户输入的数据构成的,同时传递的还要客户端回调方法的句柄,从而服务端可以调用客户端的回调方法.

该方法返回一个HarlanInfo的数据类型,客户端获得此数据,在界面上进行相应的显示.

package com.harlan.demo.aidl;
import com.harlan.demo.aidl.HarlanInfo;
import com.harlan.demo.aidl.ICallBack;
interface ExecuteServiceAIDL
{
	/**
	 *get info from server and 
	 *Transfer a callback methods handle;
	 *if occur error ,will be return null
	 *对于非基本数据类型和String和CharSequence类型,要加上方向指示
	 *包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。
     */
	HarlanInfo getServerHarlanInfo(in HarlanInfo info,ICallBack icallback);
}


好了,现在对com.harlan.demo.aidl包已经大致了解,build一下project,发现gen文件夹下面多出来一个包:



包中文件可以随便看看,不看也没事.因为你只要在客户端服务端相应的位置实现对应的接口就可以了.

先来看看服务端,因为服务端相对简单些,不需要界面什么的,只是一个Service.

上代码:

package com.harlan.demo.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.harlan.demo.aidl.ExecuteServiceAIDL;
import com.harlan.demo.aidl.HarlanInfo;
import com.harlan.demo.aidl.ICallBack;

public class AIDLService extends Service
{
    public static final String TAG = "AIDLService";
    
    private ICallBack mCallBack;
    
    /**
     * 绑定服务
     */
    @Override
    public IBinder onBind(Intent intent)
    {
        // TODO Auto-generated method stub
        return mBinder;
    }
    
    /**
     * 创建服务
     */
    @Override
    public void onCreate()
    {
        super.onCreate();
    }

    /**
     * 销毁服务
     */
    @Override
    public void onDestroy()
    {
        super.onDestroy();
    }

    /**
     * 启动服务
     */
    @Override
    public void onStart(Intent intent, int startId)
    {
        super.onStart(intent, startId);
    }

    /**
     * 解绑服务
     */
    @Override
    public boolean onUnbind(Intent intent)
    {
        mCallBack = null;
        return super.onUnbind(intent);
    }
    
    ExecuteServiceAIDL.Stub mBinder = new ExecuteServiceAIDL.Stub()
    {
       //这里实现了getServiceHarlanInfo接口
        @Override
        public HarlanInfo getServerHarlanInfo(HarlanInfo info, ICallBack icallback)
            throws RemoteException
        {
            Log.d(TAG,"getServerHarlanInfo");
            mCallBack = icallback;
            mCallBack.handleByServer("The msg is from server");
            HarlanInfo newInfo = new HarlanInfo();
            newInfo.setName(info.getName().toLowerCase());
            newInfo.setAge(info.getAge() + 10);
            newInfo.setPlace("Home");
            return newInfo;
        }
    };
    
}

一目了然,服务端主要的功能就是实现了aidl中的getServerHarlanInfo(HarlanInfo info, ICallBack icallback)接口.返回了一个mBinder供客户端调用.

写好了服务,还得在Manifest文件里面配置一下:

<service 
            android:name=".AIDLService">
            <intent-filter>
                <action android:name="com.harlan.demo.aidl.service"/>
            </intent-filter>
</service>



服务端写好了,就来客户端的了.客户端主要是一个activity,界面相对简单,如图所示:



界面布局相对简单,就不贴代码了.



下面贴ClientActivity的代码:

package com.harlan.demo.activity;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.harlan.demo.aidl.ExecuteServiceAIDL;
import com.harlan.demo.aidl.HarlanInfo;
import com.harlan.demo.aidl.ICallBack;

public class ClientActivity extends Activity
{
    public static final String TAG = "ClientActivity";
    
    private static final String BIND_ACTION = "com.harlan.demo.aidl.service";
    
    private EditText mEditTextName;
    
    private EditText mEditTextAge;
    
    private EditText mEditTextPlace;
    
    private Button mButtonCommit;
    
    private ExecuteServiceAIDL executeService;
    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        getView();
	//用户点击提交按钮,将数据传至服务端进行处理  
     	 mButtonCommit.setOnClickListener(new View.OnClickListener()
        {
            
            @Override
            public void onClick(View v)
            {
	    //绑定服务
                getServiceConnect();             
            }
        });
    }
        
    private void getView()
    {
        mEditTextName = (EditText)findViewById(R.id.editText_name);
        mEditTextAge = (EditText)findViewById(R.id.editText_age);
        mEditTextPlace = (EditText)findViewById(R.id.editText_place);
        mButtonCommit = (Button)findViewById(R.id.button_commit);
    }
    
    private void getServiceConnect()
    {
        Intent it = new Intent();
        it.setAction(BIND_ACTION);
        startService(it);
        bindService(it, mserviceConnection, BIND_AUTO_CREATE);
    }
    
    ServiceConnection mserviceConnection = new ServiceConnection()
    {
        
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            Log.d(TAG, "onServiceDisconnected");           
        }
        
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            Log.d(TAG, "onServiceConnected");
            //获取服务端传过来的IBinder对象,通过该对象调用服务端的方法
              executeService = ExecuteServiceAIDL.Stub.asInterface(service);
            if (executeService != null)
            {
                handlerInfo();
            }
        }
    };
    
    private void handlerInfo()
    {
        String mName;
        int mAge;
        String mPlace;
        if (mEditTextName.getText().toString().equals(""))
        {
            mEditTextName.setText("Harlan");
            mName = "Harlan";
        }
        else
        {
            mName = mEditTextName.getText().toString();
        }
        if (mEditTextAge.getText().toString().equals(""))
        {
            mAge = 22;
        }
        else
        {
            mAge = Integer.parseInt(mEditTextAge.getText().toString());
        }
        if (mEditTextPlace.getText().toString().equals(""))
        {
            mPlace = "Nanjing";
        }
        else
        {
            mPlace = mEditTextPlace.getText().toString();
        }
        HarlanInfo mInfo = new HarlanInfo();
        mInfo.setName(mName);
        mInfo.setAge(mAge);
        mInfo.setPlace(mPlace);
        try
        {
            HarlanInfo serverInfo = new HarlanInfo();
	   //调用服务端的方法
              serverInfo = executeService.getServerHarlanInfo(mInfo, mCallBack);
            //更新界面
              mEditTextName.setText(serverInfo.getName());
            mEditTextAge.setText(String.valueOf(serverInfo.getAge()));
            mEditTextPlace.setText(serverInfo.getPlace());
            unbindService(mserviceConnection);
        }
        catch (RemoteException e)
        {
            e.printStackTrace();
        }
    }
    ICallBack.Stub mCallBack = new ICallBack.Stub()
    {
       //客户端回调方法的具体实现
        @Override
        public void handleByServer(String param)
            throws RemoteException
        {
            Toast.makeText(getApplicationContext(), param, Toast.LENGTH_LONG).show();          
        }
    };
   
}

服务端调用客户端回调方法,在界面上显示一个toast.客户端根据服务端传回来的数据,刷新界面.
最后运行结果如图所示:





具体的Demo已经上传至CSDN,下载地址:http://download.csdn.net/detail/singleton1900/4928804
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐