没有显示错误,但是当单击按钮时,始终将失败方法。Internet处于活动状态,键是有效的。我使用调试器查看以下结果: -
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)
主要活动
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>
customvolleyrequest.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清单
<?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应用程序时遇到了相同的错误。
桌面应用程序仅支持OAUTH_CALLBACK值 'oob' /oauth/request_token
但是,当设备上安装了Twitter应用程序时,Twitter登录工作正常工作。
如果未在设备上安装Twitter应用程序,请获取Twitter登录工作,请对您的应用进行以下更改:
https://apps.twitter.com/app/13917465/permissions
转到应用程序中的"权限"选项卡,更改"读取,写入和访问直接消息",并在"其他权限"中启用"从用户请求电子邮件地址"。
最后,通过单击"更新设置"来保存更改。