将 Azure 服务总线与 Android 连接

ste*_*tef 5 azure azure-java-sdk

我编写了一个简单的 java 程序(jdk 1.7),它列出了我所有的服务总线主题并将每个主题的名称打印到标准输出:

         try {

         String namespace = "myservicebus"; // from azure portal
         String issuer = "owner";  // from azure portal
         String key = "asdjklasdjklasdjklasdjklasdjk";  // from azure portal

         Configuration config = ServiceBusConfiguration.configureWithWrapAuthentication(
                namespace, 
                issuer,
                key, 
                ".servicebus.windows.net", 
                "-sb.accesscontrol.windows.net/WRAPv0.9"); 

        ServiceBusContract service = ServiceBusService.create(config);
        ListTopicsResult result = service.listTopics();
        List<TopicInfo> infoList = result.getItems();
        for(TopicInfo info : infoList){
            System.out.println( info.getPath());
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
Run Code Online (Sandbox Code Playgroud)

现在,我试图在一个简单的 android 项目(Android 4.2)中运行这个例子,但它不起作用。运行时总是抛出以下错误:

java.lang.RuntimeException: Service or property not registered:  com.microsoft.windowsazure.services.serviceBus.ServiceBusContract
Run Code Online (Sandbox Code Playgroud)

有没有人成功建立了从 android 设备(或模拟器)到 azure 服务总线的连接?

Microsoft Azure-Java-SDK 不支持 android 项目吗?

提前致谢

Car*_*ero 2

此错误是由于生成的 apk 不包含(删除)ServiceLoader 信息(在 META-INF/services 下)造成的。您可以测试自己从生成的 jar 中删除它,并看到出现相同的错误。在文档中据说现在支持它,但我发现使用它有问题。

http://developer.android.com/reference/java/util/ServiceLoader.html

您可以使用 ant 手动将数据包含在 apk 中

将“META-INF/services”文件保留在 apk 中

经过 10 个小时的调试、手动删除类(包括 META-INF/services 等)后,我发现 Azure SDK 使用了一些 Android 不支持的类(javax.ws.*),并且任何解决方法都适合我。

因此,我建议在 Android 环境中使用 REST API,请在下面找到我用于向该主题发送消息的源代码。

private static String generateSasToken(URI uri) {
    String targetUri;
    try {
        targetUri = URLEncoder
        .encode(uri.toString().toLowerCase(), "UTF-8")
        .toLowerCase();

        long expiresOnDate = System.currentTimeMillis();
        int expiresInMins = 20; // 1 hour
        expiresOnDate += expiresInMins * 60 * 1000;
        long expires = expiresOnDate / 1000;
        String toSign = targetUri + "\n" + expires;

        // Get an hmac_sha1 key from the raw key bytes
        byte[] keyBytes = sasKey.getBytes("UTF-8");
        SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA256");

        // Get an hmac_sha1 Mac instance and initialize with the signing key
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(signingKey);
        // Compute the hmac on input data bytes
        byte[] rawHmac = mac.doFinal(toSign.getBytes("UTF-8"));

        // using Apache commons codec for base64
//      String signature = URLEncoder.encode(
//      Base64.encodeBase64String(rawHmac), "UTF-8");
        String rawHmacStr = new String(Base64.encodeBase64(rawHmac, false),"UTF-8");
        String signature = URLEncoder.encode(rawHmacStr, "UTF-8");

        // construct authorization string
        String token = "SharedAccessSignature sr=" + targetUri + "&sig="
        + signature + "&se=" + expires + "&skn=" + sasKeyName;
        return token;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public static void Send(String topic, String subscription, String msgToSend) throws Exception {

        String url = uri+topic+"/messages";

        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(url);

        // Add header
        String token = generateSasToken(new URI(uri));
        post.setHeader("Authorization", token);
        post.setHeader("Content-Type", "text/plain");
        post.setHeader(subscription, subscription);
        StringEntity input = new StringEntity(msgToSend);
        post.setEntity(input);

        System.out.println("Llamando al post");
        HttpResponse response = client.execute(post);
        System.out.println("Response Code : " 
                + response.getStatusLine().getStatusCode());
        if (response.getStatusLine().getStatusCode() != 201)
            throw new Exception(response.getStatusLine().getReasonPhrase());

}
Run Code Online (Sandbox Code Playgroud)

更多信息请参阅 REST API Azure 信息。