将图像上传到Android的tumblr API

假设使用Tumblr API来上传图片很容易。 事实并非如此。 ( 编辑现在,请参阅本条目结尾的编辑2

我的应用程序应该将图像上传到tumblr 。 我宁愿从一个服务做到这一点,但现在我使用一个活动,一旦完成上传就自动closures。 在OnCreate()用户进行身份validation:

 consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET); // It uses this signature by default // consumer.setMessageSigner(new HmacSha1MessageSigner()); provider = new CommonsHttpOAuthProvider(REQUEST_TOKEN_URL,ACCESS_TOKEN_URL,AUTH_URL); String authUrl; try { authUrl = provider.retrieveRequestToken(consumer, CALLBACK_URL); Log.d(TAG, "Auth url:" + authUrl); startActivity(new Intent("android.intent.action.VIEW", Uri.parse(authUrl))); } 

这将打开一个浏览器活动,用户可以添加用户名和密码,然后应用程序返回到活动(这也是为什么我必须使用一个活动,我不知道如何从一个服务做到这一点)

从浏览器返回数据被提取:

 Uri uri = context.getIntent().getData(); if (uri != null && uri.toString().startsWith(CALLBACK_URL)) { Log.d(TAG, "uri!=null"); String verifier = uri.getQueryParameter("oauth_verifier"); Log.d(TAG, "verifier"+verifier); try { provider.setOAuth10a(true); provider.retrieveAccessToken(consumer, verifier); Log.d(TAG, "try"); } catch (Exception e) { Log.e(TAG, e.toString()); e.printStackTrace(); } OAUTH_TOKEN = consumer.getToken(); OAUTH_SECRET = consumer.getTokenSecret(); 

这两个片段中的大部分都来自这里 ,他们工作得很好。

有了这些令牌,我现在可以尝试把数据放在tumblr上。 当我尝试添加文本时,使用此方法可以正常工作:

 private void createText() { if(!OAUTH_TOKEN.equals("")) { HttpContext context = new BasicHttpContext(); HttpPost request = new HttpPost("http://api.tumblr.com/v2/blog/" + blogname + ".tumblr.com/post"); List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); nameValuePairs.add(new BasicNameValuePair("type", "text")); nameValuePairs.add(new BasicNameValuePair("body", "this is just a test")); try { request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); } catch (UnsupportedEncodingException e1) { Log.e(TAG, e1.toString()); e1.printStackTrace(); } if (consumer == null) { consumer = new CommonsHttpOAuthConsumer(OAuthConstants.TUMBR_CONSUMERKEY, OAuthConstants.TUMBR_SECRETKEY); } if (OAUTH_TOKEN == null || OAUTH_SECRET == null) { Log.e(TAG, "Not logged in error"); } consumer.setTokenWithSecret(OAUTH_TOKEN, OAUTH_SECRET); try { consumer.sign(request); } catch (OAuthMessageSignerException e) { } catch (OAuthExpectationFailedException e) { } catch (OAuthCommunicationException e) { } HttpClient client = new DefaultHttpClient(); //finally execute this request try { HttpResponse response = client.execute(request, context); HttpEntity responseEntity = response.getEntity(); if (responseEntity != null) { Log.d(TAG, "responseEntety!=null"); try { Log.d(TAG, EntityUtils.toString(responseEntity)); } catch (ParseException e) { e.printStackTrace(); Log.e(TAG, e.toString()); } catch (IOException e) { e.printStackTrace(); Log.e(TAG, e.toString()); } // gives me {"meta":{"status":401,"msg":"Not Authorized"},"response":[]} when I try to upload a photo } else { Log.d(TAG, "responseEntety==null"); } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } PostToTumblr.this.finish(); } 

正如你可以在这里看到http://www.tumblr.com/blog/snapnowandroid (至less现在这个时候)文本“这只是一个testing”被张贴。

但是,当我尝试发布图片时,会变得很奇怪。 现在我已经检查了一下,显然这是一个众所周知的tumblr API问题,在这里已经过分讨论了 ,有些已经用其他编程语言(例如这里 )解决了,但是我一直无法重复这些成功。

该方法(在下文中)具有与上述方法(工作)完全相同的结构,nameValuePairs只是不同的

该方法被赋予一个名为photo的Bitmapvariables:

  private void uploadToTumblr(Bitmap photo) 

这个位图被转换成一个数组:

 ByteArrayOutputStream stream = new ByteArrayOutputStream(); photo.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] bytes = stream.toByteArray(); 

nameValuePairs填充如下:

 nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("type", enc), URLEncoder.encode("photo", enc))); nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("caption", enc), URLEncoder.encode(text, enc))); nameValuePairs.add(new BasicNameValuePair("data", Base64.encodeToString(bytes, Base64.URL_SAFE))); 

其结果是tumblr api上的{"meta":{"status":400,"msg":"Bad Request"},"response":{"errors":["Error uploading photo."]}}

我试图编码图片不同,如本文所述,但没有任何改变。

 //http://www.coderanch.com/t/526487/java/java/Java-Byte-Hex-String final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; char[] hexChars = new char[bytes.length * 3]; int v; for ( int j = 0; j < bytes.length; j++ ) { v = bytes[j] & 0xFF; hexChars[j * 3] = '%'; hexChars[j * 3 + 1] = hexArray[v >>> 4]; hexChars[j * 3 + 2] = hexArray[v & 0x0F]; } String s = new String(hexChars); s = URLEncoder.encode(s, enc); nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("data", enc), s)); 

这里整个方法(没有hex编码):

 private void uploadToTumblr(Bitmap photo) { if(!OAUTH_TOKEN.equals("")) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); photo.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] bytes = stream.toByteArray(); String text ="SNAP"; HttpContext context = new BasicHttpContext(); HttpPost request = new HttpPost("http://api.tumblr.com/v2/blog/" + blogname + ".tumblr.com/post"); List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); String enc = "UTF-8"; try { nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("type", enc), URLEncoder.encode("photo", enc))); nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("caption", enc), URLEncoder.encode(text, enc))); nameValuePairs.add(new BasicNameValuePair("data", Base64.encodeToString(bytes, Base64.URL_SAFE))); } catch (UnsupportedEncodingException e2) { Log.e(TAG, e2.toString()); e2.printStackTrace(); } try { request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); } catch (UnsupportedEncodingException e1) { Log.e(TAG, e1.toString()); e1.printStackTrace(); } if (consumer == null) { consumer = new CommonsHttpOAuthConsumer(OAuthConstants.TUMBR_CONSUMERKEY, OAuthConstants.TUMBR_SECRETKEY); } if (OAUTH_TOKEN == null || OAUTH_SECRET == null) { //throw new LoginErrorException(LoginErrorException.NOT_LOGGED_IN); Log.e(TAG, "Not logged in error"); } consumer.setTokenWithSecret(OAUTH_TOKEN, OAUTH_SECRET); try { consumer.sign(request); } catch (OAuthMessageSignerException e) { } catch (OAuthExpectationFailedException e) { } catch (OAuthCommunicationException e) { } HttpClient client = new DefaultHttpClient(); //finally execute this request try { HttpResponse response = client.execute(request, context); HttpEntity responseEntity = response.getEntity(); if (responseEntity != null) { Log.d(TAG, "responseEntety!=null"); try { Log.d(TAG, EntityUtils.toString(responseEntity)); } catch (ParseException e) { e.printStackTrace(); Log.e(TAG, e.toString()); } catch (IOException e) { e.printStackTrace(); Log.e(TAG, e.toString()); } } else { Log.d(TAG, "responseEntety==null"); } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { Log.d(TAG, "upload imposble... Toklen not set"); } PostToTumblr.this.finish(); } 

现在,虽然有几件事我不高兴(例如,这是使用一个活动,而不是一个服务),这里的大问题显然是上传图像的问题。 我不是第一个有这个问题,所以有人能够在Java中完成这个?

编辑1

对于手头的问题还没有取得任何进展,但是对于有同样问题的人来说,创造了一种解决方法。 Tumblr提供通过邮件发送 ,你可以编程安卓android在后台发送电子邮件,如下所示 。 这工作得很好,但你需要要求用户提供他们的邮件帐户数据和Tumblr邮件地址发布。

编辑2

多年来,使用电子邮件已经不再是简单的方法。 随着jumblr终于有一个好的Java API将在Android上工作。 OAuthauthentication是没有趣味(它永远不会),但一旦你通过这个,它的梦幻般的。

现在,从技术上讲,如何做authentication的问题不属于这里,但这是我的一个长期的问题,所以我只是在这里粘贴一些代码,如果没有意思,你就跳过它。

这使用了一个名为jumblr-0.0.10-jar-with-dependencies.jar的jar

 import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.util.Log; import com.tumblr.jumblr.JumblrClient; import com.tumblr.jumblr.request.RequestBuilder; import com.tumblr.jumblr.types.Blog; import com.tumblr.jumblr.types.User; import org.scribe.builder.ServiceBuilder; import org.scribe.builder.api.TumblrApi; import org.scribe.model.Token; import org.scribe.model.Verifier; import org.scribe.oauth.OAuthService; import java.io.File; public class Tumblr { private static final String PROTECTED_RESOURCE_URL = "http://api.tumblr.com/v2/user/info"; static OAuthService service; static Token requestToken=null; public static void share(final Activity ctx, File file) { Thread tt = new Thread(new Runnable() { @Override public void run() { JumblrClient client = new JumblrClient(Tumblr_Constants.CONSUMER_KEY, Tumblr_Constants.CONSUMER_SECRET); RequestBuilder requestBuilder = client.getRequestBuilder(); requestBuilder.setConsumer(Tumblr_Constants.CONSUMER_KEY, Tumblr_Constants.CONSUMER_SECRET); SharedPreferences settings = ctx.getSharedPreferences("TumblrData", 0); String oauthToken=settings.getString("OauthToken", ""); String oauthTokenSecret=settings.getString("OauthSecret", ""); if(oauthToken.equals("") || oauthTokenSecret.equals("")) { authenticate(ctx); while(WebViewFragment.verifier.equals("")) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } String v = WebViewFragment.verifier; Token accessToken = authenticatefurther(v); SharedPreferences.Editor edit = settings.edit(); edit.putString("OauthToken", accessToken.getToken()); edit.putString("OauthSecret", accessToken.getSecret()); edit.commit(); oauthToken=settings.getString("OauthToken", ""); oauthTokenSecret=settings.getString("OauthSecret", ""); } if(!oauthToken.equals("") && !oauthTokenSecret.equals("")) { client.setToken(oauthToken, oauthTokenSecret); User user = client.user(); System.out.println(user.getName()); for (Blog blog : user.getBlogs()) { Log.d("TUMBLR", blog.getTitle()); } } } }); tt.start(); } private static void authenticate(Context ctx) { service = new ServiceBuilder() .provider( TumblrApi.class ) .apiKey(Tumblr_Constants.CONSUMER_KEY) .apiSecret(Tumblr_Constants.CONSUMER_SECRET) .callback("snapnao://snapnao.de/ok") // OOB forbidden. We need an url and the better is on the tumblr website ! .build(); Log.d("TUMBLR", "=== Tumblr's OAuth Workflow ===" ); System.out.println(); // Obtain the Request Token Log.d("TUMBLR", "Fetching the Request Token..."); requestToken = service.getRequestToken(); Log.d("TUMBLR", "Got the Request Token!"); Log.d("TUMBLR", ""); Log.d("TUMBLR", "Now go and authorize Scribe here:" ); Log.d("TUMBLR", service.getAuthorizationUrl( requestToken ) ); String url = service.getAuthorizationUrl(requestToken); Intent i = new Intent(ctx, WebViewFragment.class); i.putExtra("url", url); ctx.startActivity(i); } private static Token authenticatefurther(String v) { Token accessToken = null; Log.d("TUMBLR", "And paste the verifier here"); Log.d("TUMBLR", ">>"); Verifier verifier = new Verifier( v); Log.d("TUMBLR", ""); // Trade the Request Token and Verfier for the Access Token Log.d("TUMBLR", "Trading the Request Token for an Access Token..."); accessToken = service.getAccessToken( requestToken , verifier ); Log.d("TUMBLR", "Got the Access Token!"); Log.d("TUMBLR", "(if your curious it looks like this: " + accessToken + " )"); Log.d("TUMBLR", ""); return accessToken; } } 

WebViewFragement看起来像这样:

 import android.app.Activity; import android.graphics.Bitmap; import android.net.http.SslError; import android.os.Bundle; import android.util.Log; import android.webkit.SslErrorHandler; import android.webkit.WebView; import android.webkit.WebViewClient; public class WebViewFragment extends Activity { public static String verifier=""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.webviewfragment); String url = getIntent().getStringExtra("url"); Log.d("TUMBLR", "webview-> "+url); WebView view = (WebView) findViewById(R.id.webView); view.setWebViewClient( new SSLTolerentWebViewClient() ); view.getSettings().setJavaScriptEnabled(true); view.loadUrl(url); } // SSL Error Tolerant Web View Client private class SSLTolerentWebViewClient extends WebViewClient { @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); // Ignore SSL certificate errors } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); Log.d("TUMBLR", "+++++"+url); if(url.contains("oauth_verifier=")) { String[] x = url.split("oauth_verifier="); verifier=x[1].replace("#_=_", ""); WebViewFragment.this.finish(); } } } } 

Solutions Collecting From Web of "将图像上传到Android的tumblr API"

你为什么不使用Jumblr是Tumblr的官方Java客户端。

问候。

你可以使用jumblr – Tumblr java客户端轻松地做到这一点

 JumblrClient client = new JumblrClient(Constant.CONSUMER_KEY,Constant.CONSUMER_SECRET); client.setToken(preferences.getString("token",null), preferences.getString("token_secret", null)); PhotoPost pp = client.newPost(client.user().getBlogs().get(0).getName(),PhotoPost.class); pp.setCaption(caption); // pp.setLinkUrl(link); // pp.setSource(mImage); // String URL pp.setPhoto(new Photo(imgFile)); pp.save(); 

这对我工作…

 nameValuePairs.add(new BasicNameValuePair(URLEncoder .encode("type", "UTF-8"), URLEncoder.encode("photo", "UTF-8"))); Log.e("Tumblr", "Image shareing file path" + filePath); nameValuePairs.add(new BasicNameValuePair("caption", caption)); nameValuePairs.add(new BasicNameValuePair("source", filePath));` 

其中filePath是http url。

我有使用多部分公共类VideoUploader扩展AsyncTask {

  ProgressDialog progressDialog; @Override protected void onPreExecute() { // TODO Auto-generated method stub progressDialog = ProgressDialog.show(RecordingActivity.this, "", "Uploading video.. "); super.onPreExecute(); } @Override protected JSONObject doInBackground(String... params) { JSONObject jsonObject = null; StringBuilder builder = new StringBuilder(); try { String url = UrlConst.VIDEO_URL; HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(url); FileBody filebodyVideo = new FileBody(new File(params[0])); StringBody title = new StringBody("uploadedfile: " + params[0]); StringBody description = new StringBody( "This is a video of the agent"); // StringBody code = new StringBody(realtorCodeStr); MultipartEntity reqEntity = new MultipartEntity(); reqEntity.addPart("uploadedfile", filebodyVideo); reqEntity.addPart("title", title); reqEntity.addPart("description", description); // reqEntity.adddPart("code", code); httppost.setEntity(reqEntity); // DEBUG System.out.println("executing request " + httppost.getRequestLine()); HttpResponse response = httpclient.execute(httppost); HttpEntity resEntity = response.getEntity(); // DEBUG StatusLine status = response.getStatusLine(); int statusCode = status.getStatusCode(); System.out.println(response.getStatusLine()); if (resEntity != null) { System.out.println(EntityUtils.toString(resEntity)); } // end if if (resEntity != null) { resEntity.consumeContent(); } // end if if (statusCode == 200) { InputStream content = resEntity.getContent(); BufferedReader reader = new BufferedReader( new InputStreamReader(content)); String line; while ((line = reader.readLine()) != null) { builder.append(line); } jsonObject = new JSONObject(builder.toString()); return jsonObject; } else { Log.e(LoginActivity.class.toString(), "Failed to download file"); } httpclient.getConnectionManager().shutdown(); } catch (Exception e) { // TODO: handle exception } return null; } @Override protected void onPostExecute(JSONObject result) { // TODO Auto-generated method stub super.onPostExecute(result); progressDialog.dismiss(); if (result != null) { try { JSONObject jsonObject = result .getJSONObject(ParsingTagConst.COMMANDRESULT); String strSuccess = jsonObject .getString(ParsingTagConst.SUCCESS); String responseString = jsonObject .getString(ParsingTagConst.RESPONSE_STRING); Toast.makeText(RecordingActivity.this, "" + responseString, Toast.LENGTH_LONG).show(); if (strSuccess.equals("1")) { // get here your response } } catch (Exception e) { // TODO: handle exception } } } } enter code here 

我已经完成了使用下面的方法。 你可以试试这个。

// paramString =“文字你要放在标题”

 private void postPhotoTumblr(String uploadedImagePhotoUrl, String paramString) { CommonsHttpOAuthConsumer localCommonsHttpOAuthConsumer = getTumblrConsumer(); String str1 = "logged in username"; String encodedImage = uploadedImagePhotoUrl; DefaultHttpClient localDefaultHttpClient = new DefaultHttpClient(); HttpPost localHttpPost = new HttpPost("http://api.tumblr.com/v2/blog/" + str1 + ".tumblr.com/post"); try { ArrayList localArrayList = new ArrayList(); localArrayList.add(new BasicNameValuePair("type", "photo")); BasicNameValuePair localBasicNameValuePair = new BasicNameValuePair("caption", paramString); localArrayList.add(localBasicNameValuePair); localArrayList.add(new BasicNameValuePair("data",encodedImage)); UrlEncodedFormEntity localUrlEncodedFormEntity = new UrlEncodedFormEntity(localArrayList); localHttpPost.setEntity(localUrlEncodedFormEntity); localCommonsHttpOAuthConsumer.sign(localHttpPost); InputStream localInputStream = localDefaultHttpClient.execute(localHttpPost).getEntity().getContent(); InputStreamReader localInputStreamReader = new InputStreamReader(localInputStream); BufferedReader localBufferedReader = new BufferedReader(localInputStreamReader); StringBuilder localStringBuilder = new StringBuilder(); while (true) { String str2 = localBufferedReader.readLine(); if (str2 == null) { Log.i("DATA post resp", localStringBuilder.toString()); break; } localStringBuilder.append(str2); } } catch (ClientProtocolException localClientProtocolException) { localClientProtocolException.printStackTrace(); } catch (IOException localIOException) { localIOException.printStackTrace(); } catch (OAuthMessageSignerException localOAuthMessageSignerException) { localOAuthMessageSignerException.printStackTrace(); } catch (OAuthExpectationFailedException localOAuthExpectationFailedException) { localOAuthExpectationFailedException.printStackTrace(); } catch (OAuthCommunicationException localOAuthCommunicationException) { localOAuthCommunicationException.printStackTrace(); } } 

编辑:首先上传图片到Web服务器,然后获取Url并尝试使用上传的Url或文件path发布。 它会正常工作确定… 🙂