[英]Android: “400 bad request” error when trying to tweet with media using Fabric and Twitter REST API
我正在尝试构建一个应用程序,用户可以在其中发布图像并附加图像。 我正在使用Fabric进行Twitter集成,并在推文中尝试扩展API客户端,以制作Statuses Service更新方法的改进版本。 我不想使用Tweet Composer进行图像推文,因为我想避免使用plus UI调用,并且我也希望能够在推文中包含位置。
这是我的自定义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);
}
这是我尝试鸣叫的代码的一部分(到目前为止,我为媒体实体使用了静态值-我使用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();
}
}
});
创建签名的功能:
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);
}
当我运行该应用程序并尝试进行鸣叫时,出现以下错误消息: 400 Bad Request
问题是什么? 我应该怎么做? 我是Fabric,Twitter REST API和Retrofit的新手,所以我将感谢经验丰富的成员的建议:)预先感谢!
编辑:
我试图记录发送到服务器的请求和得到的响应,现在我在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)
众所周知,错误的请求错误可能表示格式错误的请求(例如JSON问题),但是,根据Twitter REST API文档和其他用户的示例,我的请求应该没问题。 我还尝试发送一条没有任何媒体ID的推文(至于其他字段,我完全遵循了Fabric Statuses Service的update方法中提供的格式,应该可以使用),在这种情况下,我也遇到了同样的错误。 现在我完全迷路了。 有人可以帮我吗?
编辑:
现在,我不再使用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());
}
});
现在,我可以不带图像(媒体ID)进行发布,但是当我尝试使用媒体ID进行发布时,出现以下错误: The validation of media ids failed.
我可以使用twurl成功发布相同的tweet,所以我认为问题不在于图像。 我使用twurl手动上传图像,并使用它返回的ID。 我总是在尝试发布之前上载新图像,因此问题不在于重复的ID。 现在我显然不知道实际出了什么问题。 有人能帮我吗?
好的,原来是我的一个愚蠢的错误。 当我用twurl发布图像时,我是使用与我在应用程序中使用的帐户不同的Twitter帐户进行操作的。 为了在推文中使用,上载的媒体必须来自同一用户或包括其他用户作为其他所有者(具有Additional_owners参数),这一点很重要。 在twurl中切换帐户后,一切正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.