写给初学者,Android AIDL必看内容 Android开发技术

  更好的设计Android软件应该熟悉掌握AIDL IPC机制,可以让你编写的组件类似Windows ActiveX COM一样更好的复用,提供类似像Symbian那样的服务器机制。服务可以很好的解决在后台运行无UI的窗口。我们创建一个aidl文件名为android123.aidl下面是示例代码,修改于Android SDK文档。

一、创建AIDL文件

package cn.com.android123;

引入声明 import cn.com.android123.IAtmService;

// 声明一个接口,这里演示的是银行ATM程序
interface IBankAccountService {
    
    int getAccountBalance(); //返回整数,无参数
    void setOwnerNames(in List<String> names); //不返回,包含一个传入List参数
    BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService); //返回一个自定义类型
    int getCustomerList(in String branch, out String[] customerList); //返回整形,输入一个分支,输出一个客户列表
}

二、实现一个接口

显示的提供一个导出接口,为客户端提供绑定。

public class RemoteService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        if (IRemoteService.class.getName().equals(intent.getAction())) {
            return mBinder;
        }
        if (ISecondary.class.getName().equals(intent.getAction())) {
            return mSecondaryBinder;
        }
        return null;
    }
 //第一个接口

    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
        public void registerCallback(IRemoteServiceCallback cb) {
            if (cb != null) mCallbacks.register(cb);
        }
        public void unregisterCallback(IRemoteServiceCallback cb) {
            if (cb != null) mCallbacks.unregister(cb);
        }
    };
//第二个接口

    private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() {
        public int getPid() {
            return Process.myPid();
        }
        public void basicTypes(int anInt, long aLong, boolean aBoolean,
                float aFloat, double aDouble, String aString) {
        }
    };

}

三、客户端交互

通过Android.os提供的Parcelable类型来传递数据,通常我们使用Eclipse+ADT插件来完成,在Eclipse中在Package Explorer view视图上单击鼠标右键,选择Create Aidl preprocess file for Parcelable classes(创建aidl预编译文件),最终我们创建一个名为android123.aidl文件

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

public final class Rect implements Parcelable {
   
public int left;
   
public int top;
   
public int right;
   
public int bottom;

    public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect>() {
       
public Rect createFromParcel(Parcel in) {
           
return new Rect(in);
       
}

        public Rect[] newArray(int size) {
           
return new Rect[size];
       
}
   
};

    public Rect() {
   
}

    private Rect(Parcel in) {
        readFromParcel
(in);
   
}

    public void writeToParcel(Parcel out) { //当前数据写入到Parcel中
       
out.writeInt(left);
       
out.writeInt(top);
       
out.writeInt(right);
       
out.writeInt(bottom);
   
}

    public void readFromParcel(Parcel in) { //从Parcel中读取数据
        left
= in.readInt();
        top
= in.readInt();
        right
= in.readInt();
        bottom
= in.readInt();
   
}
}

  IPC调用方式

public class RemoteServiceBinding extends Activity {
   
/** The primary interface we will be calling on the service. */
   
IRemoteService mService = null;
   
/** Another interface we use on the service. */
   
ISecondary mSecondaryService = null;

   
Button mKillButton;
   
TextView mCallbackText;

   
private boolean mIsBound;

   
/**
     * Standard initialization of this activity.  Set up the UI, then wait
     * for the user to poke it before doing anything.
     */

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);

        setContentView
(R.layout.remote_service_binding);

       
// Watch for button clicks.
       
Button button = (Button)findViewById(R.id.bind);
        button
.setOnClickListener(mBindListener);
        button
= (Button)findViewById(R.id.unbind);
        button
.setOnClickListener(mUnbindListener);
        mKillButton
= (Button)findViewById(R.id.kill);
        mKillButton
.setOnClickListener(mKillListener);
        mKillButton
.setEnabled(false);

        mCallbackText
= (TextView)findViewById(R.id.callback);
        mCallbackText
.setText("Not attached.");
   
}

   
/**
     * Class for interacting with the main interface of the service.
     */

   
private ServiceConnection mConnection = new ServiceConnection() {
       
public void onServiceConnected(ComponentName className,
               
IBinder service) {
           
// This is called when the connection with the service has been
           
// established, giving us the service object we can use to
           
// interact with the service.  We are communicating with our
           
// service through an IDL interface, so get a client-side
           
// representation of that from the raw service object.
            mService
= IRemoteService.Stub.asInterface(service);
            mKillButton
.setEnabled(true);
            mCallbackText
.setText("Attached.");

           
// We want to monitor the service for as long as we are
           
// connected to it.
           
try {
                mService
.registerCallback(mCallback);
           
} catch (RemoteException e) {
               
// In this case the service has crashed before we could even
               
// do anything with it; we can count on soon being
               
// disconnected (and then reconnected if it can be restarted)
               
// so there is no need to do anything here.
           
}

           
// As part of the sample, tell the user what happened.
           
Toast.makeText(RemoteServiceBinding.this, R.string.remote_service_connected,
                   
Toast.LENGTH_SHORT).show();
       
}

       
public void onServiceDisconnected(ComponentName className) {
           
// This is called when the connection with the service has been
           
// unexpectedly disconnected -- that is, its process crashed.
            mService
= null;
            mKillButton
.setEnabled(false);
            mCallbackText
.setText("Disconnected.");

           
// As part of the sample, tell the user what happened.
           
Toast.makeText(RemoteServiceBinding.this, R.string.remote_service_disconnected,
                   
Toast.LENGTH_SHORT).show();
       
}
   
};

   
/**
     * Class for interacting with the secondary interface of the service.
     */

   
private ServiceConnection mSecondaryConnection = new ServiceConnection() {
       
public void onServiceConnected(ComponentName className,
               
IBinder service) {
           
// Connecting to a secondary interface is the same as any
           
// other interface.
            mSecondaryService
= ISecondary.Stub.asInterface(service);
            mKillButton
.setEnabled(true);
       
}

       
public void onServiceDisconnected(ComponentName className) {
            mSecondaryService
= null;
            mKillButton
.setEnabled(false);
       
}
   
};

   
private OnClickListener mBindListener = new OnClickListener() {
       
public void onClick(View v) {
           
// Establish a couple connections with the service, binding
           
// by interface names.  This allows other applications to be
           
// installed that replace the remote service by implementing
           
// the same interface.
            bindService
(new Intent(IRemoteService.class.getName()),
                    mConnection
, Context.BIND_AUTO_CREATE);
            bindService
(new Intent(ISecondary.class.getName()),
                    mSecondaryConnection
, Context.BIND_AUTO_CREATE);
            mIsBound
= true;
            mCallbackText
.setText("Binding.");
       
}
   
};

   
private OnClickListener mUnbindListener = new OnClickListener() {
       
public void onClick(View v) {
           
if (mIsBound) {
               
// If we have received the service, and hence registered with
               
// it, then now is the time to unregister.
               
if (mService != null) {
                   
try {
                        mService
.unregisterCallback(mCallback);
                   
} catch (RemoteException e) {
                       
// There is nothing special we need to do if the service
                       
// has crashed.
                   
}
               
}

               
// Detach our existing connection.
                unbindService
(mConnection);
                unbindService
(mSecondaryConnection);
                mKillButton
.setEnabled(false);
                mIsBound
= false;
                mCallbackText
.setText("Unbinding.");
           
}
       
}
   
};

   
private OnClickListener mKillListener = new OnClickListener() {
       
public void onClick(View v) {
           
// To kill the process hosting our service, we need to know its
           
// PID.  Conveniently our service has a call that will return
           
// to us that information.
           
if (mSecondaryService != null) {
               
try {
                   
int pid = mSecondaryService.getPid();
                   
// Note that, though this API allows us to request to
                   
// kill any process based on its PID, the kernel will
                   
// still impose standard restrictions on which PIDs you
                   
// are actually able to kill.  Typically this means only
                   
// the process running your application and any additional
                   
// processes created by that app as shown here; packages
                   
// sharing a common UID will also be able to kill each
                   
// other's processes.
                   
Process.killProcess(pid);
                    mCallbackText
.setText("Killed service process.");
               
} catch (RemoteException ex) {
                   
// Recover gracefully from the process hosting the
                   
// server dying.
                   
// Just for purposes of the sample, put up a notification.
                   
Toast.makeText(RemoteServiceBinding.this,
                            R
.string.remote_call_failed,
                           
Toast.LENGTH_SHORT).show();
               
}
           
}
       
}
   
};

   
// ----------------------------------------------------------------------
   
// Code showing how to deal with callbacks.
   
// ----------------------------------------------------------------------

   
/**
     * This implementation is used to receive callbacks from the remote
     * service.
     */

   
private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
       
/**
         * This is called by the remote service regularly to tell us about
         * new values.  Note that IPC calls are dispatched through a thread
         * pool running in each process, so the code executing here will
         * NOT be running in our main thread like most other things -- so,
         * to update the UI, we need to use a Handler to hop over there.
         */

       
public void valueChanged(int value) {
            mHandler
.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0));
       
}
   
};

   
private static final int BUMP_MSG = 1;

   
private Handler mHandler = new Handler() {
       
@Override public void handleMessage(Message msg) {
           
switch (msg.what) {
               
case BUMP_MSG:
                    mCallbackText
.setText("Received from service: " + msg.arg1);
                   
break;
               
default:
                   
super.handleMessage(msg);
           
}
       
}

   
};
}

  完整的演示工程源代码我们稍后提供下载

本人擅长Ai、Fw、Fl、Br、Ae、Pr、Id、Ps等软件的安装与卸载,精通CSS、JavaScript、PHP、ASP、C、C++、C#、Java、Ruby、Perl、Lisp、Python、Objective-C、ActionScript、Pascal等单词的拼写,熟悉Windows、Linux、OS X、Android、iOS、WP8等系统的开关机。

通过下面的方式来联系我们:

电邮:138762189@qq.com

联系QQ:点击这里给我发消息

官方站:www.tadke.com

※ ※ 联系请加我的企鹅号 ※※

※ ※技术支持请微信联系站长 ※※

Copyright © 2023 Tadke.com. 琼ICP备20000547号