Media/upload retrofit authorization


#1

Hello, I am using new fabric twitter kit and really like it so far, but I’ve found it lacking of image upload functionality so I decided to call api from retrofit. Problem is I got 400 error so I suspect I am doing something more with authorization. Could someone point me out what is wrong with my code? (sorry for quality)

        final File photo = new File("<path here>");
    TypedFile typedFile = new TypedFile("image/*", photo);

    final TwitterSession session = Twitter.getSessionManager().getActiveSession();
    if (session != null) {

        final TwitterAuthToken authToken = session.getAuthToken();

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("https://upload.twitter.com")
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setRequestInterceptor(new RequestInterceptor() {
                    @Override
                    public void intercept(RequestFacade request) {
                        byte[] b = new byte[32];
                        new Random().nextBytes(b);
                        String randomBytes = null;
                        try {
                            randomBytes = URLEncoder.encode(String.valueOf(b), "UTF-8");
                        } catch (UnsupportedEncodingException e) {
                            Log.e(TAG, e.getMessage());
                        }
                       
                        long currentTimeMillis = System.currentTimeMillis();
                        String token = session.getAuthToken().token;
                        String signature = String.format("oauth_consumer_key=%s&oauth_nonce=%s&oauth_signature_method=HMAC-SHA1&oauth_timestamp=%s&oauth_token=%s&oauth_version=1.0", MainApplication.TWITTER_KEY, randomBytes, currentTimeMillis, token);
                        String finalSignature = null;
                        try {
                            finalSignature = sha1(signature, MainApplication.TWITTER_SECRET + "&" + authToken.secret);
                        } catch (UnsupportedEncodingException e) {
                            Log.e(TAG, e.getMessage());
                        } catch (NoSuchAlgorithmException e) {
                            Log.e(TAG, e.getMessage());
                        } catch (InvalidKeyException e) {
                            Log.e(TAG, e.getMessage());
                        }
                       
                        String header = String.format("OAuth oauth_consumer_key=\"%s\", oauth_nonce=\"%s\", oauth_signature=\"%s\", " +
                                "oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"%s\", oauth_token=\"%s\", oauth_version=\"1.0\")", MainApplication.TWITTER_KEY, randomBytes, finalSignature, currentTimeMillis, token);
                        request.addHeader("Authorization", header);
                    }
                })
                .build();

        CustomService service = restAdapter.create(CustomService.class);
        service.upload(typedFile, new Callback<TwitterMedia>() {
            @Override
            public void success(Result<TwitterMedia> twitterMediaResult) {
                Log.d(TAG, "uploaded file");
            }

            @Override
            public void failure(TwitterException e) {
                Log.d(TAG, "file upload failed" + e.getMessage());
            }
        });

   public static String sha1(String s, String keyString) throws
        UnsupportedEncodingException, NoSuchAlgorithmException,
        InvalidKeyException {

    SecretKeySpec key = new SecretKeySpec((keyString).getBytes("UTF-8"), "HmacSHA1");
    Mac mac = Mac.getInstance("HmacSHA1");
    mac.init(key);
    byte[] bytes = mac.doFinal(s.getBytes("UTF-8"));

    return Base64.encodeToString(bytes, Base64.URL_SAFE);
}


interface CustomService {
    @Multipart
    @POST("/1.1/media/upload.json")
    void upload(@Part("media") TypedFile file, Callback<TwitterMedia> cb);
}

static class MyTwitterApiClient extends TwitterApiClient {

    public MyTwitterApiClient(com.twitter.sdk.android.core.Session session) {
        super(session);
    }

    public CustomService getCustomService() {
        return getService(CustomService.class);
    }
}

thank you for the answers !

PS TwitterMedia is class mapped to request from media/load api:

https://dev.twitter.com/rest/public/uploading-media


#2

Maybe @lfcipriani can help here - he wrote the sample Android Cannonball app and that does image uploads. Take a look there for ideas?


#3

Hello for the answer @andypiper I checked @lfcipriani 's cannonball app but unfortunately it uses twitter post screen to post feeds and I want to do that in a background like I can do in twitter4j. Any points for this?

Thank you


#4

@charafau8 did you find a solution to this problem ?
I am looking for the same solution. :confused: