在 Android 中使用基于 HTTPS 的 SOAP+XML 请求 Exchange Web Services 2007/2010

2024-02-19

我使用 Microsoft 的以下 C# 代码来请求 EWS 2010MSDN链接 http://msdn.microsoft.com/en-us/library/cc526065.aspx它起作用了。我需要同样的 Android 解决方案。

我尝试使用以下代码,但没有帮助

    DefaultHttpClient client = new HttpsClient(
                MyActivity.this);

        requestBytes = myXMLStringRequest.getBytes("UTF-8");

        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "text/xml;utf-8");
        if (requestBytes != null) {
            httpPost.setHeader("Content-length",
                    String.valueOf(requestBytes.length));
            Log.d(TAG, "content length: " + requestBytes.length);
        }

        client.getCredentialsProvider().setCredentials(
                new AuthScope(url, 443),
                new UsernamePasswordCredentials(userName,
                        password));
        Log.d(TAG, "Begin request");
        HttpResponse response = client.execute(httpPost);
        Log.d(TAG, "status Line: " + response.getStatusLine().toString());

这是我的 xml 请求

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" 
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> 
<soap:Body>
<GetFolder xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"                xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">   
<FolderShape>     
    <t:BaseShape>Default</t:BaseShape>  
</FolderShape>    
<FolderIds>      
    <t:DistinguishedFolderId Id="inbox"/>     
    <t:DistinguishedFolderId Id="deleteditems"/>  
</FolderIds> 
</GetFolder>

我还使用带有密钥库的自定义 HttpsClient。

public class HttpsClient extends DefaultHttpClient {
private final Context context;

public HttpsClient(final Context context) {
    super();
    this.context = context;
}

/**
 * The method used to create client connection manager
 */
@Override
protected ClientConnectionManager createClientConnectionManager() {
    final SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 8080));

    // Register for port 443 our SSLSocketFactory with our keystore
    // to the ConnectionManager
    registry.register(new Scheme("https", newSslSocketFactory(), 8443));
    return new SingleClientConnManager(getParams(), registry);
}

private SSLSocketFactory newSslSocketFactory() {
    try {
        // Get an instance of the Bouncy Castle KeyStore format
        final KeyStore trusted = KeyStore.getInstance("BKS");
        // Get the raw resource, which contains the keystore with
        // your trusted certificates (root and any intermediate certs)
        final InputStream inputStream = context.getResources().openRawResource(R.raw.parkgroup_ws_client);
        try {
            // Initialize the keystore with the provided truste
            // certificates
            // Also provide the password of the keystore
            trusted.load(inputStream, "myKeyStorePassword".toCharArray());
        } finally {
            inputStream.close();
        }
        // Pass the keystore to the SSLSocketFactory. The factory is
        // responsible
        // for the verification of the server certificate.
        final SSLSocketFactory ssf = new SSLSocketFactory(trusted);
        // Hostname verification from certificate
        // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return ssf;
    } catch (Exception e) {
        Log.e("MYTAG", e.getMessage());
        throw new AssertionError(e);
    }
}

@Override
protected HttpParams createHttpParams() {
    final HttpParams httpParams = super.createHttpParams();
    httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 1000);
    httpParams.setParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false);
    return httpParams;
}

}

但总是显示“连接超时“并且没有任何反应
请告诉我我的问题出在哪里?任何例子都会有帮助。 提前致谢!


非常感谢尼古拉·埃连科夫!

最后,我找到了解决方案。我点击这个链接:在 Android 上使用自定义证书信任存储 http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html

首先,我使用DefaultHttpClient代替HttpClient(方法createHttpClientWithDefaultSocketFactory()应该return DefaultHttpClient):

private DefaultHttpClient createHttpClientWithDefaultSocketFactory(
        KeyStore keyStore, KeyStore trustStore) {
    try {
        SSLSocketFactory sslSocketFactory = SSLSocketFactory
                .getSocketFactory();
        if (keyStore != null && trustStore != null) {
            sslSocketFactory = new SSLSocketFactory(keyStore,
                    KEYSTORE_PASSWORD, trustStore);
        } else if (trustStore != null) {
            sslSocketFactory = new SSLSocketFactory(trustStore);
        }

        return createHttpClient(sslSocketFactory);
    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e);
    }
}

然后我添加CredentialsProvider用于身份验证。

    DefaultHttpClient client = createHttpClientWithDefaultSocketFactory(
                keyStore, trustStore);
        HttpPost httpPost = new HttpPost(SERVER_AUTH_URL);
        httpPost.setHeader("Content-type", "text/xml;utf-8");

        StringEntity se = new StringEntity(builder.toString(), "UTF8");
        se.setContentType("text/xml");
        httpPost.setEntity(se);
        CredentialsProvider credProvider = new BasicCredentialsProvider();

        credProvider.setCredentials(new AuthScope(URL,
                443), new UsernamePasswordCredentials(USERNAME, password));

        // This will exclude the NTLM authentication scheme

        client.setCredentialsProvider(credProvider);
        HttpResponse response = client.execute(httpPost);

现在,它可以很好地工作了!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Android 中使用基于 HTTPS 的 SOAP+XML 请求 Exchange Web Services 2007/2010 的相关文章

  • 模拟器中 Google Wear 上的语音识别器没有语音输入

    我试图使用 Google Wear 网站上的自由形式语音输入 在 hello world 示例中 我刚刚添加了对 textView 的单击 它确实从语音意图中调出 立即发言 活动 但模拟器无法检测到我的麦克风发出的任何声音 我使用的是 Ma
  • Android TelecomManager 中的 addIncomingCall 没有执行任何操作

    我正在尝试使用本机 Android 来电 UI 我有一个连接服务 并且我已经成功注册了一个电话帐户 但在我调用方法 addNewIncomingCall 后什么也没有发生 对我所缺少的有什么想法吗 显现
  • 用于 Kotlin 中单元测试的 BuildConfigField 模拟

    我正在尝试尽可能多地涵盖Kotlin Android 库我遇到了有关自定义 BuildConfig 变量的问题 更广为人知的是buildConfigField 我想模拟这个变量来测试两者true and false values 从 Gra
  • 如何制作像 Google+ 应用程序中那样的气泡? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 有谁知道如何使用 Google An
  • 使用 proguard 混淆文件名

    我正在使用 proguard 和 Android Studio 混淆我的 apk 当我反编译我的apk时 我可以看到很多文件 例如aaa java aab java ETC 但我项目中的所有文件都有原始名称 有没有办法混淆我的项目的文件名
  • VOIP通话录音

    我正在开发一个在 android 中录制 VOIP 通话的项目 我没有找到任何解决方案 有很多应用程序支持手机上的 VOIP 录音 我找不到任何教程和帮助 立方体通话记录器 https play google com store apps
  • 如何使用 RecyclerView 创建此布局?

    我正在尝试使用这种类型的布局创建回收器视图 这些项目是字符串 可以以不同的大小出现 我不知道每行中有多少项目 我可以使用 StaggeredGridLayoutManager 来做到这一点吗 该图像只是一个假示例 每行可以有更多项目 您可能
  • 使用 DataBinding 测试片段时膨胀类 Fragment 时出错

    有人可以帮我解决这个问题吗 在我的测试中 我想检查登录按钮是否显示在起始页上 今天我已经为这个错误苦苦挣扎了一段时间 我不知道应该如何解决它 我在这里错过了什么 也许这个问题与这个问题有些相似 Espresso 测试失败 并显示 java
  • 什么是 Android 测试协调器?

    谷歌最近发布了Android测试支持库1 0 读完后overview https android developers googleblog com 2017 07 android testing support library 10 is
  • 如何在 60 分钟后删除共享首选项

    我想存储登录数据 但希望在 60 分钟后删除该数据 执行此操作的正确方法是什么 在这 60 分钟内可以关闭 停止 打开应用程序 我不想使用内部数据库 这是我的访问代码SharedPreferences sharedpreferences g
  • 我在 android studio 中使用 kotlin 时出现错误

    为什么会出现这个错误 09 12 16 36 31 502 1886 1886 com getloction nourmedhat smartgate getlocation E AndroidRuntime 致命异常 main 进程 co
  • 使用 Proguard 通过 Dropbox.com 库混淆 Android 应用程序

    我刚刚创建了一个需要 Dropbox com API 库的 Android 应用程序 我现在尝试在 发布 模式下构建应用程序 并希望在代码上运行混淆器以对其进行混淆 但是 每当我尝试运行 Proguard 时 都会收到以下错误 Progua
  • 活动加载缓慢

    我的应用程序中有大约 50 个活动 但其中一个活动非常慢 我的意思是当我按下按钮进入该活动时 需要很长时间 有时会出现黑屏 在该活动中 我有一个按钮 如果我单击该按钮 则需要很长时间才能执行 代码很轻 只有一个Button EditText
  • Expresso 的 Android 测试首选项片段

    我在通过 Expresso 测试我的代码时遇到问题 我写了这段代码 public class SettingsActivity extends Activity Override protected void onCreate Bundle
  • TextView.setMaxLines 不起作用?

    在我的应用程序中 我有一个屏幕 其中显示一些文本 然后显示一张照片 文本的长度是可变的 有时根本没有 有时很多 所以我想对其进行设置 以便文本永远不会占用超过几行 但可以滚动 为下面的图像留下足够的空间 我这部分的视图组件是以编程方式创建的
  • Android计算两个日期之间的天数

    我编写了以下代码来查找两个日期之间的天数 startDateValue new Date startDate endDateValue new Date endDate long diff endDateValue getTime star
  • 用于请求带有临时缓存的远程 Observable 的 RxJava 模式

    用例是这样的 我想暂时缓存最新发出的昂贵的Observable响应 但在它过期后 返回到昂贵的源Observable并再次缓存它 等等 一个非常基本的网络缓存场景 但我真的很难让它工作 private Observable
  • 动态更改按钮上的图像视图

    在我的应用程序中 我有按钮和ImageView 当我按下按钮时我想改变ImageView 我的可绘制文件夹中有 5 张图像 按下按钮时 ImageView 根据按钮单击一张一张地更改图像 我想要它的解决方案 感谢任何可以提供帮助的人 维护一
  • 如何从DataSource.Factory获取数据

    我必须调用此方法才能获取所有人员 我根本无法修改这个方法 Query SELECT FROM PERSON TABLE ORDER BY NAME DESC abstract fun getElements DataSource Facto
  • 如何用LoaderManager自动重新查询

    我有一个应用程序显示来自 SQLite DB 的数据 并且数据不断变化 所以显然 我认为我应该使用 LoaderManager 来显示数据 我读过一些关于将 LoaderManager 与 SQLite 结合使用的内容 然后看到了亚历克斯

随机推荐