2013-03-09 79 views
4

我写了一个简单的Java程序(JDK 1.7),列出了所有我的服务总线的主题,并打印出每个主题的名称到stdout:连接Azure的服务总线与Android

  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(); 
    } 

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

java.lang.RuntimeException: Service or property not registered: com.microsoft.windowsazure.services.serviceBus.ServiceBusContract 

有没有人成功地建立了从Android设备(或仿真器),以蔚蓝的服务总线的连接?

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

在此先感谢

+0

呃......你可能想在上面的代码示例中隐藏你的应用程序密钥! – 2013-03-11 07:02:09

+0

您是否在Linux/Mac/Windows机器上尝试过相同的示例代码?你确定这是一个Android兼容性问题吗? – 2013-03-11 17:38:33

+0

应用程序密钥被遮挡;-) – stef 2013-03-11 19:56:08

回答

2

此错误是由于生成的APK不包括(删除)的ServiceLoader信息(在META-INF /服务)的事实。您可以测试自己从生成的jar中删除它,并看到出现相同的错误。在文档中说它现在被支持,但我发现使用它的问题。

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

您可以使用Ant

Keep 'META-INF/services'-files in apk

10小时的调试后,手动删除类,包括META-INF /服务等包含人工apk中的数据,我发现, Azure SDK使用一些不受Android支持的类(javax.ws。*)以及任何对我有用的工具。

所以我建议在Android环境中使用REST API,找到下面我用来sebd消息的主题代码。

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()); 

} 

有关REST API Azure信息的更多信息。