In einer Android App, welche mit einem Server kommunizieren muss, hat man die Qual der Wahl.
Am besten setzt man hier auf etablierte Techniken, wie beispielsweise einem WebService.
In unserem Beispiel zeigen wir die Kommunikation zwischen Android und einem in PHP geschriebenem WebService via SOAP und ohne externe Android Libraries.

Was wird benötigt

– Einen PHP fähigen Webserver
– Eine SOAP-Server Implementation
– Einen WSDL-Generator
– Und natürlich eine Android App 😉

Alles in einzelnen Schritten zu dokumentieren wäre für diesen Artikel zu aufwendig. Daher wird einiges ausschließlich in Form von Code gezeigt.

Server

Der SOAP Funktionen

Folgender Code wird in eine PHP Datei namens soapFunctions.class.inc.php gepackt.

class MySoapFunctions
{
    /**
     * TestCall Method
     *
     * @param string $t
     * @param string $param
     * @return string Result of the Request
     */
    public function TestCall($t, $param) {
        return "Hello $param";
    }
}

Hier definieren wir eine Funktion namens TestCall mit zwei Parametern. Der Java Doc Kommentarblock oberhalb der Funktion ist dabei (wirklich) notwendig. Er wird bei der späteren WSDL Generierung eine entscheidende Rolle spielen.

Der SOAP-Server

Folgenden Code packt ihr ein eine PHP Datei namens interface.php, welche später von eurem Java Android Code angesprochen wird.

$server = new SoapServer("wsdl/wsdl.wsdl", array("cache_wsdl" => "WSDL_CACHE_NONE"));
$server->setClass("MySoapFunctions");
$server->handle();

Der SoapServer ist Bestandteil von PHP und benötigt lediglich die Pfadangabe zur WSDL (Web-Service-Description-Language) Datei. Diese kann man entweder automatisiert erstellen oder von verschiedenen Tools erstellen lassen.
Jedes mal wenn sich eine Methodensignatur im MySoapFunctions ändert oder eine neue Methode hinzugefügt wird, muss die WSDL erneut generiert werden.

Client

Die Service Klasse

Um mittels Android nun auf diese in PHP definierten Funktionen zugreifen zu können, benötigen wir nun 2 Klassen.
Die Service Klasse wird unser Wrapper um die SOAP spezifischen Bereiche darstellen.

Dazu legen wir eine neue Klasse namens SoapService in Android an und füllen Sie mit folgendem Code:

public class Service {
    private static final String SOAP_ACTION = "http://domain.tld/api/interface.php/";
    private static final String NAMESPACE = "http://domain.tld/api/interface.php";
    private static final String URL = "http://domain.tld/api/interface.php";


public static String TestCall(String t, String param) {
    HashMap parameters = new HashMap();
    parameters.put("t", t);
    parameters.put("param", param);

    String resp = (String)CallMethod("TestCall", parameters);
    return resp;
}


public static Object CallMethod(String SoapMethod, HashMap parameters) {
    SoapObject request = new SoapObject(NAMESPACE, SoapMethod);

    for (HashMap.Entry entry : parameters.entrySet()) {
        String key = entry.getKey();
        Object value = entry.getValue();

        request.addProperty(key, value);
    }

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.dotNet = false;
    envelope.setOutputSoapObject(request);

    HttpTransportSE aht = new HttpTransportSE(URL);
    @SuppressWarnings("unused")
    Object result;
    try {
        aht.call(SOAP_ACTION + SoapMethod, envelope);
        result = (Object) envelope.getResponse();
    }
    catch (Exception ex) {
        Log.e("", "Exception on CallMethod = " + ex.getMessage());
        result = ex.getMessage();
    }

    //Log.d("", result.toString());

    return result;
}

Für jede im PHP hinzugefügte Funktion benötigen wir in dieser Klasse eine entsprechende Methode.
Jede zusätzliche Methode wird den selben Aufbau wie die TestCall Methode haben. Wichtig ist sowie die Benennung, die Reihenfolge und Vollständigkeit der Parameter.

AsyncService

Da Netzwerk Aufgaben in Android nicht im UI-Thread laufen dürfen, müssen wir den Aufruf in einen Hintergrundthread verlegen.
Dazu eignet sich am besten ein AsyncTask.
Hier nun eine Beispiel Implementierung:

public class AsyncService extends AsyncTask {
    private OnTaskCompleted listener;
    private String methodName;
    private Context context;

    public AsyncService(OnTaskCompleted listener) {
        this.listener = listener;
    }

    @Override
    protected String doInBackground(String... params) {

        this.methodName = params[0];
        
        if (params[0].equals("TestCall"))
            return Service.TestCall(params[1], params[1]);
        else if (params[0].equals("anotherMethod"))
            // return Service.anotherMethod();
             
        return "-no-method-found-";
    }


    @Override
    protected void onPostExecute(String result) {
        this.listener.onTaskCompleted(this.methodName, result);
    }

    @Override
    protected void onPreExecute() {}

    @Override
    protected void onProgressUpdate(Void... values) {}

    public interface OnTaskCompleted {
        void onTaskCompleted(String methodName, String response);
    }
}

Aufruf in einer Activity/Fragment (o.Ä)

Und so wird eine Funktion in PHP mittels Java innerhalb einer Activity oder eines Fragments (jede andere Klasse funktioniert selbstverständlich auch), ausgeführt.
Durch die asynchrone Ausführung benötigen wir einen Callack Mechanismus, welchen wir durch das Implementieren des AsyncService.OnTaskCompleted Interfaces erreichen. Nachdem ein Vorgang ausgeführt wurde wird das Ergebnis an die onTaskCompleted Methode übergeben.

public class MyFragment extends ListFragment implements AsyncService.OnTaskCompleted {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         new AsyncService(this).execute("TestCall", parameterT, parameterParam);
    }

    @Override
    public void onTaskCompleted(String methodName, String response) {
        if (methodName.equals("TestCall")) {
            Log.d("", "TestCall was executed, response is => + response);
        }
    }
}

Tipp: Als Datenformat zur Kommunikation eignet sich XML oder JSON!

Categories: AndroidPHP