Olá pessoal!
Enfim consegui fazer um Webservice funcionar em Android. O que eu fiz para isso funcionar? Primeiramente, o código do Webservice que foi publicado com Tomcat e Axis é o seguinte:
public class Calculator {
public int somar(int numA, int numB) {
return numA + numB;
}
public int subtrair(int numA, int numB) {
return numA - numB;
}
public int multiplicar(int numA, int numB) {
return numA * numB;
}
public int dividir(int numA, int numB) {
if (numB != 0)
return numA / numB;
return 0;
}
}
Eu o publiquei seguindo o tutorial abaixo:
http://imasters.com.br/artigo/1863/java/web_services_in_java/
No meu projeto Android, criei apenas 2 classes, que listam no Logcat o resultado do Webservice. A classe que realiza a conexão com o Webservice é a classe abaixo:
package br.com.android.projeto;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
public class WebService {
private static final String NAMESPACE = "com.service.Calculator";
private static final String URL = "http://192.168.1.2:8080/axis/Calculator.jws?wsdl";
private static final String SOAP_ACTION = "Calculator";
public String webServiceOperacao(String operacao, Integer numA, Integer numB) {
SoapObject request = new SoapObject(NAMESPACE, operacao);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
String retorno = null;
// Adiciona parâmetros
request.addProperty("numA", numA);
request.addProperty("numB", numB);
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn;
retorno = resultsRequestSOAP.toString();
} catch (Exception e) {
e.printStackTrace();
}
return retorno;
}
}
Reparem que as dúvidas que eu tinha no início desse tópico (o que escrever na constante NAMESPACE, etc) foram solucionadas.
A Activity que imprime o resultado desse Webservice no Logcat é a classe abaixo:
package br.com.android.projeto;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
private WebService ws = new WebService();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
operacao("somar", 2, 2, "Somar");
operacao("subtrair", 6, 3, "Subtrair");
operacao("multiplicar", 7, 3, "Multiplicar");
operacao("dividir", 21, 3, "Dividir");
}
public void operacao(String operacao, Integer numA, Integer numB, String texto) {
operacao = ws.webServiceOperacao(operacao, numA, numB);
// Filtra o valor retornado pelo WebService
String[] primeiraParte = operacao.split("=");
String[] segundaParte = primeiraParte[1].split(";");
String retorno = segundaParte[0];
Log.i("webservice", texto + ": " + Integer.valueOf(retorno));
}
}
Porém, agora que consegui um Webservice funcional em Android, decidi ir para o que realmente interessa, que é listar informações de uma tabela de Banco de Dados, via Android. O que eu realmente preciso é criar uma aplicação em Android que busque de um Webservice informações sobre um Banco de Dados Sqlite, rodando em Windows (através da IDE SQLite Expert Personal). Ou seja, o aplicativo em Android acessará um Webservice, que por sua vez listará todos os registros (select * from tabela) de uma determinada tabela de um repositório localizado na mesma máquina que está rodando o Webservice. Logo, não usarei mais um Webservice como o que listei no início do tópico (que soma, subtrai, multiplica e divide). Usarei um Webservice bem mais complexo.
O novo Webservice que criei, afim de acessar um Banco de Dados Sqlite, rodando na minha máquina, é o seguinte:
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Dao {
// Primeira sub-classe
public class Conexao {
public Conexao() {
try{
// Carregando classe que será utilizada como conector
Class.forName("org.sqlite.JDBC").newInstance();
} catch(ClassNotFoundException e){
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private Connection connection;
public Connection getConnection(){
if (connection == null){
try{
// Tentando realizar conexão
connection = DriverManager.getConnection("jdbc:sqlite:/databases/repositorio_pergunta");
System.out.println("Conexão ok.");
} catch (SQLException e) {
e.printStackTrace();
}
}
return connection;
}
public void fecharConexao(){
try{
connection.close();
System.out.println("Conexão fechada.");
} catch (SQLException e){
e.printStackTrace();
}
}
}
public String listarPerguntas(Integer inteiro) throws Exception {
String retorno = null;
try {
// 1. Consultar dados
Conexao con = new Conexao();
PreparedStatement pst = con.getConnection().prepareStatement(
"select id, texto, resposta from pergunta");
// 2. Executar consulta
pst.execute();
// 3. Processar resultado
ResultSet rs = pst.getResultSet();
while (rs.next()){
retorno += rs.getInt("id") + ";";
retorno += rs.getString("texto") + ";";
retorno += rs.getInt("resposta") + ";";
retorno += "#";
}
// 4. Fechar tudo
rs.close();
pst.close();
} catch (SQLException e) {
System.out.println("Erro ao listar Pergunta.");
e.printStackTrace();
}
return retorno;
}
}
Ou seja, ele apenas lista todos os registros da tabela Pergunta, e os concatena em uma string, que será retornada. Decidi retornar uma string para não ter que lidar com tipos complexos (o ideal seria retornar um List no método listarPerguntas).
A tabela Pergunta possui os seguintes campos abaixo:
create table pergunta (
id integer primary key autoincrement not null,
texto text not null,
resposta integer not null
);
Atualmente ela está populada com 10 registros. O campo resposta é um Integer porque no Sqlite não existe tipo Boolean. Neste campo, 1 indica TRUE, e 0 indica FALSE.
A classe do Android que acessa esse novo Webservice é mostrada abaixo:
package br.com.android.projeto;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
public class WebService {
private static final String NAMESPACE = "com.service.Dao";
private static final String URL = "http://192.168.1.2:8080/axis/Dao.jws?wsdl";
private static final String SOAP_ACTION = "Dao";
public String webServiceBanco() {
SoapObject request = new SoapObject(NAMESPACE, "listarPerguntas");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
String retorno = null;
// Adiciona parâmetros
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn;
retorno = resultsRequestSOAP.toString();
} catch (Exception e) {
e.printStackTrace();
}
return retorno;
}
}
E a Activity que mostra no Logcat o resultado dessa listagem é mostrada abaixo.
package br.com.android.projeto;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
private WebService ws = new WebService();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String retorno = ws.webServiceBanco();
Log.i("webservice", "Retorno: " + retorno);
}
}
Porém, ao executar este novo Webservice, alguns erros aparecem:
[list]
02-14 18:33:29.805: I/ActivityManager(68): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=br.com.android.projeto/.MainActivity }
02-14 18:33:30.155: W/System.err(304): java.net.SocketException: Permission denied
02-14 18:33:30.195: W/System.err(304): at org.apache.harmony.luni.platform.OSNetworkSystem.createStreamSocketImpl(Native Method)
02-14 18:33:30.195: W/System.err(304): at org.apache.harmony.luni.platform.OSNetworkSystem.createStreamSocket(OSNetworkSystem.java:186)
02-14 18:33:30.225: W/System.err(304): at org.apache.harmony.luni.net.PlainSocketImpl.create(PlainSocketImpl.java:265)
02-14 18:33:30.225: W/System.err(304): at java.net.Socket.checkClosedAndCreate(Socket.java:873)
02-14 18:33:30.245: W/System.err(304): at java.net.Socket.connect(Socket.java:1020)
02-14 18:33:30.245: W/System.err(304): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.(HttpConnection.java:62)
02-14 18:33:30.255: W/System.err(304): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpConnectionPool.java:88)
02-14 18:33:30.255: W/System.err(304): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHTTPConnection(HttpURLConnectionImpl.java:927)
02-14 18:33:30.255: W/System.err(304): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:909)
02-14 18:33:30.255: W/System.err(304): at org.ksoap2.transport.ServiceConnectionSE.connect(Unknown Source)
02-14 18:33:30.285: W/System.err(304): at org.ksoap2.transport.HttpTransportSE.call(Unknown Source)
02-14 18:33:30.285: W/System.err(304): at br.com.android.projeto.WebService.webServiceBanco(WebService.java:21)
02-14 18:33:30.315: W/System.err(304): at br.com.android.projeto.MainActivity.onCreate(MainActivity.java:14)
02-14 18:33:30.315: W/System.err(304): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-14 18:33:30.315: W/System.err(304): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
02-14 18:33:30.315: W/System.err(304): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
02-14 18:33:30.315: W/System.err(304): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
02-14 18:33:30.315: W/System.err(304): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
02-14 18:33:30.315: W/System.err(304): at android.os.Handler.dispatchMessage(Handler.java:99)
02-14 18:33:30.325: W/System.err(304): at android.os.Looper.loop(Looper.java:123)
02-14 18:33:30.325: W/System.err(304): at android.app.ActivityThread.main(ActivityThread.java:4627)
02-14 18:33:30.325: W/System.err(304): at java.lang.reflect.Method.invokeNative(Native Method)
02-14 18:33:30.355: W/System.err(304): at java.lang.reflect.Method.invoke(Method.java:521)
02-14 18:33:30.355: W/System.err(304): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
02-14 18:33:30.355: W/System.err(304): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
02-14 18:33:30.355: W/System.err(304): at dalvik.system.NativeStart.main(Native Method)
02-14 18:33:30.355: I/webservice(304): Retorno: null
02-14 18:33:30.455: I/ActivityManager(68): Displayed activity br.com.android.projeto/.MainActivity: 551 ms (total 551 ms)
[/list]
O erro SocketException, creio eu, significa que tenho que fazer algo para que eu consiga acessar um Webservice que acessa um DAO. Mas que algo seria isso?
Logo, eu consigo acessar um Webservice simples em Android. Mas acessar outro que retorna dados de um Banco de Dados? Não!
Alguém sabe o que devo mudar na classe WebService.java para que meu aplicativo funcione?