Restful API paslauga

Aš noriu padaryti paslaugą, kurią galiu naudoti skambinant į „REST API“ žiniatinklio sąsają.

Iš esmės, aš noriu pradėti paslaugą inicijavimo programoje, tada noriu paprašyti šios paslaugos prašyti URL ir grąžinti rezultatus. Tuo tarpu noriu sugebėti rodyti pažangos >

Aš sukūriau paslaugą, kuri dabar naudoja IDL, kažkur perskaičiuojau, kad jums iš tikrųjų reikia tik bendrauti per programą, todėl pagalvokite apie tai, ko jums reikia, bet nežinau, kaip grįžti be jos. Be to, kai spusteliu mygtuką „ post(Config.getURL("login"), values) , atrodo, kad programa tam tikrą laiką sustabdyta (atrodo keista - manoma, kad paslaugos idėja yra tai, kad ji veikia kitoje temoje!)

Šiuo metu turiu paslaugą su pranešimais ir http metodais, keliais AIDL failais (dvipusis ryšys), paslaugų teikėju, kuris susijęs su paleidimu, stabdymu, susiejimu ir kt. į paslaugą, ir aš dinamiškai sukuriu prižiūrėtoją, turintį tam tikrą kodą, kai reikia.

Nenoriu, kad kiekvienas man suteiktų visą kodo pagrindą darbui, tačiau kai kurie patarimai bus labai dėkingi.

Kodas yra (daugiausia):

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

Keli AIDL failai:

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

ir

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

ir paslaugų vadybininkas:

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

Iniciatyvos ir susiejimo paslauga:

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

paslaugos skambutis:

 // 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); } } }; 
208
07 июля '10 в 20:34 2010-07-07 20:34 „Martyn“ yra nustatytas liepos 07 d. 10 val. 20:34 2010-07-07 20:34
@ 11 atsakymų

Jei jūsų paslauga yra jūsų paraiškos dalis, ją galite padaryti sudėtingesnę nei turėtų būti. Kadangi turite paprastą pavyzdį, kaip gauti tam tikrus duomenis iš „RESTful“ žiniatinklio paslaugos, turėtumėte išmokti „ ResultReceiver“ ir „ IntentService“ .

Šis „Service + ResultReceiver“ šablonas veikia paleidžiant arba susiejant su paslauga naudojant startService (), kai norite atlikti veiksmą. Galite nurodyti operaciją, kurią norite atlikti, ir perkelti į savo rezultato gavimo (veiklos) funkcijas per papildomas funkcijas.

Paslaugoje vykdote onHandleIntent, kad atliktumėte operacijoje nurodytą operaciją. Kai operacija yra baigta, naudokite „SendReceiver“ išsiųstą siuntimo žinutę, kad galėtumėte išsiųsti atgal į veiklą, kurioje yra „ OnReceiveResult“ .

Taigi, pavyzdžiui, norite ištraukti kai kuriuos duomenis iš savo žiniatinklio paslaugos.

  • Jūs sukuriate ketinimą ir paskambinkite startService.
  • Operacija operacijoje prasideda ir išsiunčia pranešimą su pradiniu pranešimu.
  • Veikla apdoroja pranešimą ir rodo pažangą.
  • Paslauga baigia operaciją ir siunčia kai kuriuos duomenis į jūsų veiklą.
  • Jūsų veikla apdoroja duomenis ir atitinka sąrašo vaizdą.
  • Tarnyba atsiunčia jums žinią, kad ji yra padaryta, ir ji užmuša save.
  • Veiksmas gauna užbaigimo pranešimą ir slepia vykdymo dialogą.

Žinau, kad paminėjote, kad jums nereikia kodo bazės, tačiau „ Google I / O 2010“ programa naudoja tokią paslaugą.

Atnaujinta, kad pridėtumėte mėginio kodą:

Veikla

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

Paslauga:

 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 plėtinys - pakeistas, kad būtų įdiegta 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); } } } 
276
07 июля '10 в 20:53 2010-07-07 20:53 atsakymas buvo pateiktas Robby Pond'ui liepos 10 d. 10 val. 20:53 2010-07-07 20:53

„REST“ kliento programų kūrimas „Android“ buvo man nuostabus šaltinis. Kalbėtojas nerodo jokio kodo, jis paprasčiausiai atsižvelgia į dizaino aplinkybes ir metodus, kaip „Rest Api“ roko masyvą įdėti į „Android“. Jei jūsų podcast'as yra tam tikras asmuo ar ne, aš rekomenduočiau bent vieną klausytis, bet asmeniškai klausiausi, kaip 4 ar 5 kartus, ir tikriausiai vėl jį klausysiu.

REST kliento programų kūrimas „Android“
Autorius: Virgil Dobzhanshi
Aprašymas:

border=0

Šioje sesijoje bus pateikti architektūriniai aspektai, skirti „Android“ platformoje sukurti „RESTful“ programas. Jame pagrindinis dėmesys skiriamas dizaino modeliams, platformos integracijai ir „Android“ platformai būdingam našumui.

Ir yra tiek daug pastabų, kad aš tikrai nepadariau pirmosios mano api versijos, kurią turėjau reorganizuoti

15
20 сент. atsakymą pateikė Terrance 20 sep. 2011-09-20 15:35 '11 prie 15:35 2011-09-20 15:35

Be to, kai pasieksiu pranešimą (Config.getURL („prisijungimas“), vertes), atrodo, kad paraiška sustabdyta (nors atrodo keista - mintis už paslaugą buvo ta, kad ji veikia kitoje temoje!)

Ne, jums reikia sukurti temą, pagal numatytuosius nustatymus vartotojo sąsajos sriegyje veikia vietinė paslauga.

15
07 июля '10 в 21:34 2010-07-07 21:34 atsakymą pateikė Soumya Simanta, liepos 7 d., 10 d., 21:34 2010-07-07 21:34

Žinau, kad @Martyn nenori pilno kodo, bet manau, kad šis komentaras yra naudingas šiam klausimui:

10 atvirojo kodo „Android“ programų, kurias kiekvienas „Android“ kūrėjas turi išmokti

„Foursquared“, skirta „Android“, yra atviro kodo ir jame yra įdomus kodas, kuris sąveikauja su REST API su keturiais užklausomis.

11
12 сент. Atsakymas pateikiamas panchicore 12 sep . 2011-09-12 22:38 '11, 10:38 val. 2011-09-12 22:38

Aš tik norėjau jus visus nukreipti į atskiros klasės, kurią aš išsinuomojau, pusę, kuri apima visas funkcijas.

http://github.com/StlTenny/RestService

Jis atlieka užklausą kaip ne blokavimą ir grąžina rezultatus lengvai įgyvendinamoje tvarkyklėje. Jame netgi pateikiamas pavyzdys.

5
11 июля '12 в 21:01 2012-07-11 21:01 atsakymas į StlTenny pateikiamas liepos 11 d. 12 val. 21:01 2012-07-11 21:01

Labai rekomenduoju „REST Retrofit“ klientą.

Radau, kad šis gerai parašytas dienoraščio įrašas labai naudingas, jame taip pat yra paprastas kodo pavyzdys. Autorius retrospektyviai naudoja tinklo skambučius ir Otto įdiegti duomenų magistralės modelį:

http://www.mdswanson.com/blog/2014/04/07/durable-android-rest-clients.html

5
27 сент. Atsakymas duotas Pete rugsėjo 27 d 2014-09-27 13:04 '14, 13:04 2014-09-27 13:04

Tarkime, aš noriu pradėti paslaugą įvykiui - onItemClicked (). Šiuo atveju imtuvo mechanizmas neveiks, nes: -
a) Persiunčiau imtuvą į paslaugą (kaip ir intent extra) iš onItemClicked ()
b) Veiksmas pereina į foną. „OnPause“ (), gavėjo nuorodą rezultato priėmime nustatiau nuliui, kad išvengtumėte veiklos nutekėjimo.
c) veikla yra sunaikinta.
d) veikla vėl sukuriama. Tačiau šiuo metu Paslauga negalės paskambinti į veiklą, nes ši gavėjo informacija yra prarasta.
Ribotas transliavimo mechanizmas arba „PendingIntent“ atrodo naudingesnis tokiuose scenarijuose - žr

4
17 марта '11 в 12:49 2011-03-17 12:49 atsakymas pateikiamas Nikhil_Katre 17 d. 11 val. 12:49 2011-03-17 12:49

Atkreipkite dėmesį, kad „Robby Pond“ sprendimas yra kažkaip nepakankamas: tokiu būdu galite leisti tik vieną „api“ skambutį vienu metu, nes „IntentService“ vienu metu apdoroja tik vieną ketinimą. Dažnai norite atlikti lygiagrečius api skambučius. Jei norite tai padaryti, turite išplėsti Paslaugą vietoj IntentService ir sukurti savo srautą.

4
28 апр. atsakymą pateikė TjerkW 28 balandis. 2011-04-28 11:15 '11, 11:15, 2011-04-28 11:15

Be to, kai pasiekiu pranešimą (vertina „Config.getURL“ („prisijungimo“), reikšmes), atrodo, kad programa truputį sustabdoma (atrodo keista - manoma, kad paslaugos idėja yra ta, kad ji veikia kitaip!)

Tokiu atveju geriau naudoti asynctask, kuris veikia kitame sriegyje, ir grąžina rezultatą atgal į ui srautą, kai baigsite.

2
04 нояб. Atsakymą pateikė Aakash 04 lapkričio. 2011-11-04 06:49 '11 at 6:49 2011-11-04 06:49

Yra ir kitas požiūris, kuris iš esmės padės jums pamiršti visą prašymų tvarkymą. Jis grindžiamas asinchroniniu eilės metodu ir atsakymu į skambutį / atgalinį ryšį. Pagrindinis privalumas yra tai, kad naudojant šį metodą galite visiškai apdoroti visą procesą (prašyti, gauti ir analizuoti atsakymą, sabe į db), visiškai skaidriai jums. Kai gausite atsakymo kodą, darbas jau baigtas. Po to jums tereikia paskambinti į „db“ ir baigsite. Tai taip pat padeda problemai, kas atsitinka, kai jūsų veikla nėra aktyvi. Kas atsitiks čia, kad visi jūsų duomenys bus saugomi jūsų vietinėje duomenų bazėje, bet atsakymas nebus apdorojamas jūsų veikloje, kuri yra ideali.

Aš parašiau apie bendrą požiūrį čia http://ugiagonzalez.com/2012/07/02/theres-life-after-asynctasks-in-android/

Į būsimus pranešimus pateiksiu konkretų kodo pavyzdį. Tikiuosi, kad tai padės, nedvejodami susisiekite su manimi, kad galėtumėte pasidalinti šiuo pasiūlymu ir išspręsti galimas abejones ar problemas.

2
05 июля '12 в 17:59 2012-07-05 17:59 atsakymas pateikiamas Jose L Ugia liepos 5 d. 12 d. 17:59 val. 2012-07-05 17:59

Robbie pateikia puikų atsakymą, nors matau, kad vis dar ieškote daugiau informacijos. Įdiegiau REST api - tai paprasta, bet ne taip. Tik po žiūrėti šį „ Google I / O“ vaizdo įrašą, supratau, kur buvau neteisingas. Tai nėra taip paprasta, kaip „AsyncTask“ kūrimas su „get / put HttpUrlConnection“ skambučiu.

0
08 апр. Atsakymą pateikė Andrew Halloran, balandžio 8 d. 2013-04-08 21:06 '13, 21:06 2013-04-08 21:06