Day 22 - Twitter4j

สวัสดีครับ บทความนี้เป็นบทความที่ 22 แล้วนะครับ ที่ผมจะมาเขียน ในซีรีย์ Learn 30 Android Libraries in 30 days
สำหรับบทความทั้งหมด อ่านได้จากด้านล่างครับ
- Day 1 : AndroidStaggered Grid
- Day 2 : Paralloid
- Day 3 : Retrofit
- Day 4 : SwipeRefreshLayout
- Day 5 : Android GraphView
- Day 6 : Holo Color Picker
- Day 7 : Android Async Http
- Day 8 : Crashlytics
- Day 9 : Butter Knife
- Day 10 : Android Annotations
- Day 11 : DateTimePicker
- Day 12 : Circular Progress Button
- Day 13 : ViewPager
- Day 14 : ViewPagerIndicator
- Day 15 : FadingActionBar
- Day 16 : AutofitTextView
- Day 17 : SwipeListView
- Day 18 : ShowcaseView
- Day 19 : GreenDAO
- Day 20 : AndroidViewAnimation
- Day 21 : ActiveAndroid
- Day 22 : Twitter4J
- Day 23 : ListViewAnimations
- Day 24 : AndEngine
- Day 25 : EazeGraph
- Day 26 : Cardslib
- Day 27 : AdapterKit
- Day 28 : WeatherLib
- Day 29 : FlatUI
- Day 30 : Android Firebase
สำหรับวันนี้ขอนำเสนอเรื่อง Twitter4J เป็น Java Library ที่เอาไว้จัดการกับ Twitter API ตัวนี้ไม่ใช่ตัว Official นะครับ ถูกสร้างมาเพื่อให้ใช้งาน Twitter API ได้ง่ายขึ้นและสะดวกขึ้น จุดเด่นคือ
- Java 100%
- รองรับ OAuth
- รองรับ Twitter API เวอร์ชัน 1.1
Installation
เปิดไฟล์ build.gradle
ขึ้นมา แล้วเพิ่ม dependencies ลงไปดังนี้
dependencies { compile 'org.twitter4j:twitter4j-core:4.0.2'}
กด Sync Gradle เป็นอันเรียบร้อย
Usage
สำหรับขั้นตอนการใช้งาน Twitter4J ขั้นแรกนั้น เราต้องทำการ config ซะก่อนครับ วิธีการ Configuration นั้นทำได้หลายวิธี แต่สำหรับผม ขอเลือกใช้วิธี config ผ่าน ConfigurationBuilder
แบบนี้ครับ
ConfigurationBuilder cb = new ConfigurationBuilder();cb.setDebugEnabled(true) .setOAuthConsumerKey("") .setOAuthConsumerSecret("******************************************") .setOAuthAccessToken("**************************************************") .setOAuthAccessTokenSecret("******************************************");TwitterFactory tf = new TwitterFactory(cb.build());Twitter twitter = tf.getInstance();
ด้านบนเป็นตัวอย่าง การ config ค่า โดยใช้ค่า OAuthConsumerKey, OAuthConsumerSecret, OAuthAccessToken และ OAuthAccessTokenSecret ของ Twitter App คุณเอง โดยจะได้เมื่อเราทำการสร้าง Twitter Client App แล้ว
Create Twitter App
วิธีการสร้าง Twitter App ให้เข้าไปที่ Twitter Apps แล้วเลือก Create New App หรือจะกดลิงค์นี้เลยก็ได้ Create new App
ให้ทำการใส่ข้อมูลที่ต้องการ
- Name : ต้องไม่ซ้ำกับแอพคนอื่น
- Description: จะใส่อะไรไปก็ได้ อธิบายไว้ซักหน่อยก็ดี
- Website: ใส่ชื่อเว็บไซต์ (หากไม่มีก็ใส่อะไรไปก็ได้)
- Callback: ปล่อยว่างไว้
เลือก Yes, I agree แล้วก็ Create App ซะ
เมื่อเราสร้างแอพเสร็จแล้ว ให้เลือกที่แท็บ API Keys สังเกตจะเห็น API Key กับ API Secret ของเรา นั่นแหละครับ ส่วนนี้ที่เราจะเอาไปใช้
ต่อมา เรายังขาดอีก 2 Key ใช่มั้ย เลื่อนลงมาอีกนิดนึง กด Create my access token ทีนี้เราก็จะได้ Access token มาแล้ว ครบ 4 ทีนี้ก็เอาไปใส่ในที่เรา เว้นไว้เลยครับ
นำค่าทั้งสี่ค่า มาใส่ที่ ConfigurationBuilder
รูปแบบก็จะได้ดังนี้
private static final String API_KEY = "YOUR_API_KEY";private static final String API_SECRET = "YOUR_SECRET_KEY";private static final String ACCESS_TOKEN = "YOUR_ACCESS_TOKEN";private static final String ACCESS_TOKEN_SECRET = "YOUR_ACCESS_TOKEN_SECRET";
ConfigurationBuilder cb = new ConfigurationBuilder();cb.setDebugEnabled(true) .setOAuthConsumerKey(API_KEY) .setOAuthConsumerSecret(API_SECRET) .setOAuthAccessToken(ACCESS_TOKEN) .setOAuthAccessTokenSecret(ACCESS_TOKEN_SECRET);TwitterFactory tf = new TwitterFactory(cb.build());Twitter twitter = tf.getInstance();
Create Project
ลองสร้างโปรเจ็คกันดูเลยดีกว่า ตัวโปรเจ็คผมจะมี ListView ไว้แสดง tweet จากหน้า Timeline และก็มี EditText อันนึง เอาไว้ใส่ข้อความที่ต้องการ Tweet ครับ หน้าเลเอาท์ เลยจัดแบบนี้ (ไม่ได้ปรับแต่งอะไรเลย เน้นไวไว้ก่อนครับ) ไฟล์ activity_twitter4j.xml
มีดังนี้
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="16dp" android:layout_width="match_parent" android:layout_height="match_parent">
<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp">
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/text_tweet" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_toLeftOf="@+id/button_tweet" />
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/tweet" android:id="@+id/button_tweet" android:layout_alignParentRight="true"/>
</RelativeLayout>
<ListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/list_view"> </ListView>
</LinearLayout>
ไฟล์ res/values/strings.xml
<resources> <string name="tweet">Tweet</string></resources>
ส่วนไฟล์ Twitter4JActivity.java
ก็สร้างดังนี้
package com.devahoy.learn30androidlibraries.day22;
import android.os.AsyncTask;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.util.Log;import android.view.View;import android.widget.Toast;
import com.devahoy.learn30androidlibraries.R;
import twitter4j.Twitter;import twitter4j.TwitterException;import twitter4j.TwitterFactory;import twitter4j.conf.ConfigurationBuilder;
public class Twitter4jActivity extends ActionBarActivity {
private static final String TAG = Twitter4jActivity.class.getSimpleName();
private static final String API_KEY = "YOUR_API_KEY"; private static final String API_SECRET = "YOUR_SECRET_KEY"; private static final String ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"; private static final String ACCESS_TOKEN_SECRET = "YOUR_ACCESS_TOKEN_SECRET";
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.day22_activity_twitter4j);
ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setDebugEnabled(true) .setOAuthConsumerKey(API_KEY) .setOAuthConsumerSecret(API_SECRET) .setOAuthAccessToken(ACCESS_TOKEN) .setOAuthAccessTokenSecret(ACCESS_TOKEN_SECRET); TwitterFactory factory = new TwitterFactory(cb.build());
Twitter twitter = factory.getInstance(); try { twitter.updateStatus("Learn to create Simple Tweet with Twitter4J via @Devahoy"); } catch (TwitterException e) { Log.d(TAG, e.toString()); }
}}
โค๊ดด้านบน เมื่อเราทำการสร้าง TwitterFactory
จาก ConfigurationBuilder
แล้ว ก็สั่งให้ factory.getInstance().updateStatus()
เพื่อทำการโพสลง Twitter ครับ ลองรันโปรแกรมดูเลย เมื่อเปิดแอพมา จะมีข้อความไปโผล่ใน Tweet แบบที่ตั้งใจไว้หรือไม่?
ปรากฎว่ามี Error ครับ แอพรันไม่ได้
401:Authentication credentials (https://dev.twitter.com/pages/auth) were missing or incorrect.Ensure that you have set valid consumer key/secret, access token/secret, and the system clock is in sync. {"request":"\/1.1\/statuses\/update.json","error":"Read-only application cannot POST."} Relevant discussions can be found on the Internet at: http://www.google.co.jp/search?q=2fc5b7cb or http://www.google.co.jp/search?q=0e1dbbf5 TwitterException{exceptionCode=[2fc5b7cb-0e1dbbf5], statusCode=401, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=4.0.2}
อะฮ่า 401:Authentication credentials, Read-only application cannot POST.
คงเดากันได้ไม่ยากครับ คือไม่มีสิทธิ์เข้าถึงข้อมูล เพราะอะไร? ลองกลับไปดูที่ส่วน Application Settings ในหน้าเว็บดูครับ สังเกตที่ Access Level เราตั้งให้มันแค่ Read-Only
ฉะนั้นแอพนี้มีสิทธิ์แค่ อ่าน Tweet จาก Timeline ได้เท่านั้น ไม่มีสิทธิ์ โพส Tweet หากเราต้องการให้มัน tweet ได้ด้วย ก็ต้องไปเปลี่ยน Access Level เป็น Read and Write ครับ
เลือกเปลี่ยน Modify app permission เป็น Read and Write และทำการ Regenerate API Keys และ Regenerate my access token key ใหม่ด้วย เพื่อให้แน่ใจว่าได้สิทธิ์ Read and Write แล้ว
จากนั้นก็ใช้ API Keys อันใหม่ ไปแทนของเก่าครับ ทดสอบรันแอพอีกครั้ง คราวนี้ Error Network OnmainThreadException ครับ ต้องใช้ AsyncTask มาช่วย
package com.devahoy.learn30androidlibraries.day22;
import android.os.AsyncTask;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.util.Log;import android.view.View;import android.widget.Toast;
import com.devahoy.learn30androidlibraries.R;
import twitter4j.Twitter;import twitter4j.TwitterException;import twitter4j.TwitterFactory;import twitter4j.conf.ConfigurationBuilder;
public class Twitter4jActivity extends ActionBarActivity {
private static final String TAG = Twitter4jActivity.class.getSimpleName();
private static final String API_KEY = "YOUR_API_KEY"; private static final String API_SECRET = "YOUR_SECRET_KEY"; private static final String ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"; private static final String ACCESS_TOKEN_SECRET = "YOUR_ACCESS_TOKEN_SECRET";
private TwitterFactory mFactory; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.day22_activity_twitter4j);
ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setDebugEnabled(true) .setOAuthConsumerKey(API_KEY) .setOAuthConsumerSecret(API_SECRET) .setOAuthAccessToken(ACCESS_TOKEN) .setOAuthAccessTokenSecret(ACCESS_TOKEN_SECRET); mFactory = new TwitterFactory(cb.build());
new AsyncTweet().execute(); }
private class AsyncTweet extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) {
String result = null; Twitter twitter = mFactory.getInstance(); try { twitter.updateStatus("Learn to create Simple Tweet with Twitter4J via @Devahoy"); } catch (TwitterException e) { Log.d(TAG, e.toString()); result = e.getErrorMessage(); } return result; }
@Override protected void onPostExecute(String result) { super.onPostExecute(result); if (result == null) { Toast.makeText(Twitter4jActivity.this, "Tweeted!", Toast.LENGTH_LONG).show(); }
} }}
ทีนี้ก็ไม่มี error แล้ว พอเปิดดูหน้า Twitter ผม ได้ข้อความนี้ขึ้นมา
Learn to create Simple Tweet with Twitter4J via @Devahoy
— Chai Phonbopit (@Phonbopit) July 30, 2014
ทีนี้ เรามี EditText และ Button นี่นา ก็ใช้มันกรอกข้อความ จากนั้นก็กด Button ถึง Tweet ดีกว่าเปิดแอพมาแล้ว Tweet ก็เลยจัดการ เปลี่ยนเป็นให้โพส Tweet เมื่อมีการกดปุ่ม Button เท่านั้น ก็เพิ่มนี้ลงไป
public class Twitter4jActivity extends ActionBarActivity {
private EditText mTweet; private Button mButtonTweet;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.day22_activity_twitter4j);
mTweet = (EditText) findViewById(R.id.text_tweet); mButtonTweet = (Button) findViewById(R.id.button_tweet);
ConfigurationBuilder cb = ... ...
mButtonTweet.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new AsyncTweet().execute(); } }); }}
สุดท้ายแล้ว ListView เอาไว้แสดง Timeline จาก Twitter ก็ใช้คำสั่งนี้ครับ
Twitter twitter = mFactory.getInstance();List<twitter4j.Status> statuses = twitter.getHomeTimeline();for (twitter4j.Status status : statuses) { // status.getUser().getName()}
สร้าง AsyncTask อีกอันสำหรับ Timeline
public class Twitter4jActivity extends ActionBarActivity {
private ListView mListView; private ArrayList<String> mTimelines = new ArrayList<String>();
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.day22_activity_twitter4j);
mListView = (ListView) findViewById(R.id.list_view); ....
new AsyncTimeline().execute(); }
private class AsyncTimeline extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) {
Twitter twitter = mFactory.getInstance(); String result = null; try { List<twitter4j.Status> statuses = twitter.getHomeTimeline(); for (twitter4j.Status status : statuses) { mTimelines.add(status.getUser().getName() + " : " + status.getText()); }
} catch (TwitterException e) { Log.d(TAG, e.toString()); result = e.getErrorMessage(); }
return result; }
@Override protected void onPostExecute(String s) { super.onPostExecute(s);
if (s == null) { ArrayAdapter<String> adapter = new ArrayAdapter<String>(Twitter4jActivity.this, android.R.layout.simple_list_item_1, mTimelines);
mListView.setAdapter(adapter); } } }
จากโค๊ดด้านบน ทำการสร้าง AsyncTimeline
ซึ่ง extend AsyncTask เอาไว้ดึงข้อมูล Timeline มา จากนั้นผมก็นำมาใส่ใน mTimeline
ซึ่งเป็น ArrayList<String>
จากนั้นก็นำมาแสดงใน ListView
เมื่อเปิดแอพดู ก็จะได้หน้าตาแบบนี้
ไฟล์ของบทความนี้ Twitter4jActivity.java ลองเอาไปรัน และลองทดสอบเล่นกันดูนะครับ ส่วนรายละเอียดต่างๆ อ่านจากเว็บต้นฉบับ มีวิธการตั้งค่า การใช้งานอยู่ครบถ้วนครับ
Happy Coding :D
Reference
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust