The question is published on by Tutorial Guruji team.
Has anyone experienced connecting to Azure’s documentdb from android? I have tried using the new Java SDK, however it doesn’t seem to be supported within android due to some old required Apache dependency conflicts in the core android SDK. I am trying the Rest API method, but it is slow going.
Thanks in advance for any help!
Answer
Okay, this was a nightmare to solve. Nine hours later… -_-‘. Long story short, here is some code that will actually work successfully. This code isn’t perfect, and is dependent on Retrofit
First, this is an example “Service” interface in Retrofit:
import retrofit.Callback; import retrofit.http.Body; import retrofit.http.Header; import retrofit.http.POST; public interface MyPojoService { @POST("/dbs/[db_id]/colls/[collection_id]/docs") void addDocument(@Header("authorization") String authorization, @Header("x-ms-date") String date, @Body MyPojo myPojo, Callback<MyPojo> cb); }
Next, we have our initial setup fields within the class that will call DocumentDB:
// Replace with your DocumentDB master key. private static final String MASTER_KEY = "[Insert Key Here]"; //Gson instance. private Gson gson = new Gson();
Now we’ll have our method that executes against the RESTful endpoint:
public void callDocumentDB() { SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); formatter.setTimeZone(TimeZone.getTimeZone("GMT")); String headerDate = formatter.format(new Date()).toLowerCase(); //According to the spec the format matters here. Make sure to use this format on the header dates. MyPojo myPojo = new MyPojo(); myPojo.id = UUID.randomUUID().toString(); //This is the only required field, and does not have to be a UUID. RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://[INSERT DB NAME HERE].documents.azure.com") .build(); MyPojoService service = restAdapter.create(MyPojoService.class); service.addDocument(generateAuthHeader("post", "docs", "[INSERT COLLECTION ID HERE]", headerDate, MASTER_KEY), headerDate, myPojo, new Callback<MyPojo>() { @Override public void success(MyPojo myPojo, Response response) { //[INSERT API SUCCESSFUL CALL LOGIC HERE] } @Override public void failure(RetrofitError error) { throw error; } }); }
Lastly we have the method that generates the authorization header. This method was a nightmare to put together, but it works properly to the spec:
private String generateAuthHeader(String verb, String resourceType, String resourceId, String date, String masterKeyBase64) throws Exception { //Decode the master key, and setup the MAC object for signing. byte[] masterKeyBytes = Base64.decode(masterKeyBase64, Base64.NO_WRAP); Mac mac = Mac.getInstance("HMACSHA256"); mac.init(new SecretKeySpec(masterKeyBytes, "HMACSHA256")); //Build the unsigned auth string. String stringToSign = verb + "n" + resourceType + "n" + resourceId + "n" + date + "n" + "n"; //Sign and encode the auth string. String signature = Base64.encodeToString(mac.doFinal(stringToSign.toLowerCase().getBytes("UTF8")), Base64.NO_WRAP); //Generate the auth header. String authHeader = URLEncoder.encode("type=master&ver=1.0&sig=" + signature, "UTF8"); return authHeader; }
NOTE: Please be aware that generateAuthString and MyPojoService are setup to use the x-ms-date header instead of the date header. There is a bug with the current version of Azure’s DocumentDB that seems to be keeping the generated token from authorizing correctly.
I hope this helps, and saves you some time.