Connect to Azure DocumentDB from Android

前端 未结 1 738
说谎
说谎 2021-02-04 20:43

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

相关标签:
1条回答
  • 2021-02-04 21:21

    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.

    0 讨论(0)
提交回复
热议问题