Como prometido no artigo anterior, o Tech-Portugal vai dar aos seus leitores as ferramentas necessárias para criar, de forma simples, uma aplicação Android a comunicar com o servidor recorrendo a WebServices.
Por termos o servidor a correr na máquina local, vamos usar o emulador do Android Studio, pois será mais fácil testar e evitar complicações no exemplo a demonstrar. Caso o leitor futuramente queira colocar o servidor a correr em rede, poderá faze-lo bastando alterar os acessos no código!
Servidor
[wptab name=’Interface’]
A interface irá ter todos os métodos que o WebService deverá implementar. Neste caso, terá apenas a função soma.
@WebService public interface myWSInterface { @WebMethod int soma(String num1, String num2); }
[/wptab]
[wptab name=’WebService’]
Criação de uma classe myWS neste caso, que irá implementar a interface anteriormente criada. Nesta classe, iremos programar o que irá fazer o método soma ou quaisquer outros métodos que o leitor queira implementar.
package ws_android; import javax.jws.WebService; @WebService(endpointInterface = "ws_android.myWSInterface") public class myWS implements myWSInterface{ public myWS(){} @Override public int soma(String num1, String num2) { System.out.println("Recebi Algo"); return Integer.parseInt(num1) + Integer.parseInt(num2); } }
[/wptab]
[wptab name=’Publisher’]
Serve apenas para criar um endpoint e publicar o WebService no ip e porto definidos.
public class Publisher { public static void main(String[] args) { Endpoint.publish("http://127.0.0.1:8080/ws_android", new myWS()); } }
[/wptab]
[end_wptabset]
Android App
[wptab name=’KSoap Configuration’]
Antes de se avançar para qualquer outro passo, o utilizador deverá criar um projeto no android studio com uma “blank activity”.
Para que o WebService funcione com pedidos SOAP, deveremos recorrer à dependência do KSOAP. Deverá então dirigir-se ao ficheiro gradle, do módulo e, acrescentar às dependências o seguinte:
compile files('libs/ksoap2-android-assembly-2.5.2.jar')
Faça clean do projeto!
De seguida deverá realizar o download do KSOAP aqui.
Após o Download, deverá copiar o .jar da qual acabou de realizar a transferência e, deverá dirigir-se à pasta do seu projeto, seguida da pasta app e colocar o .jar dentro da pasta libs, ou seja:
“[O_SEU_PROJETO] -> app -> libs” e copiar para lá o .jar do KSOAP.
Para verificar que a dependência está correta, poderá dirigir-se a “File” -> “Project Structure” e:
Note-se que poderá ter realizado o download de uma versão diferente do ksoap. Na imagem acima, o ksoap usado era da versão 3.6.0, diferente do ksoap disponibilizado para download.
[/wptab]
[wptab name=’Layout’]
O layout da aplicação a usar poderá ser o seguinte:
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:weightSum="1"> <EditText android:layout_width="254dp" android:layout_height="wrap_content" android:id="@+id/num1" /> <EditText android:layout_width="249dp" android:layout_height="wrap_content" android:id="@+id/num2" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enviar" android:id="@+id/btnEnviar" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_marginTop="81dp" /> <TextView android:layout_width="167dp" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="Large Text" android:id="@+id/textViewResultado" android:layout_weight="0.12" /> </LinearLayout>
[/wptab]
[wptab name=’MainActivity’]
É importante clarificar o seguinte:
- URL: Neste caso, a variável URL deverá ser 10.0.2.2:8080 pois estamos a correr com o emulador. Este endereço de URL é o mesmo que o localhost mas, como o emulador está a correr em máquina virtual.
O código que se segue apenas representa a acção ao evento do botão, o pedido e sucessiva resposta SOAP do servidor.
public class MainActivity extends AppCompatActivity { // localização do servidor private static final String NAMESPACE = "http://ws_android/"; private static String URL="http://10.0.2.2:8080/ws_android?wsdl"; // nome dos métodos a chamar e, ação a realizar private static final String METHOD_NAME = "soma"; private static final String SOAP_ACTION = NAMESPACE + METHOD_NAME; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button)findViewById(R.id.btnEnviar); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v){ TextView tvNum1 = (TextView)findViewById(R.id.num1); TextView tvNum2 = (TextView)findViewById(R.id.num2); // Content values com o valor dos numeros // chamada ao método soap ContentValues cv = new ContentValues(); cv.put("num1", tvNum1.getText().toString()); cv.put("num2", tvNum2.getText().toString()); new SoapRequest().execute(cv); } }); } // Função para atualizar vista private void AtualizaVista(String resultado){ TextView tvResultado = (TextView)findViewById(R.id.textViewResultado); tvResultado.setText(resultado); } private class SoapRequest extends AsyncTask<ContentValues, Void, String> { @Override protected String doInBackground(ContentValues... params) { String result; SoapObject request = null; request = new SoapObject(NAMESPACE, METHOD_NAME); // get dos numeros que estavam na TextView String num1 = params[0].getAsString("num1"); String num2 = params[0].getAsString("num2"); // Passagem dos numeros para o webservice request.addProperty("arg0", num1); request.addProperty("arg1", num2); // Criacao de um envelope para enviar ao servidor // Este envelope irá conter o pedido e as variáveis da funcao soma SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.setOutputSoapObject(request); HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); try { androidHttpTransport.call(SOAP_ACTION, envelope); // Obter a resposta, neste caso será a soma dos dois numeros enviados SoapPrimitive resultRequest = (SoapPrimitive) envelope.getResponse(); Log.wtf("[RESPONSE]", resultRequest.toString()); result = resultRequest.toString(); } catch (IOException e) { result = "Error: " + e; //Log.wtf("[ERROR]", "error 1"); } catch (XmlPullParserException e) { result = "Error: " + e; } Log.wtf("[RESULT]", result); return result; } // Atualizar a vista após a execução da AsyncTask protected void onPostExecute(String res) { // TODO: check this.exception // TODO: do something with the feed AtualizaVista(res); } }
[/wptab]
[end_wptabset]
Uma vez que a aplicação irá aceder à internet, o leitor não se deverá esquecer de dar a devida permissão:
<uses-permission android:name="android.permission.INTERNET" />
Com isto, o resultado deverá ser trivial. O programa está preparado para receber números inteiros (não existem verificações nem validações caso o utilizador insira floats ou strings).