studio para example consumir consume android web-services api rest

android - para - Servicio API de descanso



consumir web api android studio (11)

Además, cuando llego a la publicación (Config.getURL ("inicio de sesión", valores), la aplicación parece detenerse por un tiempo (parece extraño: ¡la idea detrás de un servicio es que se ejecuta en un hilo diferente!)

En este caso, es mejor usar asynctask, que se ejecuta en un subproceso diferente y devuelve el resultado al subproceso de la interfaz de usuario una vez completado.

Estoy buscando hacer un servicio que pueda usar para hacer llamadas a una API REST basada en la web.

Básicamente, quiero iniciar un servicio en la aplicación init, luego quiero poder pedirle a ese servicio que solicite un url y devuelva los resultados. Mientras tanto, quiero poder mostrar una ventana de progreso o algo similar.

Actualmente, he creado un servicio que usa IDL. He leído en alguna parte que solo necesitas esto para la comunicación entre aplicaciones, así que piensas que estas necesidades se están eliminando pero no estás seguro de cómo hacer devoluciones de llamadas sin él. Además, cuando llego a la post(Config.getURL("login"), values) la aplicación parece detenerse por un tiempo (parece extraño: ¡la idea detrás de un servicio es que se ejecuta en un hilo diferente!)

Actualmente tengo un servicio con métodos de publicación y obtención http, un par de archivos AIDL (para comunicación bidireccional), un ServiceManager que se ocupa de iniciar, detener, vincular, etc. al servicio y estoy creando dinámicamente un controlador con un código específico para las devoluciones de llamada según sea necesario.

No quiero que nadie me dé una base de código completa para trabajar, pero algunos consejos serían muy apreciados.

Código en (en su mayoría) completo:

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) {...} };

Un par de archivos AIDL:

package com.something.android oneway interface IRemoteServiceCallback { void userLogIn(String result); }

y

package com.something.android import com.something.android.IRemoteServiceCallback; interface IRestfulService { void doLogin(in String username, in String password); void registerCallback(IRemoteServiceCallback cb); }

y el gerente de servicio:

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; } }

Servicio de inicio y enlace:

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

Llamada a la función de servicio:

// 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); } } };


Además, cuando llego a la publicación (Config.getURL ("inicio de sesión", valores), la aplicación parece detenerse por un tiempo (parece extraño: ¡la idea detrás de un servicio es que se ejecuta en un hilo diferente!)

No, tiene que crear un subproceso, un servicio local se ejecuta en el subproceso de la interfaz de usuario de forma predeterminada.


Aquí hay otro enfoque que básicamente le ayuda a olvidarse de la gestión completa de las solicitudes. Se basa en un método de cola asíncrona y en una respuesta basada en callback / callback. La principal ventaja es que al usar este método podrá hacer que todo el proceso (solicitud, obtención y análisis de respuesta, sabe a db) sea completamente transparente para usted. Una vez que obtenga el código de respuesta, el trabajo ya está hecho. Después de eso solo necesitas hacer una llamada a tu db y listo. También ayuda con la problemática de lo que sucede cuando su actividad no está activa. Lo que sucederá aquí es que tendrá todos sus datos guardados en su base de datos local, pero la respuesta no será procesada por su actividad, esa es la manera ideal.

Escribí sobre un enfoque general aquí http://ugiagonzalez.com/2012/07/02/theres-life-after-asynctasks-in-android/

Pondré código de muestra específico en próximas publicaciones. Espero que ayude, no dude en contactarme para compartir el enfoque y resolver posibles dudas o problemas.


Digamos que quiero iniciar el servicio en un evento - onItemClicked () de un botón. El mecanismo Receptor no funcionaría en ese caso porque:
a) Pasé el Receptor al servicio (como en Intent extra) de onItemClicked ()
b) La actividad se mueve al fondo. En onPause () configuré la referencia del receptor dentro del ResultReceiver a nulo para evitar perder la Actividad.
c) La actividad se destruye.
d) La actividad se crea de nuevo. Sin embargo, en este punto, el Servicio no podrá realizar una devolución de llamada a la Actividad ya que la referencia del receptor se pierde.
El mecanismo de una emisión limitada o un PendingIntent parece ser más útil en tales escenarios. Consulte Notificar actividad del servicio.



Robby proporciona una gran respuesta, aunque puedo ver que aún buscas más información. He implementado REST api llamadas de la manera fácil PERO de manera incorrecta. No fue hasta que vi este video de Google I / O que entendí dónde me equivoqué. No es tan simple como armar una AsyncTask con una llamada Get / Put de HttpUrlConnection.



Si su servicio va a ser parte de su aplicación, entonces lo está haciendo mucho más complejo de lo que debe ser. Ya que tiene un caso de uso simple de obtener algunos datos de un servicio web RESTful, debe buscar ResultReceiver e IntentService .

Este patrón Service + ResultReceiver funciona al iniciar o vincularse al servicio con startService() cuando desea realizar alguna acción. Puede especificar la operación a realizar y pasar su ResultReceiver (la actividad) a través de los extras en la Intención.

En el servicio, implementas onHandleIntent para realizar la operación que se especifica en la Intención. Cuando se completa la operación, utilice el Pase en ResultReceiver para send un mensaje a la Actividad en el que se onReceiveResult .

Así, por ejemplo, desea extraer algunos datos de su servicio web.

  1. Usted crea la intención y llama a startService.
  2. La operación en el servicio comienza y envía a la actividad un mensaje que dice que comenzó
  3. La actividad procesa el mensaje y muestra un progreso.
  4. El servicio finaliza la operación y envía algunos datos a su actividad.
  5. Su actividad procesa los datos y los coloca en una vista de lista.
  6. El servicio le envía un mensaje que dice que está hecho y se mata a sí mismo.
  7. La actividad recibe el mensaje final y oculta el diálogo de progreso.

Sé que mencionó que no quería un código base, pero la aplicación de código abierto Google I / O 2010 usa un servicio de la forma en que lo describo.

Actualizado para agregar código de muestra:

La actividad.

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; } }

El servicio:

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); } } } }

Extensión ResultReceiver - editada para implementar MyResultReceiver.Receiver

public class MyResultReceiver implements 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); } } }


Solo quería apuntar a todos en la dirección de una clase independiente que saqué e incorpora toda la funcionalidad.

http://github.com/StlTenny/RestService

Ejecuta la solicitud como no bloqueante y devuelve los resultados en un controlador fácil de implementar. Incluso viene con una implementación de ejemplo.


Tenga en cuenta que de alguna manera falta la solución de Robby Pond: de esta manera, solo se permite realizar una llamada a una api a la vez, ya que IntentService solo maneja una intención a la vez. A menudo desea realizar llamadas de API paralelas. Si desea hacer todo esto, debe extender el Servicio en lugar de IntentService y crear su propio hilo.


El desarrollo de aplicaciones cliente REST para Android ha sido un recurso increíble para mí. El orador no muestra ningún código, solo repasa las consideraciones de diseño y las técnicas para armar un Rest Api sólido en Android. Si es un podcast o no, le recomiendo que escuche al menos una vez, pero personalmente lo he escuchado 4 o 5 veces hasta el momento y probablemente lo vuelva a escuchar.

Desarrollo de aplicaciones cliente REST para Android
Autor: Virgil Dobjanschi
Descripción:

Esta sesión presentará consideraciones de arquitectura para desarrollar aplicaciones RESTful en la plataforma Android. Se centra en los patrones de diseño, la integración de la plataforma y los problemas de rendimiento específicos de la plataforma Android.

Y hay tantas consideraciones que realmente no había hecho en la primera versión de mi API que he tenido que refactorizar