将图像从 Android 上传到 tumblr API [英] Uploading Images to tumblr API from Android

查看:30
本文介绍了将图像从 Android 上传到 tumblr API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设使用 Tumblr API 上传图片很容易.不是.(编辑现在是,请参阅本条目末尾的编辑 2)

One assumed using the Tumblr API to upload images would be easy. It isn't. (EDIT It is now, see Edit 2 at the end of this entry)

我的应用程序应该将图像上传到 tumblr.我更喜欢从服务中执行此操作,但现在我使用的活动在上传完成后立即关闭.在 OnCreate() 中,用户已通过身份验证:

My app is supposed to upload an image to tumblr. I would prefer doing that from a service but for now I use an activity that closes itself as soon as its done uploading. In OnCreate() the user is authenticated:

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

} 

这会打开一个浏览器活动,用户可以在其中添加用户名和密码,然后应用返回活动(这也是我必须使用活动的原因,我不知道如何从服务中执行此操作)

This opens a browser activity where the user can add username and passoword and then the app returns to the activity (this is also why I have to use an activity, I don't know how to do this from a service)

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

Returning from the browser the data is extracted:

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

这两个片段中的大部分是我从这里获得的,它们运行良好.

Most of these two snippets I got from here and they work well.

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

With these tokens I can now try putting data on tumblr. When I try to add Text this works fine using this method:

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(至少截至目前)发布了这只是一个测试"的文字.

As you can see here http://www.tumblr.com/blog/snapnowandroid (at least as of this time) the text "this is just a test" is posted.

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

However, when I try to post images, it gets strange. Now I have checked around and apparently this is a well known issue with the tumblr API, which has excessively been discussed here and some have solved it in other programming languages (for example here) but I have been unable to repeat those successes.

该方法(以下全部内容)与上述方法(有效)具有完全相同的结构,只是 nameValuePairs 不同

The method (in its entirety below) has the exact same structure to the above method (that works), the nameValuePairs are just different

该方法被赋予一个名为 photo 的 Bitmap 变量:

The method is given a Bitmap variable called photo:

    private void uploadToTumblr(Bitmap photo)

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

This bitmap is converted into an array:

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

nameValuePairs 填写如下:

The nameValuePairs are filled as follows:

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

结果是一个 {"meta":{"status":400,"msg":"Bad Request"},"response":{"errors":["Error uploading photo."]}} 来自 tumblr api.

The result is a {"meta":{"status":400,"msg":"Bad Request"},"response":{"errors":["Error uploading photo."]}} from the tumblr api.

我尝试对图片进行不同的编码,如 这篇文章 但没有任何改动.

I have tries encoding the picture differently as discribed in this article but without any changes.

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

这里是整个方法(没有十六进制编码):

Here the entire method (without the hex encoding):

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 完成这个问题?

Now, while there are several things I am unhappy with (for example that this is done using an activity instead of a service) the big issue here is clearly the problem of uploading images. I am by no means the first to have this problem, so has anyone been able to get this done in java?

编辑 1

手头的问题没有取得任何进展,但创建了一个可能对遇到相同问题的人有用的解决方法.Tumblr 提供 通过邮件发帖,您可以编程 android 在后台发送电子邮件作为 此处显示.这很有效,但您需要要求用户提供他们的邮件帐户数据和要发布的 Tumblr 邮件地址.

Have not made any progress with the problem at hand but created a workaround that might be nice for people who have the same issue. Tumblr offers posting via mail and you can programm android to send emails in the background as shown here. This works very well but you need to ask users to provide their mail account data and the Tumblr-mail Adress to post.

编辑 2

多年过去了,使用电子邮件不再是简单的方法.有了 jumblr,终于有一个很好的 Java API 可以在 android 上运行.OAuth 身份验证并不好玩(从来都不是),但是一旦你克服了这一点,它就太棒了.

Years have pased and using email is no longer the easy way to do it. With jumblr there is finally a good API for Java that will work on android. OAuth-Authentication is no fun (it never is) but once you get past this, its fantastic.

现在,从技术上讲,如何进行身份验证的问题不属于这里,但我的问题太长了,所以我将在这里粘贴一些代码,如果您不感兴趣,请跳过它.

Now, technically the question of how to do the authentication does not belong here but It's my overly long question, so I'll just paste some code here and if it's not interesting to you just skip it.

这使用了一个名为 jumblr-0.0.10-jar-with-dependencies.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 看起来像这样:

The WebViewFragement looks like this:

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

推荐答案

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

Why don't you use Jumblr the official Java client for Tumblr.

问候.

这篇关于将图像从 Android 上传到 tumblr API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆