Bon ... c'est mon premier post ici en francais donc yaaayy ! :)
Apparemment c'est pas facile d'intégrer twitter sur android (contrairement à ce que je pensais ), j'ai eu une dizaine d'erreurs avant que tout marche, Donc pour vous éviter ces erreurs voici les étapes à suivre :
1 - Choisir la librairie twitter a utilisé
Actuellement on a 3 choix :
A mon avis JTwitter est le moins mis à jour et ne couvre pas la totalité de l'API Twitter , les deux autres sont mieux en terme de qualité mais Twitter4j est vraiment mis à jour avec chaque changement dans l' API Twitter (trés récurrent d'ailleurs) et son javadoc est trés utile et c'est pourquoi je l'ai choisis.
2- Télécharger le jar Twitter4j : récuperer la version pour android (actuellement c'est la twitter4j-android-2.2.6.zip ) et ajouter dans votre projet le jar twitter4j-core-android (dans le dossier libs et dans le buildpath).
3- S'incrire sur twitter developers et configurer l'application en ajoutant les informations demandés le site vous génere CONSUMER_KEY , CONSUMER_SECRET que vous aller utilisé avec le callback que vous allez saisir qu'est aussi important pour le reste de l'application.
4- le code de l'application :
TestTwitterApp.java (Activité principale):
package mona.android.TestTwitter;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class TestTwitterApp extends Activity {
private Button connectTwitterBtn;
private SharedPreferences prefs;
private static final String TAG = "WhereTwitApp";
private Twitter twitter;
private final static String CONSUMER_KEY = "<CONSUMER_KEY_ICI>";
private final static String CONSUMER_SECRET = "<CONSUMER_SECRET_ICI";
static final String OAUTH_CALLBACK_URL = "<CALLBACK_URL_ICI>";
private OAuthConsumer mConsumer;
private OAuthProvider mProvider;
private Context m_context;
private static final String TWITTER_CONNECTION_RESULT_ACTION = "twitter_connection_result_action";
private static final String TWITTER_CONNECTION_RESULT = "twitter_connection_result";
private static final int TWITTER_CONNECTION_SUCCESS = 1;
private static final int TWITTER_CONNECTION_FAILURE = 2;
private static final int REQUEST_AUTHORIZATION = 851;
private RequestToken requestToken;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
connectTwitterBtn = (Button) findViewById(R.id.connect_twitter_btn);
connectTwitterBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new GetTwitterRequestToken().execute();
}
});
}
private class GetTwitterRequestToken extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
String url;
try {
mConsumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
mProvider = new DefaultOAuthProvider(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"https://api.twitter.com/oauth/authorize");
url = mProvider.retrieveRequestToken(mConsumer, Uri.parse(OAUTH_CALLBACK_URL).toString());
Log.i(TAG, "url = "+url);
//Lance WebView activity
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(CONSUMER_KEY);
builder.setOAuthConsumerSecret(CONSUMER_SECRET);
Configuration configuration = builder.build();
TwitterFactory factory = new TwitterFactory(configuration);
twitter = factory.getInstance();
requestToken = twitter.getOAuthRequestToken();
Intent i = new Intent(WhereTwitApp.this, TwitterWebView.class);
i.putExtra(TwitterWebView.URL, requestToken.getAuthorizationURL());
startActivityForResult(i, REQUEST_AUTHORIZATION);
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
return "signing the request failed ";
} catch (OAuthNotAuthorizedException e) {
e.printStackTrace();
return "Twitter is not reachable at the moment, please try again later";
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
return "required parameters were not correctly set" ;
} catch (OAuthCommunicationException e) {
e.printStackTrace();
return "server communication failed, check internet connectivity";
} catch (TwitterException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result){
if (result != null) {
Toast.makeText(WhereTwitApp.this, result, Toast.LENGTH_LONG).show();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Uri uri = getIntent().getData();
if(uri != null && uri.toString().startsWith(OAUTH_CALLBACK_URL)){
String verifier = uri.getQueryParameter(oauth.signpost.OAuth.OAUTH_VERIFIER);
Log.i(TAG, "verifier = "+verifier);
try {
mProvider.retrieveAccessToken(mConsumer, verifier);
AccessToken at = new AccessToken(mConsumer.getToken(), mConsumer.getTokenSecret());
Log.i(TAG, "AccessToken at = "+ at);
twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
twitter.setOAuthAccessToken(at);
}
catch (Exception e) {
}
}
}
}
TwitterWebView.java :
package mona.android.TestTwitter;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewGroup.LayoutParams;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class TwitterWebView extends Activity {
final static String URL = "twitter_authorization_url";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView = new WebView(this);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAppCacheEnabled(false);
webView.getSettings().setSaveFormData(false);
webView.getSettings().setSavePassword(false);
webView.setWebViewClient(new WebViewClient() {
@Override
public void onLoadResource(WebView view, String url) {
checkURL(url);
}
});
Log.d(TwitterWebView.class.getName(), "Chargement Url: " + getIntent().getStringExtra(URL));
webView.loadUrl(getIntent().getStringExtra(URL));
setContentView(webView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
private void checkURL(String url) {
if(url.contains(getString(R.string.twitter_callbackGranted))) {
Uri uri = Uri.parse(url);
String oauthVerifier = uri.getQueryParameter("oauth_verifier");
Intent i = new Intent();
i.putExtra("oauth_verifier", oauthVerifier);
Log.d(TwitterWebView.class.getName(), "OK, Url: " + url);
setResult(RESULT_OK, i);
finish();
}
else if(url.contains(getString(R.string.twitter_callbackDenied))) {
Log.d(TwitterWebView.class.getName(), "Unauthorized, Url: " + url);
setResult(RESULT_FIRST_USER);
finish();
}
//URLs Bannés
else if(url.contains(getString(R.string.twitter_home)) ||
url.contains(getString(R.string.twitter_appSettings)) ||
url.contains(getString(R.string.twitter_tos)) ||
url.contains(getString(R.string.twitter_privacy))
) {
Log.d(TwitterWebView.class.getName(), "Unauthorized, Url: " + url);
setResult(RESULT_FIRST_USER);
finish();
}
else {
Log.d(TwitterWebView.class.getName(), "Passage Url: " + url);
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
setResult(RESULT_FIRST_USER);
finish();
}
}
Strings.xml :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, WhereTwitActivity!</string>
<string name="app_name">TestTwitter</string>
<string name="description_logo">TestTwitter</string>
<string name="connect_twitter">Connect twitter</string>
<string name="twitter_callbackGranted">oauth_verifier=</string>
<string name="twitter_callbackDenied">callback?denied=</string>
<string name="twitter_listenerAuthError">Could not authenticate with OAuth</string>
<string name="twitter_home">twitter.com/home</string>
<string name="twitter_appSettings">twitter.com/settings/applications</string>
<string name="twitter_tos">twitter.com/tos</string>
<string name="twitter_privacy">twitter.com/privacy</string>
<string name="twitter_unauthorizedMessage">Unauthorized</string>
<string name="twitter_errorMessage">Error</string>
<string name="twitter_okMessage">Tweet Successful</string>
</resources>
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="mona.android.TestTwitterApp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:logo="@drawable/ic_launcher"
android:hardwareAccelerated="true">
<activity
android:name=".TestTwitterApp"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:host="http" android:scheme="where.twit" />
</intent-filter>
</activity>
<activity
android:name="TwitterWebView"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
</application>
</manifest>
Alors pour expliquer un peu ce code en utilisant quelques erreurs que j'ai eu et comment ils sont corrigés dans le code :
- Faire attention pour que la constante CALLBACK_URL n'est pas la même partout (dans la configuration de l'application sur twitter developers , dans l'activité principale et dans le AndroidManifest) .
- oauth.signpost.exception.OAuthCommunicationException Communication with the service provider failed null
Ceci été à cause d'un appel network (connexion à Twitter ) dans le main thread en le mettant dans doInbackground de AsyncTask ce qui le permet d'etre exécuté dans un autre thread le probléme est réglé.
- Aprés l'authentification sur twitter la rédirection vers l'application ne marche pas et on a un erreur "Web page not available".
pour contourner ceci on crée une activité TwitterWebView que nous on controle en la configurant au URL de twitter et qui provoque un retour à l'application.
Si vous avez des questions n'hesitez pas.
Recent Comments