Android: загрузка изображения в Twitter с использованием REST API и Fabric, ошибка сломанной трубы
Я пытаюсь создать приложение, в котором пользователь может сделать снимок и загрузить его на сервер Twitter (через конечную точку мультимедиа / загрузки), чтобы прикрепить этот мультимедийный объект к сообщению (также отправленному из приложения). Я использую Fabric для доступа к Twitter REST API. Моя проблема в том, что всякий раз, когда я пытаюсь загрузить изображение, я получаю сообщение об ошибке сломанной трубы.
Вот некоторые части моего кода:
Мой пользовательский сервис для загрузки изображения:
public interface UploadMediaService {
@Multipart
@POST("/1.1/media/upload.json")
void upload(@Part("media") TypedFile file, @Part("additional_owners") String owners, com.twitter.sdk.android.core.Callback<JSONObject> cb);
}
Загрузка файла изображения:
File photo = new File(mCurrentPhotoPath);
TypedFile typedFile = new TypedFile("application/octet-stream", photo);
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://upload.twitter.com")
.setLogLevel(RestAdapter.LogLevel.FULL)
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("Authorization", createSignature(session));
}
})
.build();
UploadMediaService service = restAdapter.create(UploadMediaService.class);
service.upload(typedFile, null, new Callback<JSONObject>() {
@Override
public void success(Result<JSONObject> twitterMediaResult) {
try {
Log.v("success", twitterMediaResult.data.getString("media_id_string"));
MyTwitterApiClient myclient = new MyTwitterApiClient(Twitter.getSessionManager().getActiveSession());
StatusWithMediaService mediaService = myclient.getStatusWithMediaService();
mediaService.update("@xxxxx " + eventtype + ": \n" + comment.getText().toString(), null, false, mypos.latitude, mypos.longitude, null, true, false, twitterMediaResult.data.getString("media_id_string"), 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());
}
});
} catch (Exception e) {
Log.e("testapp", e.getMessage());
}
}
@Override
public void failure(TwitterException e) {
Log.e("testapp", e.getMessage());
}
});
Создание подписи:
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);
}
Когда я запускаю приложение, я получаю следующие вещи в logcat:
Начало HTTP-запроса:
08-07 14:48:02.932 14395-15643/com.example.test.testapp D/Retrofit﹕ ---> HTTP POST https://upload.twitter.com/1.1/media/upload.json
08-07 14:48:02.932 14395-15643/com.example.test.testapp D/Retrofit﹕ Authorization: OAuth oauth_consumer_key="XXXXX", oauth_nonce="XXXXX", oauth_signature="XXXXX", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1438948082911", oauth_token="XXXXX", oauth_version="1.0")
08-07 14:48:02.932 14395-15643/com.example.test.testapp D/Retrofit﹕ Content-Type: multipart/form-data; boundary=2d963c0d-6f81-4b88-8718-7d4100b7f8e3
08-07 14:48:02.934 14395-15643/com.example.test.testapp D/Retrofit﹕ Content-Length: 1056730
08-07 14:48:03.086 14395-15643/com.example.test.testapp D/Retrofit﹕ --2d963c0d-6f81-4b88-8718-7d4100b7f8e3
Content-Disposition: form-data; name="media"; filename="JPEG_20150807_144749_1349351950.jpg"
Content-Type: application/octet-stream
Content-Length: 1056450
Content-Transfer-Encoding: binary
Сообщения об ошибках:
08-07 14:48:04.236 14395-15643/com.example.test.testapp D/Retrofit﹕ ---- ERROR https://upload.twitter.com/1.1/media/upload.json
08-07 14:48:04.252 14395-15643/com.example.test.testapp D/Retrofit﹕ javax.net.ssl.SSLException: Write error: ssl=0x9f822c00: I/O error during system call, Broken pipe
at com.android.org.conscrypt.NativeCrypto.SSL_write(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:765)
at com.android.okio.Okio$1.write(Okio.java:70)
at com.android.okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:116)
at com.android.okio.RealBufferedSink.write(RealBufferedSink.java:44)
at com.android.okhttp.internal.http.HttpConnection$FixedLengthSink.write(HttpConnection.java:291)
at com.android.okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:116)
at com.android.okio.RealBufferedSink$1.write(RealBufferedSink.java:131)
at java.io.OutputStream.write(OutputStream.java:82)
at retrofit.mime.TypedByteArray.writeTo(TypedByteArray.java:66)
at retrofit.client.UrlConnectionClient.prepareRequest(UrlConnectionClient.java:68)
at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:37)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:321)
at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at retrofit.Platform$Android$2$1.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:818)
08-07 14:48:04.252 14395-15643/com.example.test.testapp D/Retrofit﹕ ---- END ERROR
08-07 14:48:04.261 14395-14395/com.example.test.testapp E/fail﹕ Write error: ssl=0x9f822c00: I/O error during system call, Broken pipe
У кого-нибудь есть идеи, в чем может быть проблема и как ее обойти? Заранее благодарю за любую помощь:)