Erholsamer API-Service
Ich bin auf der Suche um eine Dienstleistung, die ich verwenden können, um Anrufe zu tätigen, um eine web-basierte REST-API.
Grundsätzlich möchte ich einen Dienst starten, app auf init, dann möchte ich in der Lage sein, zu bitten, die service anfordern einer url und gibt die Ergebnisse zurück. In der Zwischenzeit möchte ich die Möglichkeit, um ein Fenster oder etwas ähnliches.
Habe ich einen service-aktuell die IDL verwendet, habe ich irgendwo gelesen, dass Sie nur wirklich brauchen, diese für die cross-app-communication, die so denken, diese Bedürfnisse zu entfernen, aber nicht sicher sind, wie Sie tun, Rückrufe, ohne es. Auch wenn ich drücken Sie die post(Config.getURL("login"), values)
scheint die app auf pause für eine Weile (scheint seltsam - dachte, die Idee hinter dem Dienst war, dass es läuft auf einen anderen thread!)
Aktuell habe ich einen service mit post und get-http-Methoden innerhalb von ein paar AIDL-Dateien (für zwei-Wege-Kommunikation), einem Dienste-Verwalter, die sich mit starten, beenden, binden etc. auf den service und ich bin dynamisch erstellen eines Handler mit spezifischen code für die Rückrufe, wie gebraucht.
Ich nicht wollen, dass jemand mir eine komplette code-Basis zu arbeiten, aber ein paar Tipps würde sehr geschätzt werden.
Code in (meist) voll:
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) {...}
};
Ein paar AIDL-Dateien:
package com.something.android
oneway interface IRemoteServiceCallback {
void userLogIn(String result);
}
und
package com.something.android
import com.something.android.IRemoteServiceCallback;
interface IRestfulService {
void doLogin(in String username, in String password);
void registerCallback(IRemoteServiceCallback cb);
}
und der 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 und binden:
//this I'm calling on app onCreate
servicemanager = new ServiceManager(this);
servicemanager.startService();
servicemanager.bindService();
application = (ApplicationState)this.getApplication();
application.setServiceManager(servicemanager);
service-Funktion aufrufen:
//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);
}
}
};
InformationsquelleAutor der Frage Martyn | 2010-07-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Ihr Dienst wird ein Teil von Ihnen-Anwendung dann sind Sie, dass es viel komplexer ist, als es sein muss. Da haben Sie einen einfachen Anwendungsfall, einige Daten aus einem RESTful Web Service, die Sie in Aussehen sollte ResultReceiver und IntentService.
Dieser Dienst + ResultReceiver Muster funktioniert durch starten oder die Bindung an den service mit startService() wenn Sie wollen ein bisschen action. Sie können angeben, welche operation auf und übergeben Ihr ResultReceiver (die Tätigkeit), über die extras, die in der Absicht.
In den service, den Sie implementieren onHandleIntentum die operation, die in der Absicht. Wenn der Vorgang abgeschlossen ist, verwenden Sie die übergebene ResultReceiver zu senden eine Nachricht zurück, um die Aktivität an dem Punkt onReceiveResult aufgerufen werden.
Also zum Beispiel, Sie möchten, ziehen Sie einige Daten von Ihrem Web-Service.
Ich weiß, Sie erwähnt Sie nicht wollen, eine code-Basis, aber die open-source - Google I/O 2010 app nutzt einen service in dieser Art und Weise bin ich zu beschreiben.
Aktualisiert hinzufügen von Beispielcode:
Aktivität.
Service:
ResultReceiver Erweiterung - bearbeitet zu implementieren, MyResultReceiver.Empfänger
InformationsquelleAutor der Antwort Robby Pond
Entwicklung von Android REST client applications wurde eine großartige Ressource für mich. Der Sprecher zeigt keine code, er geht einfach über design-überlegungen und Techniken, die bei der Zusammenstellung eines rock-solid-Rest-Api in android. Wenn Ihr einen podcast irgendwie person ist oder nicht, würde ich empfehlen, geben diese eine mindestens eine hören, aber ich persönlich habe hörte es sich wie 4 oder fünf mal so weit und ich bin wahrscheinlich hören Sie es wieder.
Die Entwicklung von Android REST client applications
Autor: Virgil Dobjanschi
Beschreibung:
Dieser Sitzung präsentieren architektonische überlegungen für die Entwicklung von RESTful-Anwendungen auf der Android-Plattform. Es konzentriert sich auf design-patterns, Plattform-integration und performance-Probleme spezifisch für die Android-Plattform.
Und es gibt so viele überlegungen, die ich wirklich nicht gemacht hätte in der ersten version von meine-api, die ich habe zu überarbeiten
InformationsquelleAutor der Antwort Terrance
Nein, Sie müssen erstellen ein thread sich selbst, ein Lokalen service läuft im UI-thread standardmäßig.
InformationsquelleAutor der Antwort Soumya Simanta
Ich weiß, @Martyn will nicht vollständigen code, aber ich denke, diese Anmerkung das ist gut für diese Frage:
10 Open-Source-Android-Apps, die jedes Android-Entwickler muss sich über
Foursquared für Android ist open-sourceund haben eine interessante code-Muster der Interaktion mit der foursquare-REST-API.
InformationsquelleAutor der Antwort panchicore
Wollte nur zeigen Sie alle in Richtung einer eigenständigen Klasse, ich rollte, beinhaltet die gesamte Funktionalität.
http://github.com/StlTenny/RestService
Wird die Anfrage als nicht-blockierend, und gibt die Ergebnisse in einer einfach zu implementieren handler. Auch kommt mit einer Beispiel-Implementierung.
InformationsquelleAutor der Antwort StlTenny
Ich würde empfehlen, den REST-client Nachrüstung.
Ich fand diese gut geschrieben blog-post sehr hilfreich, es enthält auch eine einfache Beispiel-code.
Der Autor verwendet Nachrüstung, um die Netzwerk-Aufrufe und Otto zu implementieren eines data bus Muster:
http://www.mdswanson.com/blog/2014/04/07/durable-android-rest-clients.html
InformationsquelleAutor der Antwort Pete
Können sagen, ich will den Dienst starten, auf ein Ereignis - onItemClicked() eine Schaltfläche. Die Empfänger-Mechanismus nicht funktionieren würde, in diesem Fall, weil :-
a) ich übergeben Sie den Empfänger an den service (wie in Absicht extra) aus onItemClicked()
b) Aktivitäten in den hintergrund wechselt. In onPause() ich habe die receiver-Referenz innerhalb der ResultReceiver auf null, um zu vermeiden undicht die Tätigkeit.
c) die Aktivität zerstört wird.
d) Aktivität erzeugt wird, wieder. Aber an diesem Punkt wird der Dienst nicht in der Lage sein, einen Rückruf zu der Aktivität, die receiver-Referenz verloren gegangen ist.
Der Mechanismus, der eine begrenzte broadcast-oder ein PendingIntent scheint zu sein, nützlich in solchen Szenarien beziehen sich auf Benachrichtigen Aktivität von service
InformationsquelleAutor der Antwort Nikhil_Katre
Beachten Sie, dass die Lösung von Robby Teich irgendwie fehlt: auf diese Weise können Sie nur erlauben Sie eine todo-api-Aufruf in einer Zeit, da der IntentService behandelt nur einen Vorsatz zu einer Zeit. Oft Sie möchten durchführen, parallel-api-Aufrufe. Wenn Sie möchten, todo dies haben Sie zu verlängern Service statt IntentService und erstellen Sie Ihre eigenen thread.
InformationsquelleAutor der Antwort TjerkW
In diesem Fall ist es besser, asynctask, die läuft auf einem anderen thread und return Ergebnis zurück an den ui-thread auf die Fertigstellung.
InformationsquelleAutor der Antwort Aakash
Es ist ein anderer Ansatz hier, die im Grunde hilft Sie zu vergessen, über die gesamte Verwaltung der Anforderungen. Es basiert auf einer asynchronen Warteschlange Methode und ein callable/callback-basiert Antwort.
Der Vorteil ist, dass durch die Nutzung dieser Methode werden Sie in der Lage sein, um den gesamten Prozess (request, get und parse response, sabe, - db) völlig transparent für Sie. Sobald Sie die Antwort-code-die Arbeit ist bereits getan. Nach, die Sie gerade brauchen, um einen Anruf zu tätigen, um Ihre db-und Sie sind fertig.
Es hilft auch mit der Problematik, was passiert, wenn Sie Ihre Tätigkeit nicht aktiv.
Was hier geschehen ist, Sie haben alle Ihre Daten, gespeichert in Ihrer lokalen Datenbank, aber die Antwort wird nicht verarbeitet, die durch Ihre Aktivität, das ist die ideale Art und Weise.
Schrieb ich über einen Allgemeinen Ansatz hier
http://ugiagonzalez.com/2012/07/02/theres-life-after-asynctasks-in-android/
Werde ich dabei sein, konkrete Beispiel-code in kommenden Beiträgen.
Hoffe, es hilft, fühlen Sie sich frei, mich zu Kontaktieren für den Austausch der Ansatz und die Lösung von möglichen zweifeln oder Problemen.
InformationsquelleAutor der Antwort Jose L Ugia
Robby bietet eine große Antwort, aber ich kann sehen, dass Sie noch auf der Suche nach mehr Informationen. Ich implementierte REST-api-Aufrufe, die einfache, ABER falsche Weg. Es war nicht, bis beobachten dieses Google I/O videodass ich Verstand, wo ich schief ging. Es ist nicht so einfach wie die Zusammenstellung eines AsyncTask mit einer HttpUrlConnection get/put call.
InformationsquelleAutor der Antwort Andrew Halloran