【问题标题】:KSoap2 on Android freezing the device instead of making a webservice callAndroid 上的 KSoap2 冻结设备而不是进行 Web 服务调用
【发布时间】:2014-07-29 14:33:41
【问题描述】:

我正在尝试连接到 .NET 4.0 网络服务,该网络服务是为了从 Android 设备接收 SOAP 调用而创建的,现在托管在 本地 IIS 上用于测试目的。

我发现 ksoap2 将是一个出色的类库,可以做我想做的事。从https://code.google.com/p/ksoap2-android/ 下载了.jar 包,然后开始狂喜地敲击键盘……用我的手指。

发送的信息量从几千字节到几兆字节不等。

什么工作

HttpTransportSE.call(String, SoapSerializationEnvelope)-method 仍然在 Eclipse 的 Android 模拟器中完美运行,将调用发送到托管在本地 IIS 中的 web 服务。甚至测试了该网络服务在尝试从同一局域网中的网络浏览器打开服务地址时收到空调用。

什么不起作用

当我将 .apk 文件复制到 Android 设备、安装、启动它并尝试拨打电话时,整个程序冻结而不拨打电话。

从代码块中可以看出,在考虑了可能的错误之后出现了一些行:在模拟环境中,成功的调用返回一个 SoapPrimitive 对象或流入正确的 catch 块 根据当前情况为用户生成错误消息。

然后在实时 Android 设备上,程序永远失去响应性,必须从应用程序菜单中终止。

我尝试了什么

我从异步方法中删除了调用,并尝试直接从分配给按钮单击事件的匿名内部函数调用它。

尝试不尝试获得响应,只是拨打电话。

尝试为设备获取一个 logcat 程序以查看 UI 背后发生了什么,找到了两个,他们需要 root 访问权限,而我在设备中没有。这就是为什么我没有任何 logcat 可以显示给你,并且显示模拟器 logcat 可能(?)是无用的,因为它在那里工作正常。

没有尝试连接到本地主机。

尝试在运行 Android 4.2.2 的旧版联想平板电脑和全新的三星 Galaxy Tab 上安装该程序,两者都会遇到同样的问题,但运行良好。

代码

这是在设备/模拟器中进行调用的异步方法,其中变量 str_URLsoapRequest 分别是正确的服务地址(已检查)和格式正确的 SoapObject:

@Override
protected WebServiceResult doInBackground(Void... v) {
    WebServiceResult _ret;
    SoapSerializationEnvelope soapEnvelope= new SoapSerializationEnvelope(SoapEnvelope.VER11);
    soapEnvelope.dotNet=true;
    soapEnvelope.setAddAdornments(false);
    soapEnvelope.setOutputSoapObject(soapRequest);
    HttpTransportSE conn = new HttpTransportSE(str_URL);
    conn.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
    conn.debug = true;
    try {
        conn.call(str_ACTION, soapEnvelope); 
        SoapObject o = (SoapObject)soapEnvelope.getResponse();
        _ret = new WebServiceResult(o, WebServiceResultEnum.ok);
    } catch (NetworkOnMainThreadException e) {
        _ret = new WebServiceResult(null, WebServiceResultEnum.keskeytys);
    } catch (HttpResponseException e) {
        _ret = new WebServiceResult(null, WebServiceResultEnum.httpVirhe);
    } catch (XmlPullParserException e) {
        _ret = new WebServiceResult(null, WebServiceResultEnum.vaara_muoto);
    } catch (SocketTimeoutException e) {
        _ret = new WebServiceResult(null, WebServiceResultEnum.aikakatkaisu);
    } catch (Exception e) {
        _ret = new WebServiceResult(null, WebServiceResultEnum.keskeytys);
    }
    return _ret;
}

提前谢谢你!

【问题讨论】:

  • 不,logcat 不需要需要root。如果您在后台执行网络操作,它不会冻结您的 UI,除非您不明智地让您的 UI 线程等待后台操作或其结果。
  • 您可以在 IDE 中查看 logcat,您不需要应用程序。

标签: java android ksoap2 android-ksoap2


【解决方案1】:

有没有可能你正在做这样的事情:

YourAsyncTask task = new YourAsyncTask();
WebServiceResult result = task.doInBackground();

因为那是错误的,完全错误的。如果您直接调用doInBackground(),它将在同一个Thread 中运行,而不是在新的Thread 中运行。您需要像这样以execute() 开头AsyncTask

YourAsyncTask task = new YourAsyncTask();
task.execute();

你需要像这样实现AsyncTask

public class ExampleTask extends AsyncTask<Void, Void, WebServiceResult> {

    public interface FinishedListener {
        public void onFinished(WebServiceResult result);
    }

    private final FinishedListener finishedListener;

    public ExampleTask(FinishedListener listener) {
        this.finishedListener = listener;
    }

    @Override
    protected WebServiceResult doInBackground(Void... params) {
        WebServiceResult result = ...;
        return result;
    }

    @Override
    protected void onPostExecute(WebServiceResult result) {
        super.onPostExecute(result);

        if(this.finishedListener != null) {
            this.finishedListener.onFinished(result);
        }
    }
}

如果你以这种方式实现它,你可以像这样使用它:

ExampleTask task = new ExampleTask(new ExampleTask.FinishedListener() {
    @Override
    public void onFinished(WebServiceResult result) {
        // This will be called if the task has finished
    }
});
task.execute();

【讨论】:

  • 感谢您对正确使用异步方法的全面说明。这一切我都不知道!但正如我在原始帖子中已经说过的那样,我已经尝试从异步方法中删除对 web 服务的调用并直接在 UI 中进行调用。我知道Android不喜欢主线程中的网络操作,这就是为什么我有一个catch-block,所以我可以看看调用是否有效。编辑:过早提交评论。继续:所以我完全按照您的指示进行了更改,但程序仍然在真实设备上冻结并在模拟器上运行。
【解决方案2】:

似乎我在 AndroidManifest.xml 中声明了最低 SDK 为 14目标 SDK 为 17。我没有在较新的 sdk 中使用任何花哨的东西,所以我将目标 SDK 降低到与最低 SDK 相同的级别,14。我还有一个 Avast!在我删除的平板电脑上运行的防病毒服务

这解决了我的问题。可能就是 Avast!防病毒程序想要阻止来自未从 Play 商店下载的应用程序的所有通信。不知道改目标SDK有没有效果。

【讨论】:

    【解决方案3】:

    嗯,我和你有同样的问题。当它转到方法transport.call 时,它会暂停,一会儿,它会抛出超时问题。起初,我以为可能是网络不好,但服务器 logcat 显示不是问题。请求很好,反应很好。我的业务流程如下:

    首先,我通过 ksoap 内部子线程从服务器获取一个列表,然后循环该列表,根据列表的每个项目发送一个 ksoap 请求。这意味着它将发送另一个list.size() 请求。在真实设备中调试时,会出现上述问题。我通过在获取列表并在新的子线程中发出所有list.size 请求后启动一个新的子线程来解决它。因此,在 android 中使用 ksoap 可能会导致线程阻塞,从而导致 ioexception。所以当你把它放在一个新线程中时,它会从父级 catch 异常中逃脱并且工作正常。

    【讨论】:

    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    相关资源
    最近更新 更多