Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use AIDL remote service to deal with defferent clients' concurrent requests?

I'm writting a plug-in which defines a remote Service and provides a AIDL interface for 3rd party developers.

How can I use this remote service to deal with defferent clients' concurrent requests?

It is that service apk's activitys can keep status for each client, when they switched between each other, how to do it?

like image 263
Shrek.Z Avatar asked Dec 19 '12 08:12

Shrek.Z


People also ask

What is AIDL used for?

The Android Interface Definition Language (AIDL) is a tool that lets users abstract away IPC. Given an interface (specified in a . aidl file), various build systems use the aidl binary to construct C++ or Java bindings so that this interface can be used across processes, regardless of the runtime or bitness there.

What data types are supported by AIDL?

all native Java data types like int,long, char and Boolean.

What is one way in AIDL?

The oneway keyword modifies the behavior of remote calls. When used, a remote call does not block; it simply sends the transaction data and immediately returns. The implementation of the interface eventually receives this as a regular call from the Binder thread pool as a normal remote call.


1 Answers

This can be achieved using HandlerThread with Looper which maintains and service all the request no matter received from 100 applications.

For this AIDL callback interface is also needs to be added as request will be furnished through these callbacks.

SERVER APP

IAidlService.aidl

interface IAidlService {
    void getStockInfo(IAidlCallback callback);
}

IAidlCallback.aidl

oneway interface IAidlCallback {
    void handleStockInfo(in Stock stockinfo);
}

Stock.aidl

parcelable Stock;

Stock.java

public class Stock implements Parcelable {

String stockName;

public String getStockName() {
    return stockName;
}

public void setStockName(String stockName) {
    this.stockName = stockName;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(stockName);
}

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

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

public Stock(Parcel in) {
    this.stockName = in.readString();
}

public Stock() {}
}

AidlService.java

This is main Service class which overrides the AIDL Service methods and implements them. It also handled the return of request with output to specific application requesting for it.

public class AidlService extends Service {

private static final int MSG_STOCK_INFO = 53;

private ArrayList<IAidlCallback> mRemoteCallbacks;

private ServiceHandler mHandler = null;

HandlerThread mHandlerThread = new HandlerThread("AidlServiceThread");

@Override
public void onCreate() {
    super.onCreate();

    mRemoteCallbacks = new ArrayList<>();
}

@Override
public IBinder onBind(Intent intent) {

    // Handler Thread handling all call back methods
    mHandlerThread.start();
    mHandler = new ServiceHandler(mHandlerThread.getLooper());

    return mBinder;
}

/**
 * Stub implementation for Remote service
 */
IAidlService.Stub mBinder = new IAidlService.Stub() {

    @Override
    public void getStockInfo(IAidlCallback callback) throws RemoteException {

        sendMsgToHandler(callback, MSG_STOCK_INFO);
    }
};

/**
 * Create handler message to be sent
 *
 * @param callback
 * @param flag
 */
void sendMsgToHandler(IAidlCallback callback, int flag) {

    mRemoteCallbacks.add(callback);

    Message message = mHandler.obtainMessage();
    message.arg1 = mRemoteCallbacks.size() - 1;

    message.what = flag;
    mHandler.sendMessage(message);
}

/**
 * Handler class sending result in callback to respective
 * application
 */
private class ServiceHandler extends Handler {
    int callbackIndex = 0;

    ServiceHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        callbackIndex = msg.arg1;

        switch (msg.what) {

            case MSG_STOCK_INFO:

                Stock stock = new Stock();
                stock.setStockName("Apple Inc");

                try {
                    mRemoteCallbacks.get(callbackIndex).handleStockInfo(stock);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
        }
    }
}
}

CLIENT APP

In any client app create a ServiceConnection and once binded to service you simply need to make Stub class for 'IAidlCallback` and send object along with getStockInfo call. Like:

IAidlCallback.Stub callback = new IAidlCallback.Stub() {
    @Override
    public void handleStockInfo(Stock stockinfo) throws RemoteException {

        // do what ever you want with stock info :)
    }
};

Hope it helps :)

like image 99
Harneev Avatar answered Sep 28 '22 19:09

Harneev