Twitter相关功能集成

Posted by 程序亦非猿 on 2015-10-12

前言

app 未来可能有要往国外推的需求,需要做Facebook,Twitter登录,FB用umeng搞定了部分,剩下Twitter需要自己做.

Create-App

前提是你有账号,去注册Twitter
Twitter开发者平台创建开发者账号

这里有个很难搞的坑,就是创建应用需要添加手机号,否则你会得到以下错误:

Error
You must add your mobile phone to your Twitter profile before creating an application. Please read https://support.twitter.com/articles/110250-adding-your-mobile-number-to-your-account-via-web for more information.

但是令人发指的是,Twitter又不支持中国大陆+86的手机,遇到这个问题后瞬间整个人就不好了…
但是还是得完成啊,于是百般搜索,寻找解决方案,无果.
最后给twitter support(support@twitter.com)发了邮件,最终,人家给我开通了时间有限的权限.

1
2
3
4
5
6
7
Thank you for reaching out. We’re aware that you are not able to register a mobile phone number to your account. We have enabled access for you to create an app without doing so. Please note that this access will expire 7 days from the date of this email, so you must create your app within this time frame.
While developing your application, please review our Developer Agreement and Policy to ensure that your application is compliant with our Rules.
Regards,
ElliotSamuelson
Twitter Platform Operations

finally,我可以创建应用了.

Fabric

Twitter弄了个叫Fabric的插件,AS可用.
它会帮忙设置项目,帮忙生成很多必要的代码文件,挺繁琐的,这里省略了,因为已经弄完了,不想再搞了.

大致记录一些,不全,具体看我Github.
build.gradle文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
compile('com.twitter.sdk.android:twitter:1.8.0@aar') {
transitive = true;
}
compile('com.twitter.sdk.android:tweet-composer:0.9.0@aar') {
transitive = true;
}
buildscript {
repositories {
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'io.fabric.tools:gradle:1.+'
}
}
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
repositories {
maven { url 'https://maven.fabric.io/public' }
}

APP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class App extends Application {
// Note: Your consumer key and secret should be obfuscated in your source code before shipping.
private static final String TWITTER_KEY = "RJjbqTVS5kIseg9q4jsRecf7u";
private static final String TWITTER_SECRET = "dbBgVZYA4oBkmSr5jKaInMzijO2mt3uB82SHviTJ1tgK2Z5P8E";
@Override
public void onCreate() {
super.onCreate();
TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
// Fabric.with(this, new TwitterCore(authConfig), new Digits());
Fabric.with(this, new TwitterCore(authConfig),new TweetComposer());
}
}

集成完后,开始写代码.
PS:个人非常讨厌Twitter这种方式,而且搞的AS编译时间非常非常久,夸张的时候1个小时都没成功,不知道什么坑.

登录

最简单的方式

使用推特提供的TwitterLoginButton,自带UI效果

  1. 配置xml
    1
    2
    3
    4
    5
    <com.twitter.sdk.android.core.identity.TwitterLoginButton
    android:id="@+id/btn_twitter"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    />

效果

  1. 代码里设置监听回调
    调用TwitterLoginButton.setCallback即可监听,不需要设置点击事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    private void setUpTwitterButton() {
    mBtnTwitter.setCallback(new Callback<TwitterSession>() {//userName alancheen06 secret 4H6cMSpc59EbLSlcQ5QI0SzAUXAAZnxDZ40KUqQkJkl7s token 3313987080-L3UPicTGjEZrNjpjsobeDQRCbWGFyczUCV2O408
    @Override
    public void success(Result<TwitterSession> result) {
    Log.d("Twitter", "success() called with: " + "result = [" + result + "]++++data" + result.data);
    String name = result.data.getUserName();
    long userId = result.data.getUserId();//3313987080
    long id = result.data.getId();
    TwitterAuthToken token = result.data.getAuthToken();
    String secret = token.secret;
    String strToken = token.token;
    }
    @Override
    public void failure(TwitterException exception) {
    Log.d("Twitter", "failure() called with: " + "exception = [" + exception.getMessage() + "]");
    }
    });
    }
  2. 处理onActivityResult

如果有fragment则需要用fragment来处理,否则Activity处理

1
mBtnTwitter.onActivityResult(requestCode, resultCode, data);//140 requestCode

点击后效果

当手机安装了推特客户端,那么以上代码都没有问题,但是如果没有安装,那么就不能授权!
解决办法是去推特开发者后台,把app的setting下的callback url设置一下,不论什么,可以访问即可!

相关资料–>戳这里

自定义UI

但是我的需求不能使用推特提供的UI,不过貌似没看到哪里文档有提,不过幸好自己摸索出了如下方法.

其实说白了就是掰了一些TwitterLoginButton里的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mTvCustom.setOnClickListener(v -> {
new TwitterAuthClient().authorize(TwitterActivity.this, new Callback<TwitterSession>() {
@Override
public void success(Result<TwitterSession> result) {
String name = result.data.getUserName();
long userId = result.data.getUserId();//3313987080
long id = result.data.getId();
TwitterAuthToken token = result.data.getAuthToken();
String secret = token.secret;
String strToken = token.token;
}
@Override
public void failure(TwitterException e) {
}
});
});
}

获取更多信息

从上文也能看出来,我们只能获取一个name严格来说是screen_name,另外一个是userId,而我还需要头像等信息.
于是,还得接下去搞.
其实过程异常痛苦,因为推特并没有给出详细的例子,自己也没有弄清楚oauth,找了老半天也没有详细的文档,不过最后还是被我弄出来了.

这里直接给代码了,无非就是拿token去获取数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/***
* {"id":3313987080,"id_str":"3313987080","name":"\u7a0b\u5e8f\u4ea6\u975e\u733fAlan","screen_name":"alancheen06","location":"","profile_location":null,"description":"An android developer from China.","url":null,"entities":{"description":{"urls":[]}},"protected":false,"followers_count":1,"friends_count":34,"listed_count":0,"created_at":"Thu Aug 13 05:29:54 +0000 2015","favourites_count":2,"utc_offset":-25200,"time_zone":"Pacific Time (US & Canada)","geo_enabled":false,"verified":false,"statuses_count":13,"lang":"en","status":{"created_at":"Mon Oct 12 04:23:09 +0000 2015","id":653425648577286144,"id_str":"653425648577286144","text":"@Support How to add phone num?Thanks a lot!","source":"\u003ca href=\"http:\/\/twitter.com\" rel=\"nofollow\"\u003eTwitter Web Client\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":17874544,"in_reply_to_user_id_str":"17874544","in_reply_to_screen_name":"Support","geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":1,"entities":{"hashtags":[],"symbols":[],"user_mentions":[{"screen_name":"Support","name":"Twitter Support","id":17874544,"id_str":"17874544","indices":[0,8]}],"urls":[]},"favorited":false,"retweeted":false,"lang":"en"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/631699830872498176\/yThxaLUe_normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/631699830872498176\/yThxaLUe_normal.jpg","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false}
* @param token
*/
private void getInfo(final TwitterAuthToken token) {
new Thread(new Runnable() {
@Override
public void run() {
TwitterAuthConfig authConfig = TwitterCore.getInstance().getAuthConfig();
OAuthSigning oauthSigning = new OAuthSigning(authConfig, token);
Map<String, String> authHeaders = oauthSigning.getOAuthEchoHeadersForVerifyCredentials();
URL url = null;
try {
// url = new URL("https://api.twitter.com/1.1/users/show.json?");
url = new URL("https://api.twitter.com/1.1/users/show.json?screen_name=alancheen06&user_id=3313987080");
// url = new URL("http://api.yourbackend.com/check_credentials.json");
HttpURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// for (Map.Entry<String, String> entry : authHeaders.entrySet()) {
// connection.setRequestProperty(entry.getKey(), entry.getValue());
// }
// connection.addRequestProperty("Authorization","OAuth oauth_consumer_key=\"7Ud4sn002Jquc6hR6XFREEqds\", oauth_nonce=\"456e1966e1db379f36f1ea9551ce0ad8\", oauth_signature=\"QWGBWcurKrLd5RvtDwjzmqtasBc%3D\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1444727699\", oauth_token=\"3313987080-h6f0ecdEc100MCQjpKyTuiNVakj6nZ0bdV2HvUw\", oauth_version=\"1.0\"");
Map<String, String> par = new HashMap<String, String>();
par.put("screen_name", "alancheen06");
par.put("user_id", "3313987080");
OAuth1aService.signRequest(authConfig, token, conn, par);
conn.connect();
int status = conn.getResponseCode();
//得到读取的内容(流)
InputStreamReader in = new InputStreamReader(conn.getInputStream());
// 为输出创建BufferedReader
BufferedReader buffer = new BufferedReader(in);
String inputLine = null;
String resultData = "";
//使用循环来读取获得的数据
while (((inputLine = buffer.readLine()) != null)) {
//我们在每一行后面加上一个"\n"来换行
resultData += inputLine + "\n";
}
JSONObject jo = new JSONObject(resultData);
String imgUrl = jo.getString("profile_image_url");
Log.d("Twitter", "run: resultData" + resultData);
final String aa = resultData;
runOnUiThread(()->mTvInfo.setText(aa));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}).start();
}

Twitter分享

既然登录做了,那么分享也是需要的~

分享相对来说简单多了,只是需要注意推特分享图片只能是本地文件

1
2
3
4
5
TweetComposer.Builder builder = new TweetComposer.Builder(context)
.text(content)
.image(fileUri)
.url(url);
builder.show();

稍微解释一下参数:

  1. .text(String) 是发推的文本
  2. .image(Uri imageUri) 上面提过是因为只支持本地文件一般Uri.fromFile(file)即可
  3. .url(URL url)) 这个是网页链接,就是别人点击后跳转的地方,会出现在推文里.

分享效果

分享结果处理

上面提供的方法接收不到推特分享的结果,看了一下TweetComposer.Builder的源码后想出来了:
builder.createIntent()可以创建一个intent,然后自己调用startActivityForResult,重写onActivityResult来接受结果即可.
需要注意的是这样context的类型必须是activity了.

机智如我,搞定~

总结

做推特的功能大概花费了2天的时间,第一步添加手机号码的确实让我崩溃,后面也不顺利,但是幸好还是完成了功能~
另外也感慨一下自己的英文实在是烂,全英文的文档实在吃不消.
感谢Umeng集成了那么多第三方登录,分享功能,自己做真的累.

希望能给现在有需要or未来需要的人一些参考吧,就这样.

资料

API Console Tool
Log in with Twitter
SignIn-with-Twitter
文档
API
cannonball-android
示例-app