我正在使用twitter rest api,这是( https://api.twitter.com/1.1/).

首先,我使用路标库生成oauth_signature.它运作良好.

上传状态端点(https://api.twitter.com/1.1/statuses/upload.json)运行良好,但如果状态参数包含“@”符号,则表示无效.所以这是我的代码

TwitterStatusesService.java

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;

public interface TwitterStatusesService {
    @POST("/1.1/statuses/update.json")
    Call<ResponseBody> update(@Query("status") String status,@Query("in_reply_to_status_id") String inReplyToStatusId,@Query("lat") Double lat,@Query("long") Double lon,@Query("media_ids") String mediaIds);
}

TwitterStatusesapiclient.java

import android.util.Log;

import com.twitter.sdk.android.core.TwitterauthToken;
import com.twitter.sdk.android.core.TwitterCore;
import com.twitter.sdk.android.core.TwitterSession;

import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Retrofit;
import se.akerfeldt.okhttp.signpost.OkHttpOAuthConsumer;
import se.akerfeldt.okhttp.signpost.SigningInterceptor;

public class TwitterStatusesClient {

    private final String TAG = getClass().getSimpleName();

    private static final String BASE_URL = "https://api.twitter.com/";

    private final TwitterStatusesService apiService;

    private static TwitterStatusesClient webServiceClient;

    public static TwitterStatusesClient getInstance() {
        if (webServiceClient == null)
            webServiceClient = new TwitterStatusesClient();
        return webServiceClient;
    }

    private TwitterStatusesClient() {
        private TwitterStatusesClient() {
        OkHttpOAuthConsumer consumer = new OkHttpOAuthConsumer(TWITTER_KEY,TWITTER_SECRET);

        TwitterSession activeSession = TwitterCore.getInstance().getSessionManager().getActiveSession();
        if (activeSession != null) {
            TwitterauthToken authToken = activeSession.getAuthToken();
            String token = authToken.token;
            String secret = authToken.secret;
            consumer.setTokenWithSecret(token,secret);
        }

        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new SigningInterceptor(consumer))
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client)
                .build();

        apiService = retrofit.create(TwitterStatusesService.class);
    }

    public Call<ResponseBody> update(String status,String statusId,Double lat,Double lon,String mediaIds) {
        return apiService.update(status,statusId,lat,lon,mediaIds);
    }
}

调用api客户端

String status = "@example";
TwitterStatusesClient.getInstance().update(status,null,null).enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call,Response<ResponseBody> response) {
            Log.v(TAG,"onResponse");
            progressDialog.dismiss();
            try {
                if (response.errorBody() != null) {
                    String error = response.errorBody().string();
                    Log.e(TAG,"Error : " + error);
                    ToastUtils.showErrorMessage(getContext(),"Error : " + error);
                    return;
                }

                String body = response.body().string();
                Log.v(TAG,"body : " + body);
            } catch (Exception e) {
                e.printstacktrace();
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call,Throwable t) {
            Log.v(TAG,"onFailure");
            t.printstacktrace();
        }
    });

给出错误:

{"errors":[{"code":32,"message":"Could not authenticate you."}]}

但是,如果我将使用状态变量“只是示例”而不是“@example”(具体点是删除@字符)正在工作.只有’@’符号不起作用.

编辑

这是我通过改装拦截器手动创建OAuth v1.0a签名签名代码:

OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Interceptor.Chain chain) throws IOException {
                    Request request = chain.request();

                    String method = request.method();
                    String baseUrl = "https://api.twitter.com" + request.url().url().getPath();

                    String oauthToken = "";
                    String oauthTokenSecret = "";

                    TwitterSession activeSession = TwitterCore.getInstance().getSessionManager().getActiveSession();
                    if (activeSession != null) {
                        TwitterauthToken authToken = activeSession.getAuthToken();
                        oauthToken = authToken.token;
                        oauthTokenSecret = authToken.secret;
                    }

                    String oauthNonce = "TXZScw4M8TG";
                    String oauthSignatureMethod = "HMAC-SHA1";
                    String oauthTimestamp = String.valueOf(System.currentTimeMillis() / 1000);
                    String oauthVersion = "1.0";

                    String parameterString = "";

                    parameterString = OAuthParams.addParam(request,parameterString,"count");
                    parameterString = OAuthParams.addParam(request,"id");
                    parameterString = OAuthParams.addParam(request,"in_reply_to_status_id");

                    // if any parameter added to parameterString,append '&' character.
                    if (parameterString.length() > 0) {
                        parameterString += "&";
                    }

                    parameterString += "oauth_consumer_key=" + TWITTER_KEY + "&"
                            + "oauth_nonce=" + oauthNonce + "&"
                            + "oauth_signature_method=" + oauthSignatureMethod + "&"
                            + "oauth_timestamp=" + oauthTimestamp + "&"
                            + "oauth_token=" + oauthToken + "&"
                            + "oauth_version=" + oauthVersion;

                    // add status parameter to parameterString.
                    parameterString = OAuthParams.addParam(request,"status");

                    Log.d(TAG,"normalizedParameters : " + parameterString);
                    Log.d(TAG,"parameterStringPercent : " + OAuth.percentEncode(parameterString));

                    String signatureBaseString = "";
                    signatureBaseString += OAuth.percentEncode(method) + "&";
                    signatureBaseString += OAuth.percentEncode(baseUrl) + "&";
                    signatureBaseString += OAuth.percentEncode(parameterString);

                    String oauthSignature = OauthSignature.generateSignature(signatureBaseString,TWITTER_SECRET,oauthTokenSecret);

                    String authorization = "OAuth oauth_consumer_key=\"" + TWITTER_KEY + "\"," +
                            "oauth_signature_method=\"HMAC-SHA1\"," +
                            "oauth_timestamp=\"" + oauthTimestamp + "\"," +
                            "oauth_nonce=\"" + oauthNonce + "\"," +
                            "oauth_version=\"1.0\"," +
                            "oauth_token=\"" + oauthToken + "\"," +
                            "oauth_signature=\"" + OAuth.percentEncode(oauthSignature) + "\"";

                    Log.w(TAG,"Authorization : " + authorization);

                    request = request.newBuilder()
                            .addHeader("Authorization",authorization)
                            .build();
                    return chain.proceed(request);
                }
            }).addInterceptor(interceptor).build();

OAuth.java

public static String percentEncode(String s) {
    if (s == null) {
        return "";
    }
    try {
        return URLEncoder.encode(s,ENCODING)
                // OAuth encodes some characters differently:
                .replace("+","%20").replace("*","%2A")
                .replace("%7E","~");
        // This Could be done faster with more hand-crafted code.
    } catch (UnsupportedEncodingException wow) {
        throw new RuntimeException(wow.getMessage(),wow);
    }
}

OAuthSignature.java

import android.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class OauthSignature {

public static String generateSignature(String signatueBaseStr,String oAuthConsumerSecret,String oAuthTokenSecret) {
    byte[] byteHMAC = null;
    try {
        Mac mac = Mac.getInstance("HmacSHA1");
        SecretKeySpec spec;
        if (null == oAuthTokenSecret) {
            String signingKey = OAuth.percentEncode(oAuthConsumerSecret) + '&';
            spec = new SecretKeySpec(signingKey.getBytes(),"HmacSHA1");
        } else {
            String signingKey = OAuth.percentEncode(oAuthConsumerSecret) + '&' + OAuth.percentEncode(oAuthTokenSecret);
            spec = new SecretKeySpec(signingKey.getBytes(),"HmacSHA1");
        }
        mac.init(spec);
        byteHMAC = mac.doFinal(signatueBaseStr.getBytes());
    } catch (Exception e) {
        e.printstacktrace();
    }
    return new String(Base64.encode(byteHMAC,Base64.DEFAULT));
}
}

解决方法

我建议使用面料 – https://fabric.io,它有各种各样的libs,如twitter登录,crashlytics和alss,你需要设置与Android工作室的面料插件.发布您可以发布/检索推文,无论您想发布什么.

对于您的问题 – 检查’@’是特殊符号,其中改造导致问题.这些问题是我在不同场景中遇到的改造.

尝试使用Fabric进行Twitter登录/ oAuth

android – Twitter OAuth Rest Api状态参数’@’符号的更多相关文章

  1. ios – 签名无效:oauth_signature

    我正在尝试生成oauth_signature以使用FatsecretAPI,但是获得无效的签名错误–无法弄清楚原因.我尝试尽可能准确地遵循here所述的所有步骤(参见步骤2)来生成签名值.他们说:UsetheHMAC-SHA1signaturealgorithmasdefinedbythe[RFC2104]tosigntherequestwheretextistheSignatureBaseStr

  2. ios – Oauth突然无法使用iphone(仅安装了FS应用程序)

    我们的iPhone应用程序允许通过oauth通过Foursquare登录.它工作正常,最近停止工作.我们得到的错误是:连接失败:回调uri对此使用者无效.但是,如果用户没有在手机上安装foursquare应用程序,它可以像以前一样正常工作.似乎FS现在正在进行重定向来处理FS应用程序内部的oauth,并且在尝试返回到原始应用程序时失败.通过野生动物园它似乎工作.这是在ios9上.解决方案?

  3. 保护MY REST API仅用于MY IOS APP

    我在Laravel中设计一个RESTAPI,用于我的ios应用程序.目前我被困在以下几点:如何保护我的RESTAPI只允许访问我的ios应用程序?听起来我需要通过向我的IOSAPP授予一个私钥来将类似于HMAC方法的内容合并到我的IOSAPP代码中.当从iosapp中运行请求时,我传递带有私钥和其他数据的哈希,然后当在服务器上收到请求时,我通过重新计算哈希来检测请求是否来自应用程序内的用户.我不知道这是否安全&我会认为不是吗?

  4. iOS Swift在哪里存储用户登录数据或OAuth令牌?

    事情并不像在用户手机上存储登录数据的最佳做法那样清晰.有人建议将userID=123和loggedIn=true类型数据等数据存储在NSUSerDefaults数据中.然而根据我的理解,根据这篇文章https://www.andyibanez.com/nsuserdefaults-not-for-sensitive-data/,这些数据可以很容易地被操作所以问题是:当用户浏览各种屏幕时,持久登录数

  5. ios – 使用带有OAuth 2.0的Google API在iPhone中登录Gmail

    我找到了Google提供的服务,可以访问各种Google服务的GoogleApi.我可以在iPhone中设置一个项目,并为iOS应用程序和本机应用程序创建API访问.我想为我的iPhone应用程序使用本机API.它API为我提供了电子邮件,全名,名字,姓氏,google_id,性别,dob,profile_image.如何在我的iPhone应用程序,任何示例应用程序,可用的代码段中使用这些?

  6. ios – 如何确定OAuth令牌是否已过期?

    我的iOS移动应用程序消耗使用OAuth2.0协议实现的服务.OAuth访问令牌带有刷新令牌和expires_in字段.我在我的应用程序中保存了刷新令牌并访问令牌过期时间,但是在使用它们时并没有什么好主意.>那么使用这个expires_in的通常和最佳做法是什么?>如何识别我的访问令牌是否过期?>是否有常见的Web服务错误格式,表示我的访问令牌已过期?

  7. ios – 在本地应用和网站之间共享凭据

    解决方法关联域和共享Web凭据在这里似乎不是一个好办法.你有两个选择:>将OAuth访问令牌作为URL-QueryString-Param传递给网页浏览器.https://x.y.z/?access_token=abc您必须操纵嵌入的URL,并确保您的后端了解这一点.很常见和容易的方法.许多网站像Facebook和Google正在URL中传递访问令牌.>如果您使用的是应用内浏览器,则可以截取URL请求并自行添加授权头.参见thisUIWebView和thisforWKWebView

  8. REST API iOS开发

    我将RestKitAPI设置到我的应用程序有很多麻烦.我想知道有没有其他好的API来制作RESTful应用程序?

  9. ios – 使用Firebase登录Facebook.找不到OAuth重定向URI

    我正在关注Firebase提供的手册.然而,我似乎无法做到的早期步骤.手册告诉我我在哪里可以在Facebook上找到这个设置?

  10. 泛型 – Swift相当于MIN和MAX宏

    在C/Objective-C中,可以使用MIN和MAX宏找到两个数字之间的最小值和最大值。Swift不支持宏,似乎在语言/基础库中没有等价物。应该有一个定制的解决方案,也许基于类似这样的one?min和max已经在Swift中定义:看到这个伟大的写在documented&undocumentedbuilt-infunctionsinSwift。

随机推荐

  1. bluetooth-lowenergy – Altbeacon库无法在Android 5.0上运行

    昨天我在Nexus4上获得了Android5.0的更新,并且altbeacon库停止了检测信标.似乎在监视和测距时,didEnterRegion和didRangeBeaconsInRegion都没有被调用.即使RadiusNetworks的Locate应用程序现在表现不同,一旦检测到信标的值,它们就不再得到更新,并且通常看起来好像信标超出了范围.我注意到的一点是,现在在logcat中出现以下行“B

  2. android – react-native动态更改响应者

    我正在使用react-native进行Android开发.我有一个视图,如果用户长按,我想显示一个可以拖动的动画视图.我可以使用PanResponder实现这一点,它工作正常.但我想要做的是当用户长按时,用户应该能够继续相同的触摸/按下并拖动新显示的Animated.View.如果您熟悉Google云端硬盘应用,则它具有类似的功能.当用户长按列表中的任何项目时,它会显示可拖动的项目.用户可以直接拖

  3. android – 是否有可能通过使用与最初使用的证书不同的证书对其进行签名来发布更新的应用程序

    是否可以通过使用与最初使用的证书不同的证书进行签名来发布Android应用程序的更新?我知道当我们尝试将这样的构建上传到市场时,它通常会给出错误消息.但有没有任何出路,比如将其标记为主要版本,指定市场中的某个地方?解决方法不,你不能这样做.证书是一种工具,可确保您是首次上传应用程序的人.所以总是备份密钥库!

  4. 如何检测Android中是否存在麦克风?

    ..所以我想在让用户访问语音输入功能之前检测麦克风是否存在.如何检测设备上是否有麦克风.谢谢.解决方法AndroidAPI参考:hasSystemFeature

  5. Android – 调用GONE然后VISIBLE使视图显示在错误的位置

    我有两个视图,A和B,视图A在视图B上方.当我以编程方式将视图A设置为GONE时,它将消失,并且它正下方的视图将转到视图A的位置.但是,当我再次将相同的视图设置为VISIBLE时,它会在视图B上显示.我不希望这样.我希望视图B回到原来的位置,这是我认为会发生的事情.我怎样才能做到这一点?编辑–代码}这里是XML:解决方法您可以尝试将两个视图放在RelativeLayout中并相对于彼此设置它们的位置.

  6. android – 获得一首歌的流派

    我如何阅读与歌曲相关的流派?我可以读这首歌,但是如何抓住这首歌的流派,它存放在哪里?解决方法检查此代码:

  7. android – 使用textShadow折叠工具栏

    我有一个折叠工具栏的问题,在展开状态我想在文本下面有一个模糊的阴影,我使用这段代码:用:我可以更改textColor,它可以工作,但阴影不起作用.我为阴影尝试了很多不同的值.是否可以为折叠文本投射阴影?

  8. android – 重用arm共享库

    我已经建立了armarm共享库.我有兴趣重用一个函数.我想调用该函数并获得返回值.有可能做这样的事吗?我没有任何头文件.我试过这个Android.mk,我把libtest.so放在/jni和/libs/armeabi,/lib/armeabi中.此时我的cpp文件编译,但现在是什么?我从objdump知道它的名字编辑:我试图用这个android.mk从hello-jni示例中添加prebuild库:它工作,但libtest.so相同的代码显示以下错误(启动时)libtest.so存在于libhello-j

  9. android – 为NumberPicker捕获键盘’Done’

    我有一个AlertDialog只有一些文本,一个NumberPicker,一个OK和一个取消.(我知道,这个对话框还没有做它应该保留暂停和恢复状态的事情.)我想在软键盘或其他IME上执行“完成”操作来关闭对话框,就像按下了“OK”一样,因为只有一个小部件可以编辑.看起来处理IME“Done”的最佳方法通常是在TextView上使用setonEditorActionListener.但我没有任何Te

  10. android – 想要在调用WebChromeClient#onCreateWindow时知道目标URL

    当我点击一个带有target=“_blank”属性的超链接时,会调用WebChromeClient#onCreateWindow,但我找不到新的窗口将打开的新方法?主页url是我唯一能知道的东西?我想根据目标网址更改应用行为.任何帮助表示赞赏,谢谢!

返回
顶部