REST的API服务 [英] Restful API service

查看:222
本文介绍了REST的API服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在找做,我可以用它来拨打电话到一个基于Web的REST API的服务。

基本上我想在应用程序启动服务初始化,然后我希望能够问这个服务请求的url并返回结果。与此同时,我希望能够显示进度窗口或类似的东西。

我已经创建,它使用目前IDL服务,我读过的地方,你只有真的需要这种跨应用程序通信,因此认为这些需要剥离出来,但不确定该怎么做回调离不开它。此外,当我打的后(Config.getURL(登录),值)的应用程序似乎停顿了一会儿(似乎不可思议 - 以为后面服务的想法是它运行在不同的线程!)

目前我有一个后服务,并得到内部HTTP方法,一对夫妇的AIDL文件(双向通信),一个的ServiceManager其中涉及启动,停止,装订等的服务,我动态创建一个处理程序具体code的回调需要。

我不希望任何人给我一个完整的code的基础上工作,但一些指针,将大大AP preciated。

code的(主要)全:

 公共类RestfulAPIService延伸服务{

最后RemoteCallbackList< IRemoteServiceCallback> mCallbacks =新RemoteCallbackList< IRemoteServiceCallback>();

公共无效ONSTART(意向意图,诠释startId){
    super.onStart(意向,startId);
}
公众的IBinder onBind(意向意图){
    返回粘合剂;
}
公共无效的onCreate(){
    super.onCreate();
}
公共无效的onDestroy(){
    super.onDestroy();
    mCallbacks.kill();
}
私人最终IRestfulService.Stub粘合剂=新IRestfulService.Stub(){
    公共无效doLogin(字符串用户名,字符串密码){

        消息味精=新的Message();
        捆绑数据=新包();
        HashMap的<字符串,字符串>值=新的HashMap<字符串,字符串>();
        values​​.put(用户名,用户名);
        values​​.put(密码,密码);
        字符串结果=交(Config.getURL(登录),价值);
        data.putString(回应,结果);
        msg.setData(数据);
        msg.what = Config.ACTION_LOGIN;
        mHandler.sendMessage(MSG);
    }

    公共无效registerCallback(IRemoteServiceCallback CB){
        如果(CB!= NULL)
            mCallbacks.register(CB);
    }
};

私人最终处理程序mHandler =新的处理程序(){
    公共无效的handleMessage(信息MSG){

        //广播到所有客户端的新值。
        最终诠释N = mCallbacks.beginBroadcast();
        的for(int i = 0; I&n种;我++){
            尝试 {
                开关(msg.what){
                案例Config.ACTION_LOGIN:
                    mCallbacks.getBroadcastItem(我).userLogIn(msg.getData()的getString(回应)。);
                    打破;
                默认:
                    super.handleMessage(MSG);
                    返回;

                }
            }赶上(RemoteException的E){
            }
        }
        mCallbacks.finishBroadcast();
    }
    公共字符串后(字符串URL,HashMap的<字符串,字符串> namePairs){...}
    公共字符串获取(字符串URL){...}
};
 

一对夫妇的AIDL文件:

 包com.something.android

单向接口IRemoteServiceCallback {
    无效用户登陆(字符串​​结果);
}
 

 包com.something.android
进口com.something.android.IRemoteServiceCallback;

接口IRestfulService {
    无效doLogin(String中的用户名,在字符串密码);
    无效registerCallback(IRemoteServiceCallback CB);
}
 

和服务管理器:

 公共类的ServiceManager {

    最后RemoteCallbackList< IRemoteServiceCallback> mCallbacks =新RemoteCallbackList< IRemoteServiceCallback>();
    公共IRestfulService restfulService;
    私人RestfulServiceConnection康涅狄格州;
    私人布尔开始= FALSE;
    私人上下文的背景下;

    公众的ServiceManager(上下文的背景下){
        this.context =背景;
    }

    公共无效startService(){
        如果(开始){
            Toast.makeText(背景下,服务已启动,Toast.LENGTH_SHORT).show();
        } 其他 {
            意图I =新意图();
            i.setClassName(com.something.android,com.something.android.RestfulAPIService);
            context.startService(ⅰ);
            开始= TRUE;
        }
    }

    公共无效stopService(){
        如果(!开始){
            Toast.makeText(背景下,服务尚未开始,Toast.LENGTH_SHORT).show();
        } 其他 {
            意图I =新意图();
            i.setClassName(com.something.android,com.something.android.RestfulAPIService);
            context.stopService(ⅰ);
            开始= FALSE;
        }
    }

    公共无效bindService(){
        如果(康涅狄格州== NULL){
            康恩=新RestfulServiceConnection();
            意图I =新意图();
            i.setClassName(com.something.android,com.something.android.RestfulAPIService);
            context.bindService(我,康涅狄格州,Context.BIND_AUTO_CREATE);
        } 其他 {
            Toast.makeText(背景下,不能绑定 - 服务已经绑定,Toast.LENGTH_SHORT).show();
        }
    }

    保护无效的destroy(){
        releaseService();
    }

    私人无效releaseService(){
        如果(conn将!= NULL){
            context.unbindService(康涅狄格州);
            康恩= NULL;
            Log.d(LOG_TAG,unbindService());
        } 其他 {
            Toast.makeText(背景下,不能解除 - 服务不绑定,Toast.LENGTH_SHORT).show();
        }
    }

    类RestfulServiceConnection实现ServiceConnection {
        公共无效onServiceConnected(组件名的className,的IBinder boundService){
            restfulService = IRestfulService.Stub.asInterface((的IBinder)boundService);
            尝试 {
            restfulService.registerCallback(mCallback);
            }赶上(RemoteException的E){}
        }

        公共无效onServiceDisconnected(组件名的className){
            restfulService = NULL;
        }
    };

    私人IRemoteServiceCallback mCallback =新IRemoteServiceCallback.Stub(){
        公共无效用户登陆(字符串​​结果)将抛出RemoteException {
            mHandler.sendMessage(mHandler.obtainMessage(Config.ACTION_LOGIN,结果));

        }
    };

    私人处理器mHandler;

    公共无效setHandler(处理程序处理){
        mHandler =处理程序;
    }
}
 

服务初始化和绑定:

  //此,我号召应用程序的onCreate
的ServiceManager =新的ServiceManager(本);
servicemanager.startService();
servicemanager.bindService();
应用=(ApplicationState)this.getApplication();
application.setServiceManager(的ServiceManager);
 

服务功能调用:

  //这个地段我打电话要求 - 在本例中为登陆
progressDialog =新ProgressDialog(Login.this);
progressDialog.setMessage(记录你的......);
progressDialog.show();

应用=(ApplicationState)getApplication();
的ServiceManager = application.getServiceManager();
servicemanager.setHandler(mHandler);

尝试 {
    servicemanager.restfulService.doLogin(参数[0],的args [1]);
}赶上(RemoteException的E){
    e.printStackTrace();
}

...后来在同一文件...

处理器mHandler =新的处理程序(){
    公共无效的handleMessage(信息MSG){

        开关(msg.what){
        案例Config.ACTION_LOGIN:

            如果(progressDialog.isShowing()){
                progressDialog.dismiss();
            }

            尝试 {
                ...过程登录结果...
                }
            }赶上(JSONException E){
                Log.e(JSON,有一个错误解析JSON,E);
            }
            打破;
        默认:
            super.handleMessage(MSG);
        }

    }

};
 

解决方案

如果您的服务将是您的应用程序,那么你正在创造一种方式更加复杂的比它需要的部分。既然你有一个简单的例子,从一个RESTful Web服务得到一些数据,你应该看看 ResultReceiver IntentService

本服务+ ResultReceiver模式的工作原理是启动或<绑定到服务href="http://developer.android.com/reference/android/content/Context.html#startService%28android.content.Intent%29">startService()当你想要做一些动作。您可以指定要执行的操作,并通过在Intent的额外传递你的ResultReceiver(活动)。

在服务您实施<一个href="http://developer.android.com/reference/android/app/IntentService.html#onHandleIntent%28android.content.Intent%29">onHandleIntent做在Intent中指定的操作。当操作完成后使用传入ResultReceiver到<一个href="http://developer.android.com/reference/android/os/ResultReceiver.html#send%28int,%20android.os.Bundle%29">send一个消息发送回活动在该点<一href="http://developer.android.com/reference/android/os/ResultReceiver.html#onReceiveResult%28int,%20android.os.Bundle%29">onReceiveResult将被调用。

因此​​,例如,你想从你的Web服务拉一些数据。

  1. 您创建的意图,并呼吁startService。
  2. 在服务启动运行,并将其发送活动的一个消息,说是开始
  3. 活动处理的消息,并显示一个进度。
  4. 在服务完成的操作,发送一些数据返回到你的活动。
  5. 您的活动处理数据,并将在一个列表视图
  6. 在该服务向您发送一条消息,说是做的,它会杀死自己。
  7. 在该活动得到完成消息并隐藏进度对话框。

我知道你提到你不想一个code的基础,但开源谷歌I / O 2010 应用程序以这种方式我描述使用服务。

更新添加样品code:

活动。

 公共类HomeActivity扩展活动实现MyResultReceiver.Receiver {

    公共MyResultReceiver mReceiver;

    公共无效的onCreate(包savedInstanceState){
        mReceiver =新MyResultReceiver(新处理器());
        mReceiver.setReceiver(本);
        ...
        最终意向意图=新的意图(Intent.ACTION_SYNC,空,这一点,QueryService.class);
        intent.putExtra(接收器,mReceiver);
        intent.putExtra(命令,查询);
        startService(意向);
    }

    公共无效的onPause(){
        mReceiver.setReceiver(空); //清晰的接收器,让无泄漏。
    }

    公共无效onReceiveResult(INT结果code,捆绑resultData){
        开关(结果code){
        情况下运行:
            //显示进度
            打破;
        案例表面处理:
            列表结果= resultData.getParcelableList(结果);
            //做一些有趣的事情
            //隐藏进展
            打破;
        如果出现错误:
            //处理错误;
            打破;
    }
}
 

该服务:

 公共类QueryService的扩展IntentService {
    保护无效onHandleIntent(意向意图){
        最后ResultReceiver接收器= intent.getParcelableExtra(接收器);
        字符串命令= intent.getStringExtra(命令);
        叠B =新包();
        如果(command.equals(查询){
            receiver.send(STATUS_RUNNING,Bundle.EMPTY);
            尝试 {
                //得到一些数据,或者什么
                b.putParcelableArrayList(结果,结果);
                receiver.send(STATUS_FINISHED,B)
            }赶上(例外五){
                b.putString(Intent.EXTRA_TEXT,e.toString());
                receiver.send(STATUS_ERROR,B);
            }
        }
    }
}
 

ResultReceiver扩展 - 编辑即将实施MyResultReceiver.Receiver

 公共MyResultReceiver延伸ResultReceiver {
    私人接收mReceiver;

    公共MyResultReceiver(处理程序处理){
        超(处理);
    }

    公共无效setReceiver(接收器接收器){
        mReceiver =接收器;
    }

    公共接口接收器{
        公共无效onReceiveResult(INT结果code,捆绑resultData);
    }

    @覆盖
    保护无效onReceiveResult(INT结果code,捆绑resultData){
        如果(mReceiver!= NULL){
            mReceiver.onReceiveResult(结果code,resultData);
        }
    }
}
 

I'm looking to make a service which I can use to make calls to a web-based REST API.

Basically I want to start a service on app init then I want to be able to ask that service to request a url and return the results. In the meantime I want to be able to display a progress window or something similar.

I've created a service currently which uses IDL, I've read somewhere that you only really need this for cross app communication, so think these needs stripping out but unsure how to do callbacks without it. Also when I hit the post(Config.getURL("login"), values) the app seems to pause for a while (seems weird - thought the idea behind a service was that it runs on a different thread!)

Currently I have a service with post and get http methods inside, a couple of AIDL files (for two way communication), a ServiceManager which deals with starting, stopping, binding etc to the service and I'm dynamically creating a Handler with specific code for the callbacks as needed.

I don't want anyone to give me a complete code base to work on, but some pointers would be greatly appreciated.

Code in (mostly) full:

public class RestfulAPIService extends Service  {

final RemoteCallbackList<IRemoteServiceCallback> mCallbacks = new RemoteCallbackList<IRemoteServiceCallback>();

public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
}
public IBinder onBind(Intent intent) {
    return binder;
}
public void onCreate() {
    super.onCreate();
}
public void onDestroy() {
    super.onDestroy();
    mCallbacks.kill();
}
private final IRestfulService.Stub binder = new IRestfulService.Stub() {
    public void doLogin(String username, String password) {

        Message msg = new Message();
        Bundle data = new Bundle();
        HashMap<String, String> values = new HashMap<String, String>();
        values.put("username", username);
        values.put("password", password);
        String result = post(Config.getURL("login"), values);
        data.putString("response", result);
        msg.setData(data);
        msg.what = Config.ACTION_LOGIN;
        mHandler.sendMessage(msg);
    }

    public void registerCallback(IRemoteServiceCallback cb) {
        if (cb != null)
            mCallbacks.register(cb);
    }
};

private final Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {

        // Broadcast to all clients the new value.
        final int N = mCallbacks.beginBroadcast();
        for (int i = 0; i < N; i++) {
            try {
                switch (msg.what) {
                case Config.ACTION_LOGIN:
                    mCallbacks.getBroadcastItem(i).userLogIn( msg.getData().getString("response"));
                    break;
                default:
                    super.handleMessage(msg);
                    return;

                }
            } catch (RemoteException e) {
            }
        }
        mCallbacks.finishBroadcast();
    }
    public String post(String url, HashMap<String, String> namePairs) {...}
    public String get(String url) {...}
};

A couple of AIDL files:

package com.something.android

oneway interface IRemoteServiceCallback {
    void userLogIn(String result);
}

and

package com.something.android
import com.something.android.IRemoteServiceCallback;

interface IRestfulService {
    void doLogin(in String username, in String password);
    void registerCallback(IRemoteServiceCallback cb);
}

and the service manager:

public class ServiceManager {

    final RemoteCallbackList<IRemoteServiceCallback> mCallbacks = new RemoteCallbackList<IRemoteServiceCallback>();
    public IRestfulService restfulService;
    private RestfulServiceConnection conn;
    private boolean started = false;
    private Context context;

    public ServiceManager(Context context) {
        this.context = context;
    }

    public void startService() {
        if (started) {
            Toast.makeText(context, "Service already started", Toast.LENGTH_SHORT).show();
        } else {
            Intent i = new Intent();
            i.setClassName("com.something.android", "com.something.android.RestfulAPIService");
            context.startService(i);
            started = true;
        }
    }

    public void stopService() {
        if (!started) {
            Toast.makeText(context, "Service not yet started", Toast.LENGTH_SHORT).show();
        } else {
            Intent i = new Intent();
            i.setClassName("com.something.android", "com.something.android.RestfulAPIService");
            context.stopService(i);
            started = false;
        }
    }

    public void bindService() {
        if (conn == null) {
            conn = new RestfulServiceConnection();
            Intent i = new Intent();
            i.setClassName("com.something.android", "com.something.android.RestfulAPIService");
            context.bindService(i, conn, Context.BIND_AUTO_CREATE);
        } else {
            Toast.makeText(context, "Cannot bind - service already bound", Toast.LENGTH_SHORT).show();
        }
    }

    protected void destroy() {
        releaseService();
    }

    private void releaseService() {
        if (conn != null) {
            context.unbindService(conn);
            conn = null;
            Log.d(LOG_TAG, "unbindService()");
        } else {
            Toast.makeText(context, "Cannot unbind - service not bound", Toast.LENGTH_SHORT).show();
        }
    }

    class RestfulServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName className, IBinder boundService) {
            restfulService = IRestfulService.Stub.asInterface((IBinder) boundService);
            try {
            restfulService.registerCallback(mCallback);
            } catch (RemoteException e) {}
        }

        public void onServiceDisconnected(ComponentName className) {
            restfulService = null;
        }
    };

    private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
        public void userLogIn(String result) throws RemoteException {
            mHandler.sendMessage(mHandler.obtainMessage(Config.ACTION_LOGIN, result));

        }
    };

    private Handler mHandler;

    public void setHandler(Handler handler) {
        mHandler = handler;
    }
}

Service init and bind:

// this I'm calling on app onCreate
servicemanager = new ServiceManager(this);
servicemanager.startService();
servicemanager.bindService();
application = (ApplicationState)this.getApplication();
application.setServiceManager(servicemanager);

service function call:

// this lot i'm calling as required - in this example for login
progressDialog = new ProgressDialog(Login.this);
progressDialog.setMessage("Logging you in...");
progressDialog.show();

application = (ApplicationState) getApplication();
servicemanager = application.getServiceManager();
servicemanager.setHandler(mHandler);

try {
    servicemanager.restfulService.doLogin(args[0], args[1]);
} catch (RemoteException e) {
    e.printStackTrace();
}

...later in the same file...

Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {

        switch (msg.what) {
        case Config.ACTION_LOGIN:

            if (progressDialog.isShowing()) {
                progressDialog.dismiss();
            }

            try {
                ...process login results...
                }
            } catch (JSONException e) {
                Log.e("JSON", "There was an error parsing the JSON", e);
            }
            break;
        default:
            super.handleMessage(msg);
        }

    }

};

解决方案

If your service is going to be part of you application then you are making it way more complex than it needs to be. Since you have a simple use case of getting some data from a RESTful Web Service, you should look into ResultReceiver and IntentService.

This Service + ResultReceiver pattern works by starting or binding to the service with startService() when you want to do some action. You can specify the operation to perform and pass in your ResultReceiver (the activity) through the extras in the Intent.

In the service you implement onHandleIntent to do the operation that is specified in the Intent. When the operation is completed you use the passed in ResultReceiver to send a message back to the Activity at which point onReceiveResult will be called.

So for example, you want to pull some data from your Web Service.

  1. You create the intent and call startService.
  2. The operation in the service starts and it sends the activity a message saying it started
  3. The activity processes the message and shows a progress.
  4. The service finishes the operation and sends some data back to your activity.
  5. Your activity processes the data and puts in in a list view
  6. The service sends you a message saying that it is done, and it kills itself.
  7. The activity gets the finish message and hides the progress dialog.

I know you mentioned you didn't want a code base but the open source Google I/O 2010 app uses a service in this way I am describing.

Updated to add sample code:

The activity.

public class HomeActivity extends Activity implements MyResultReceiver.Receiver {

    public MyResultReceiver mReceiver;

    public void onCreate(Bundle savedInstanceState) {
        mReceiver = new MyResultReceiver(new Handler());
        mReceiver.setReceiver(this);
        ...
        final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, QueryService.class);
        intent.putExtra("receiver", mReceiver);
        intent.putExtra("command", "query");
        startService(intent);
    }

    public void onPause() {
        mReceiver.setReceiver(null); // clear receiver so no leaks.
    }

    public void onReceiveResult(int resultCode, Bundle resultData) {
        switch (resultCode) {
        case RUNNING:
            //show progress
            break;
        case FINISHED:
            List results = resultData.getParcelableList("results");
            // do something interesting
            // hide progress
            break;
        case ERROR:
            // handle the error;
            break;
    }
}

The Service:

public class QueryService extends IntentService {
    protected void onHandleIntent(Intent intent) {
        final ResultReceiver receiver = intent.getParcelableExtra("receiver");
        String command = intent.getStringExtra("command");
        Bundle b = new Bundle();
        if(command.equals("query") {
            receiver.send(STATUS_RUNNING, Bundle.EMPTY);
            try {
                // get some data or something           
                b.putParcelableArrayList("results", results);
                receiver.send(STATUS_FINISHED, b)
            } catch(Exception e) {
                b.putString(Intent.EXTRA_TEXT, e.toString());
                receiver.send(STATUS_ERROR, b);
            }    
        }
    }
}

ResultReceiver extension - edited about to implement MyResultReceiver.Receiver

public MyResultReceiver extends ResultReceiver {
    private Receiver mReceiver;

    public MyResultReceiver(Handler handler) {
        super(handler);
    }

    public void setReceiver(Receiver receiver) {
        mReceiver = receiver;
    }

    public interface Receiver {
        public void onReceiveResult(int resultCode, Bundle resultData);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        if (mReceiver != null) {
            mReceiver.onReceiveResult(resultCode, resultData);
        }
    }
}

这篇关于REST的API服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆