android - 登录推特总是去回调失败方法

标签 android android-volley twitter-fabric android-twitter

没有显示错误,但是当单击按钮时,它总是会回调失败方法。互联网处于 Activity 状态并且 key 有效。我使用调试器看到以下结果:-

E/Twitter: Invalid json: <?xml version="1.0" encoding="UTF-8"?>
       <hash>
         <error>Desktop applications only support the oauth_callback value 'oob'</error>
         <request>/oauth/request_token</request>
       </hash>

       com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
           at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
           at com.twitter.sdk.android.core.models.SafeListAdapter$1.read(SafeListAdapter.java:45)
           at com.twitter.sdk.android.core.models.SafeMapAdapter$1.read(SafeMapAdapter.java:45)
           at com.google.gson.Gson.fromJson(Gson.java:879)
           at com.google.gson.Gson.fromJson(Gson.java:844)
           at com.google.gson.Gson.fromJson(Gson.java:793)
           at com.google.gson.Gson.fromJson(Gson.java:765)
           at com.twitter.sdk.android.core.TwitterApiException.parseApiError(TwitterApiException.java:111)
           at com.twitter.sdk.android.core.TwitterApiException.readApiError(TwitterApiException.java:96)
           at com.twitter.sdk.android.core.TwitterApiException.<init>(TwitterApiException.java:44)
           at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)
           at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
           at android.os.Handler.handleCallback(Handler.java:739)
           at android.os.Handler.dispatchMessage(Handler.java:95)
           at android.os.Looper.loop(Looper.java:148)
           at android.app.ActivityThread.main(ActivityThread.java:5417)
           at java.lang.reflect.Method.invoke(Native Method)
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
        Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
           at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:387)
           at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:209)
           at com.twitter.sdk.android.core.models.SafeListAdapter$1.read(SafeListAdapter.java:45) 
           at com.twitter.sdk.android.core.models.SafeMapAdapter$1.read(SafeMapAdapter.java:45) 
           at com.google.gson.Gson.fromJson(Gson.java:879) 
           at com.google.gson.Gson.fromJson(Gson.java:844) 
           at com.google.gson.Gson.fromJson(Gson.java:793) 
           at com.google.gson.Gson.fromJson(Gson.java:765) 
           at com.twitter.sdk.android.core.TwitterApiException.parseApiError(TwitterApiException.java:111) 
           at com.twitter.sdk.android.core.TwitterApiException.readApiError(TwitterApiException.java:96) 
           at com.twitter.sdk.android.core.TwitterApiException.<init>(TwitterApiException.java:44) 
           at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42) 
           at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68) 
           at android.os.Handler.handleCallback(Handler.java:739) 
           at android.os.Handler.dispatchMessage(Handler.java:95) 
           at android.os.Looper.loop(Looper.java:148) 
           at android.app.ActivityThread.main(ActivityThread.java:5417) 
           at java.lang.reflect.Method.invoke(Native Method) 
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
E/Twitter: Failed to get request token
       com.twitter.sdk.android.core.TwitterApiException: HTTP request failed, Status: 401
           at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)
           at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
           at android.os.Handler.handleCallback(Handler.java:739)
           at android.os.Handler.dispatchMessage(Handler.java:95)
           at android.os.Looper.loop(Looper.java:148)
           at android.app.ActivityThread.main(ActivityThread.java:5417)
           at java.lang.reflect.Method.invoke(Native Method)
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
E/Twitter: Authorization completed with an error
       com.twitter.sdk.android.core.TwitterAuthException: Failed to get request token
           at com.twitter.sdk.android.core.identity.OAuthController$1.failure(OAuthController.java:95)
           at com.twitter.sdk.android.core.internal.oauth.OAuth1aService$1.failure(OAuth1aService.java:194)
           at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)
           at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
           at android.os.Handler.handleCallback(Handler.java:739)
           at android.os.Handler.dispatchMessage(Handler.java:95)
           at android.os.Looper.loop(Looper.java:148)
           at android.app.ActivityThread.main(ActivityThread.java:5417)
           at java.lang.reflect.Method.invoke(Native Method)
           at   com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

主要 Activity

package com.integrationtutorial;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.twitter.sdk.android.Twitter;
import com.twitter.sdk.android.core.Callback;
import com.twitter.sdk.android.core.Result;
import com.twitter.sdk.android.core.TwitterAuthConfig;
import com.twitter.sdk.android.core.TwitterAuthToken;
import com.twitter.sdk.android.core.TwitterException;
import com.twitter.sdk.android.core.TwitterSession;
import com.twitter.sdk.android.core.identity.TwitterLoginButton;
import com.twitter.sdk.android.core.models.User;

import io.fabric.sdk.android.Fabric;
import retrofit2.Call;

public class MainActivity extends AppCompatActivity
{

//This is your KEY and SECRET
//And it would be added automatically while the configuration
private static final String TWITTER_KEY = "KEY_HERE";
private static final String TWITTER_SECRET = "KEY_HERE";

//Tags to send the username and image url to next activity using intent
public static final String KEY_USERNAME = "username";
public static final String KEY_PROFILE_IMAGE_URL = "image_url";

//Twitter Login Button
TwitterLoginButton twitterLoginButton;


@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    //Initializing TwitterAuthConfig, these two line will also added automatically while configuration we did
    TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
    Fabric.with(this, new Twitter(authConfig));

    setContentView(R.layout.activity_main);

    //Initializing twitter login button
    twitterLoginButton = (TwitterLoginButton) findViewById(R.id.twitterLogin);

    //Adding callback to the button
    twitterLoginButton.setCallback(new Callback<TwitterSession>()
    {
        @Override
        public void success(Result<TwitterSession> result)
        {
            //If login succeeds passing the Calling the login method and passing Result object
            login(result);
        }

        @Override
        public void failure(TwitterException exception) {
            //If failure occurs while login handle it here
            Toast.makeText(getApplicationContext(),"Login with Twitter failure",Toast.LENGTH_LONG).show();

        }
    });

}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    //Adding the login result back to the button
    twitterLoginButton.onActivityResult(requestCode, resultCode, data);
}

//The login function accepting the result object
public void login(Result<TwitterSession> result) {

    //Creating a twitter session with result's data
    TwitterSession session = result.data;

    //Getting the username from session
    final String username = session.getUserName();

    //This code will fetch the profile image URL
    //Getting the account service of the user logged in
    Call<User> call= Twitter.getApiClient(session).getAccountService().verifyCredentials(true, false);
    call.enqueue(new Callback<User>()
    {
                @Override
                public void failure(TwitterException e)
                {
                    //If any error occurs handle it here
                }

                @Override
                public void success(Result<User> userResult)
                {
                    //If it succeeds creating a User object from userResult.data
                    User user = userResult.data;

                    //Getting the profile image url
                    String profileImage = user.profileImageUrl.replace("_normal", "");

                    //Creating an Intent
                    Intent intent = new Intent(MainActivity.this, ProfileActivity.class);

                    //Adding the values to intent
                    intent.putExtra(KEY_USERNAME,username);
                    intent.putExtra(KEY_PROFILE_IMAGE_URL, profileImage);

                    //Starting intent
                    startActivity(intent);
                }

    });
}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.integrationtutorial.MainActivity">


<com.twitter.sdk.android.core.identity.TwitterLoginButton
    android:id="@+id/twitterLogin"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical" />

</RelativeLayout>

ProfileActivity.java

package com.integrationtutorial;

import android.content.Intent; 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;

public class ProfileActivity extends AppCompatActivity {

//Image Loader object
private ImageLoader imageLoader;

//NetworkImageView Ojbect
private NetworkImageView profileImage;

//TextView object
private TextView textViewUsername;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_profile);

    //Initializing views
    profileImage = (NetworkImageView) findViewById(R.id.profileImage);
    textViewUsername = (TextView) findViewById(R.id.textViewUsername);

    //Getting the intent
    Intent intent = getIntent();

    //Getting values from intent
    String username = intent.getStringExtra(MainActivity.KEY_USERNAME);
    String profileImageUrl = intent.getStringExtra(MainActivity.KEY_PROFILE_IMAGE_URL);

    //Loading image
    imageLoader = CustomVolleyRequest.getInstance(this).getImageLoader();
    imageLoader.get(profileImageUrl, ImageLoader.getImageListener(profileImage, R.mipmap.ic_launcher, android.R.drawable.ic_dialog_alert));
    profileImage.setImageUrl(profileImageUrl, imageLoader);

    //Setting the username in textview
    textViewUsername.setText("@"+username);
}
}

activity_profile.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"


android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.integrationtutorial.ProfileActivity">

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/profileImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />


    <TextView
        android:id="@+id/textViewUsername"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />



</LinearLayout>

自定义 Volley 请求.java

package com.integrationtutorial;

import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

import com.android.volley.Cache;
import com.android.volley.Network;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.BasicNetwork;
import com.android.volley.toolbox.DiskBasedCache;
import com.android.volley.toolbox.HurlStack;
 import com.android.volley.toolbox.ImageLoader;

public class CustomVolleyRequest {

private static CustomVolleyRequest customVolleyRequest;
private static Context context;
private RequestQueue requestQueue;
private ImageLoader imageLoader;

private CustomVolleyRequest(Context context) {
    this.context = context;
    this.requestQueue = getRequestQueue();

    imageLoader = new ImageLoader(requestQueue,
            new ImageLoader.ImageCache() {
                private final LruCache<String, Bitmap>
                        cache = new LruCache<String, Bitmap>(20);

                @Override
                public Bitmap getBitmap(String url) {
                    return cache.get(url);
                }

                @Override
                public void putBitmap(String url, Bitmap bitmap) {
                    cache.put(url, bitmap);
                }
            });
}

public static synchronized CustomVolleyRequest getInstance(Context context)     {
    if (customVolleyRequest == null) {
        customVolleyRequest = new CustomVolleyRequest(context);
    }
    return customVolleyRequest;
}

public RequestQueue getRequestQueue() {
    if (requestQueue == null) {
        Cache cache = new DiskBasedCache(context.getCacheDir(), 10 * 1024 * 1024);
        Network network = new BasicNetwork(new HurlStack());
        requestQueue = new RequestQueue(cache, network);
        requestQueue.start();
    }
    return requestQueue;
}

public ImageLoader getImageLoader() {
    return imageLoader;
}
}

Android list

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.integrationtutorial">
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <meta-data
        android:name="io.fabric.ApiKey"
        android:value="KEY_HERE" />
</application>

<uses-permission android:name="android.permission.INTERNET" />
</manifest>

最佳答案

当我的设备上没有安装 Twitter 应用程序时,我遇到了同样的错误。

Desktop applications only support the oauth_callback value 'oob' /oauth/request_token

但是当 Twitter 应用程序安装在设备上时,Twitter 登录工作正常。

如果设备上未安装 Twitter 应用程序,要使 Twitter 登录正常工作,请对您的应用程序进行以下更改:

https://apps.twitter.com/app/13917465/permissions

转到应用程序中的“权限”选项卡,将“访问权限”更改为“读取、写入和访问直接消息”,并在“其他权限”中启用“向用户请求电子邮件地址”。

最后,单击“更新设置”保存更改。

关于android - 登录推特总是去回调失败方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41120959/

相关文章:

android - PreferenceScreen 中的文本大小

Android应用如何存储用户喜爱的数据来个性化动态数据

mysql - 选项卡和 ListView 中的 JSON 解析问题

android - 在 Android 应用程序中禁用 Volley 日志

java - 无法获取请求 token 方法 POST 必须具有请求正文

android-studio - Android Studio - 无法使用 Fabric 插件部署签名的 APK

android - Jetpack Compose 动画的行为是什么?

java - 坏或没有互联网连接检查器

java - 在 Volley 中更新 UI 的最有效方法是什么

android - 从 Fabric 插件注销