简体   繁体   English

Android:尝试使用Fabric和Twitter REST API推媒体时出现“ 400错误请求”错误

[英]Android: “400 bad request” error when trying to tweet with media using Fabric and Twitter REST API

I am trying to build an app where the user can post to Twitter with the possibility to attach images. 我正在尝试构建一个应用程序,用户可以在其中发布图像并附加图像。 I am using Fabric for Twitter integration and for the Tweeting I am trying to extend the API client to make an improved version of the Statuses Service's update method. 我正在使用Fabric进行Twitter集成,并在推文中尝试扩展API客户端,以制作Statuses Service更新方法的改进版本。 I don't want to use Tweet Composer for tweeting with images, as I want to avoid the plus UI call and I also want to be able to include location in the tweets. 我不想使用Tweet Composer进行图像推文,因为我想避免使用plus UI调用,并且我也希望能够在推文中包含位置。

Here is my custom Twitter API client class: 这是我的自定义Twitter API客户端类:

public class MyTwitterApiClient extends TwitterApiClient {

    public MyTwitterApiClient(TwitterSession session)
    {
        super(session);
    }

    public StatusWithMediaService getStatusWithMediaService() {
        return  getService(StatusWithMediaService.class);
    }


}

public interface StatusWithMediaService {
    @FormUrlEncoded
    @POST(value="/1.1/statuses/update.json")
    void update(@Field(value="status")
                java.lang.String status,
                @Field(value="in_reply_to_status_id")
                java.lang.Long inReplyToStatusId,
                @Field(value="possibly_sensitive")
                java.lang.Boolean possiblySensitive,
                @Field(value="lat")
                java.lang.Double latitude,
                @Field(value="long")
                java.lang.Double longitude,
                @Field(value="place_id")
                java.lang.String placeId,
                @Field(value="display_cooridnates")
                java.lang.Boolean displayCoordinates,
                @Field(value="trim_user")
                java.lang.Boolean trimUser,
                @Field(value ="media_ids")
                String mediaIds,
                com.twitter.sdk.android.core.Callback<Tweet> cb);
}

And here is the part of my code where I am trying to tweet (as for now I am using a static value for the media entity - the ID of a picture I uploaded using twurl): 这是我尝试鸣叫的代码的一部分(到目前为止,我为媒体实体使用了静态值-我使用twurl上传的图片的ID):

submit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (eventtype != null && mypos != null) {

                    final TwitterSession session = Twitter.getSessionManager().getActiveSession();

                    RestAdapter restAdapter = new RestAdapter.Builder()
                        .setEndpoint("https://api.twitter.com")
                        .setLogLevel(RestAdapter.LogLevel.FULL).setLog(new AndroidLog("testapp retrofit"))
                        .setRequestInterceptor(new RequestInterceptor() {
                    @Override
                    public void intercept(RequestFacade request) {

                        request.addHeader("Authorization", createSignature(session));

                    }
                })
                .build();

                StatusWithMediaService mediaService = restAdapter.create(StatusWithMediaService.class);

                    mediaService.update("@xxxx " + eventtype + ": \n" + comment.getText().toString(), null, false, mypos.latitude, mypos.longitude, null, true, false, "628524774898180096", new Callback<Tweet>() {
                        @Override
                        public void success(Result<Tweet> tweetResult) {
                            Toast.makeText(getActivity(), "Raportin lähettäminen onnistui.", Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void failure(TwitterException e) {
                            Log.e("testapp", e.getMessage());
                        }
                    });
                }
                else
                {
                    Toast.makeText(getActivity(), "Puuttuvat tiedot: sijainti", Toast.LENGTH_SHORT).show();
                }
            }
        });

The function for creating the signature: 创建签名的功能:

public String createSignature(TwitterSession session)
    {
        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("encoding error", e.getMessage());
        }

        long currentTimeInMillis = System.currentTimeMillis();
        TwitterAuthToken authToken = session.getAuthToken();
        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", MainActivity.TWITTER_KEY, randomBytes, currentTimeInMillis, token);
        String finalSignature = null;
        try
        {
            finalSignature = sha1(signature, MainActivity.TWITTER_SECRET + "&" +authToken.secret);
        }
        catch (UnsupportedEncodingException e)
        {
            Log.e("encoding error", e.getMessage());
        }
        catch (NoSuchAlgorithmException e)
        {
            Log.e("algorithm error", e.getMessage());
        }
        catch (InvalidKeyException e)
        {
            Log.e("key error", 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\")", MainActivity.TWITTER_KEY, randomBytes, finalSignature, currentTimeInMillis, token);

        return header;
    }

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

When I run the app and I try to tweet, I get the following error message: 400 Bad Request 当我运行该应用程序并尝试进行鸣叫时,出现以下错误消息: 400 Bad Request

What is the problem? 问题是什么? What should I do differently? 我应该怎么做? I am quite new to Fabric, Twitter REST API and Retrofit, so I would appreciate advice from more experienced members :) Thanks in advance! 我是Fabric,Twitter REST API和Retrofit的新手,所以我将感谢经验丰富的成员的建议:)预先感谢!

EDIT: 编辑:

I tried to log the request sent to the server and the response I get, and now I get this in logcat: 我试图记录发送到服务器的请求和得到的响应,现在我在logcat中得到了:

08-05 10:46:54.364  20026-20561/com.example.test.testapp D/testapp retrofit﹕ ---HTTP POST https://api.twitter.com/1.1/statuses/update.json
08-05 10:46:54.364  20026-20561/com.example.test.testapp D/testapp retrofit﹕ Authorization: OAuth oauth_consumer_key="XXXXX", oauth_nonce="XXXXX", oauth_signature="XXXXX", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1438760814359", oauth_token="XXXXX", oauth_version="1.0")
08-05 10:46:54.364  20026-20561/com.example.test.testapp D/testapp retrofit﹕ Content-Type: application/x-www-form-urlencoded; charset=UTF-8
08-05 10:46:54.364  20026-20561/com.example.test.testapp D/testapp retrofit﹕ Content-Length: 164
08-05 10:46:54.366  20026-20561/com.example.test.testapp D/testapp retrofit﹕ status=%40tkl_testi+Onnettomuus%3A+%0A&possibly_sensitive=false&lat=61.4892668&long=23.7791515&display_cooridnates=true&trim_user=false&media_ids=628825606512316416
08-05 10:46:54.366  20026-20561/com.example.test.testapp D/testapp retrofit﹕ ---> END HTTP (164-byte body)
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ <--- HTTP 400 https://api.twitter.com/1.1/statuses/update.json (803ms)
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ : HTTP/1.0 400 Bad Request
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ content-length: 0
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ date: Wed, 05 Aug 2015 07:46:55 GMT
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ server: tsa_b
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ X-Android-Received-Millis: 1438760815133
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ X-Android-Response-Source: NETWORK 400
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ X-Android-Sent-Millis: 1438760814969
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ x-connection-hash: fb74c0c2ee1c7830163453a33dd099de
08-05 10:46:55.170  20026-20561/com.example.test.testapp D/testapp retrofit﹕ <--- END HTTP (0-byte body)

As we know, the bad request error could refer to malformed request (so eg problems with the JSON), however, according to the Twitter REST API documentation and other users' examples my request should be fine. 众所周知,错误的请求错误可能表示格式错误的请求(例如JSON问题),但是,根据Twitter REST API文档和其他用户的示例,我的请求应该没问题。 I also tried sending a tweet without any media ID (as for those other fields I completely followed the format provided in Fabric Statuses Service's update method, it should have worked) and I got the same error in that case too. 我还尝试发送一条没有任何媒体ID的推文(至于其他字段,我完全遵循了Fabric Statuses Service的update方法中提供的格式,应该可以使用),在这种情况下,我也遇到了同样的错误。 Now I am completely lost. 现在我完全迷路了。 Could someone help me, please? 有人可以帮我吗?

EDIT: 编辑:

Instead of using the Retrofit REST adapter, now I call my custom update method through my custom Twitter API client, so the update part of the code now looks like this: 现在,我不再使用Retrofit REST适配器,而是通过自定义Twitter API客户端调用自定义更新方法,因此代码的更新部分现在如下所示:

MyTwitterApiClient myclient = new MyTwitterApiClient(Twitter.getSessionManager().getActiveSession());

                    StatusWithMediaService mediaService = myclient.getStatusWithMediaService();
                    mediaService.update("@xxxx " + eventtype + ": \n" + comment.getText().toString(), null, false, mypos.latitude, mypos.longitude, null, true, false, "629232743633842180", new Callback<Tweet>() {
                        @Override
                        public void success(Result<Tweet> tweetResult) {
                            Toast.makeText(getActivity(), "Raportin lähettäminen onnistui.", Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void failure(TwitterException e) {
                            TwitterApiException apiException = (TwitterApiException) e;
                            Log.e("testapp", apiException.getErrorMessage());
                            Log.e("testapp", apiException.getMessage());
                        }
                    });

With this I can now post without images (media IDs), but when I try to post with a media ID, I get the following error: The validation of media ids failed. 现在,我可以不带图像(媒​​体ID)进行发布,但是当我尝试使用媒体ID进行发布时,出现以下错误: The validation of media ids failed.

I can successfully post the same tweet using twurl, so I don't think that the problem is with the image. 我可以使用twurl成功发布相同的tweet,所以我认为问题不在于图像。 I upload the images manually using twurl and I use the ID returned by it. 我使用twurl手动上传图像,并使用它返回的ID。 I always upload a new image before attempting to post, so the problem is not with duplicate IDs. 我总是在尝试发布之前上载新图像,因此问题不在于重复的ID。 Now I clearly have no idea what is actually going wrong. 现在我显然不知道实际出了什么问题。 Can someone help me? 有人能帮我吗?

OK, so it turned out it was due to a stupid mistake from my part. 好的,原来是我的一个愚蠢的错误。 When I posted the image with twurl, I did it under a different Twitter account from the one I was using in the app. 当我用twurl发布图像时,我是使用与我在应用程序中使用的帐户不同的Twitter帐户进行操作的。 It is important that the uploaded media has to either come from the same user or include the other user as additional owner (with the additional_owners parameter) in order to be used in a tweet. 为了在推文中使用,上载的媒体必须来自同一用户或包括其他用户作为其他所有者(具有Additional_owners参数),这一点很重要。 After I switched accounts in twurl, everything worked fine. 在twurl中切换帐户后,一切正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android Rest Api Post 400错误请求 - Android Rest Api Post 400 bad request 使用放心 put 方法测试 api 时出现错误请求 400 和反序列化错误 - Bad Request 400 and deserialization error while testing api using rest assured put method 使用 okHttp 4.* 将 json 数据发布到 rest api 时,响应代码为 400 的错误请求 - Bad request with response code 400, when posting json data to rest api using okHttp 4.* 使用java客户端通过rest api上传文件时出现400错误请求 - 400 bad request when using java client to upload file through rest api 呼叫驱动器Rest API:400错误请求 - Call drive Rest API: 400 bad request Android上的Google翻译API给出错误“ GoogleJsonResponseException:400错误的请求” - Google translate api on android gives error 'GoogleJsonResponseException: 400 Bad Request' 使用 RestTemplate.postForObject 调用 API 时出现 400 Bad Request - 400 Bad Request when using RestTemplate.postForObject to call API 使用 HttpURLConnection 的 Android 分段文件上传 - 400 错误请求错误 - Android Multipart File Upload using HttpURLConnection - 400 Bad Request Error Parse.com REST API错误代码400:从Java HTTP请求到云功能的错误请求 - Parse.com REST API Error Code 400: Bad Request from Java HTTP Request to Cloud Function Android Drive Api收到400错误请求 - Android Drive Api getting 400 Bad Request
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM