我已经在我的应用程序中实现了Twitter,我在Callback中面临问题。
Twitter API已于近期更新,因此我无法发送回拨网址。
此外,设置页面现在更改,没有选择基于Web的应用程序或桌面应用程序的选项。
如果我在此行发送回叫:
authUrl = provider.retrieveRequestToken(consumer,CALLBACK_URL);
它总是返回
oauth.signpost.exception.OAuthNotAuthorizedException: Authorization failed (server replied with a 401). This can happen if the consumer key was not correct or the signatures did not match.
但如果我在重定向到Twitter登录页面中发送 Null ,但在成功授权后,它不会返回我的应用程序。
显示Pin编号后,我想重定向回我的应用程序。
注意:Twitter已经更新了他们的API,因此Post中提供的旧代码无效。
我尝试了所有以下链接
Link 1, Link 2, Link 3, Link4 , Link5 , Link 6
我的代码如下:
public class Main extends Activity {
OAuthConsumer consumer;
OAuthProvider provider;
Twitter twitter;
private static String CALLBACK_URL = "twitterapptest://connect";
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
consumer = new DefaultOAuthConsumer(
"XXXXXXXXXXX",
"XXXXXXXXXXXXX");
provider = new DefaultOAuthProvider(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"https://api.twitter.com/oauth/authorize");
String authUrl = null;
try {
authUrl = provider.retrieveRequestToken(consumer,null);
this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)));
} catch (OAuthMessageSignerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OAuthNotAuthorizedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OAuthCommunicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String pin = null;
try {
pin = br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
provider.retrieveAccessToken(consumer, "4947222");
} catch (OAuthMessageSignerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OAuthNotAuthorizedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OAuthCommunicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL url = null;
try {
url = new URL("http://twitter.com/statuses/mentions.xml");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpURLConnection request = null;
try {
request = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
consumer.sign(request);
} catch (OAuthMessageSignerException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (OAuthExpectationFailedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (OAuthCommunicationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
request.connect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
System.out.println("Response: " + request.getResponseCode() + " "
+ request.getResponseMessage());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* As soon as the user successfully authorized the app, we are notified
* here. Now we need to get the verifier from the callback URL, retrieve
* token and token_secret and feed them to twitter4j (as well as
* consumer key and secret).
*/
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Uri uri = intent.getData();
if (uri != null && uri.toString().startsWith(CALLBACK_URL)) {
String verifier = uri
.getQueryParameter(oauth.signpost.OAuth.OAUTH_VERIFIER);
try {
// this will populate token and token_secret in consumer
provider.retrieveAccessToken(consumer,
verifier);
// TODO: you might want to store token and token_secret in you
// app settings!!!!!!!!
AccessToken a = new AccessToken(consumer.getToken(),
consumer.getTokenSecret());
// initialize Twitter4J
twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer("XXXXXXX", "XXXXXXXXXX");
twitter.setOAuthAccessToken(a);
// create a tweet
Date d = new Date(System.currentTimeMillis());
String tweet = "#OAuth working! " + d.toLocaleString();
// send the tweet
twitter.updateStatus(tweet);
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
}
我的宣言:
<?xml version="1.0" encoding="utf-8"?>
<activity android:name=".OAuthForTwitter" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden" android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="twitterapptest" android:host="connect" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.INTERNET" />
答案 0 :(得分:8)
问题在于Callback URl。 我们应该在应用程序的设置页面中的CallBack URL的字段名称中提供一个虚拟回调URL。
如果我们这样做并在我们的代码中发送回拨网址,则在成功登录后会有一个名为重定向到您的应用的选项
如需进一步参考,请查看此Link for Twitter
答案 1 :(得分:3)
您是否找到了问题的来源?我有同样的一个例外,最后我发现了它的来源。 Twitter的设置页面已经改变,你不能再选择基于Web的应用程序或桌面应用程序了。但是这里有一些提示:在你的Twitter应用程序的设置中,只需用http://www.dummy.com这样的虚拟URL填充回调URL。这将隐式设置您的应用程序具有Web浏览器,然后当您发送自己的回调时,它将重新设置虚拟的回调。 我花了很多时间才找到这个,所以我希望这个答案能帮助别人。
答案 2 :(得分:0)
将以下Callback URL
添加到应用中可以解决问题。它会将用户重定向到Application
,启动它以验证用户的Twitter
帐户_
在Manifest
_
<activity android:name="<YOUR ACTIVITY NAME>"
android:launchMode="singleTask" android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:screenOrientation="portrait">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="x-oauthflow-twitter" android:host="callback" />
</intent-filter>
在TwitterManager
中,您拥有所有TwitterFactory
和所需内容_
final public static String CALLBACK_SCHEME = "x-oauthflow-twitter";
final public static String CALLBACK_URL = CALLBACK_SCHEME + "://callback";
public static final String TWITTER_IEXTRA_OAUTH_VERIFIER = "oauth_verifier";
最后,您可以获得所需的一切_
例如,getHost
,getScheme
,getEncodedQuery
,getQuery
,getEncodedSchemeSpecificPart
等等根据您的需要使用 intent
通过回拨_返回
@Override
protected void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... arg0) {
Uri uri = intent.getData();
if (uri != null && uri.toString().startsWith(TwitterManager.TWITTER_CALLBACK_URL)) {
String verifier = uri.getQueryParameter(TwitterManager.TWITTER_IEXTRA_OAUTH_VERIFIER);
Log.e("---ActivityMain-onNewIntent---", "verifier:"+verifier+", uri- getQuery:"+uri.getQuery());
Log.i(ApplicationPockets.TAG, "verifier : "+verifier);
if(verifier != null){
try {
/*
*---Get the AccessToken and do what you like ... :)
*/
AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, verifier);
SharedPreferences.Editor e = context.getSharedPreferences(SF_TWITTER, Context.MODE_PRIVATE).edit();
e.putString(TWITTER_PREF_KEY_TOKEN, accessToken.getToken());
e.putString(TWITTER_PREF_KEY_SECRET, accessToken.getTokenSecret());
e.commit();
//Extra you would like to do...
} catch (TwitterException e) {
e.printStackTrace();
}
}else{
//Logout Twitter.
}
}
return null;
}
}.execute();
}
您的RequestToken _
try {
RequestToken requestToken = twitter.getOAuthRequestToken(TWITTER_CALLBACK_URL);
//Toast.makeText(activity, "Please authorize this app!", Toast.LENGTH_LONG).show();
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(requestToken.getAuthenticationURL())));
} catch (TwitterException e) {
e.printStackTrace();
}
我希望这对每个人都有帮助_