메시징 서비스
트위터 로그인 후 트위터 글 보기
등록
=> 페이지 X
https://dev.twitter.com/
dev.twitter.com/twitter-kit/android
=>변경
https://docs.fabric.io/android/fabric/overview.html
=>라이브러리를 이용해 쉽게 개발
킷을 이용한 손쉽게 연동
https://www.fabric.io/kits/android/twitterkit/install
1. 라이브러리 등록
app
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
}
2. 권한 설정
<uses-permission android:name="android.permission.INTERNET" />
3. 로그인 처리
버튼을 create 메서드에서 객체 생성 후 클릭시 connect 메서드를 호출해 준다.
connectBtn = (Button) findViewById(R.id.connectBtn);
connectBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
connect();
}
});
BasicInfo.TwitLogin 로그인 되었으면 if 문을 실행하고 트위터 로그인이 안되어 있으면 else 문으로 간다.
로그인이 안되어 있어서 RequestToken 요청 스레드
RequestTokenThread 의 스레드를 객체를 생성 후 start 시켜준다. 웹상의 네트워크연결이라서 당연히 스레드로 처리해야 한다.
private void connect() {
Log.d(TAG, "connect() called.");
if (BasicInfo.TwitLogin) {
Log.d(TAG, "twitter already logged in.");
Toast.makeText(getBaseContext(), "twitter already logged in.",
Toast.LENGTH_LONG).show();
try {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthAccessToken(BasicInfo.TWIT_KEY_TOKEN);
builder.setOAuthAccessTokenSecret(BasicInfo.TWIT_KEY_TOKEN_SECRET);
builder.setOAuthConsumerKey(BasicInfo.TWIT_CONSUMER_KEY);
builder.setOAuthConsumerSecret(BasicInfo.TWIT_CONSUMER_SECRET);
Configuration config = builder.build();
TwitterFactory tFactory = new TwitterFactory(config);
BasicInfo.TwitInstance = tFactory.getInstance();
Toast.makeText(getBaseContext(), "twitter connected.", Toast.LENGTH_LONG).show();
} catch (Exception ex) {
ex.printStackTrace();
}
showUserTimeline();
} else {
RequestTokenThread thread = new RequestTokenThread();
thread.start();
}
}
먼저 트위터의 인증코드의 key 값과 Secret 값을 가져온다.
이값은 BasicInfo 클래스에 다음과 같이 설정 하였다.
package org.androidtown.sns.twitapp;
import java.text.SimpleDateFormat;
import twitter4j.Twitter;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
public class BasicInfo {
public static final String TWIT_API_KEY = "xRoDCNvHVfoQToAWyebf4g";
public static final String TWIT_CONSUMER_KEY = "xRoDCNvHVfoQToAWyebf4g";
public static final String TWIT_CONSUMER_SECRET = "LooMN0gPSrc0j1ddX8AV8tmxBsA28rLWxNhFo0pNJg";
public static final String TWIT_CALLBACK_URL = "http://android-town.org";
public static final int REQ_CODE_TWIT_LOGIN = 1001;
public static boolean TwitLogin = false;
public static Twitter TwitInstance = null;
public static AccessToken TwitAccessToken = null;
public static RequestToken TwitRequestToken = null;
public static String TWIT_KEY_TOKEN = "";
public static String TWIT_KEY_TOKEN_SECRET = "";
public static String TwitScreenName = "";
public static SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy년 MM월 dd일 HH시 mm분");
}
트위터 팩토리에서 트위터 객체를 생성하고 키와 secret 값을 트위터 팩토리에 빌드하여 인증과정을 거친다.
인증과정은 당연히 handler 를 이용하여 인텐트로 전송한다.
인텐트의 putExtra 의 authUrl 은 트위트의 키값이다.
트위터에서 키값을 받아서 로그인 되면 반환 할수 있게 startActivityForResult 로 처리 하였다.
*/
class RequestTokenThread extends Thread {
public void run() {
try {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setDebugEnabled(true);
builder.setOAuthConsumerKey(BasicInfo.TWIT_CONSUMER_KEY);
builder.setOAuthConsumerSecret(BasicInfo.TWIT_CONSUMER_SECRET);
TwitterFactory factory = new TwitterFactory(builder.build());
Twitter mTwit = factory.getInstance();
final RequestToken mRequestToken = mTwit.getOAuthRequestToken();
String outToken = mRequestToken.getToken();
String outTokenSecret = mRequestToken.getTokenSecret();
Log.d(TAG, "Request Token : " + outToken + ", " + outTokenSecret);
Log.d(TAG, "AuthorizationURL : " + mRequestToken.getAuthorizationURL());
BasicInfo.TwitInstance = mTwit;
BasicInfo.TwitRequestToken = mRequestToken;
mHandler.post(new Runnable() {
public void run() {
Intent intent = new Intent(getApplicationContext(), TwitLogin.class);
intent.putExtra("authUrl", mRequestToken.getAuthorizationURL());
startActivityForResult(intent, BasicInfo.REQ_CODE_TWIT_LOGIN);
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
트위터에서 반환되는 resultCode 코드 rk RESULT_OK 이고 BasicInfo.REQ_CODE_TWIT_LOGIN=
1001 같으면 OAuthAccessTokenThread 스레드를 실행한다. 이때 트위터에서 가져온 resultIntent 값을 파라미터로 넘긴다.
로그인 실패시 응답처리 과정은 없다.
/**
* 다른 액티비티로부터의 응답 처리
*/
protected void onActivityResult(int requestCode,
int resultCode, Intent resultIntent) {
super.onActivityResult(requestCode, resultCode, resultIntent);
if (resultCode == RESULT_OK) {
if (requestCode == BasicInfo.REQ_CODE_TWIT_LOGIN) {
OAuthAccessTokenThread thread =
new OAuthAccessTokenThread(resultIntent);
thread.start();
}
}
}
트위터에 가져온 정보를 BasicInfo 클래스에 저장을 하고, 토스트로 트위터 접속 성공 메시지를 뿌려준다.
showUserTimeline() 메소드를 호출해 준다.
class OAuthAccessTokenThread extends Thread {
Intent resultIntent;
public OAuthAccessTokenThread(Intent intent) {
resultIntent = intent;
}
public void run() {
try {
Twitter mTwit = BasicInfo.TwitInstance;
AccessToken mAccessToken =
mTwit.getOAuthAccessToken(BasicInfo.TwitRequestToken,
resultIntent.getStringExtra("oauthVerifier"));
BasicInfo.TwitLogin = true;
BasicInfo.TWIT_KEY_TOKEN = mAccessToken.getToken();
BasicInfo.TWIT_KEY_TOKEN_SECRET = mAccessToken.getTokenSecret();
BasicInfo.TwitAccessToken = mAccessToken;
BasicInfo.TwitScreenName = mTwit.getScreenName();
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(getBaseContext(), "Twitter connection succeeded : "
+ BasicInfo.TWIT_KEY_TOKEN, Toast.LENGTH_LONG).show();
showUserTimeline();
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
showUserTimeline 메소드는 접속하기 버튼을 숨기고 텍스트에 트위터 계정이름을 뿌려준다.
그리고 트위터 글을 갱신할 수있게 GetUserTimelineThread 스레드를 생성하고 start 시킨다.
private void showUserTimeline() {
Log.d(TAG, "showUserTimeline() called.");
connectBtn.setVisibility(View.GONE);
nameText.setVisibility(View.VISIBLE);
nameText.setText(BasicInfo.TwitScreenName);
// UserTimeline 요청
GetUserTimelineThread thread = new GetUserTimelineThread();
thread.start();
}
StatusListView statusList; StatusListAdapter statusAdapter;
트위터 목록을 갱신 하여 어댑터로 데이터를 화면에 뿌려준다.
class GetUserTimelineThread extends Thread {
public void run() {
getUserTimeline();
}
/**
* UserTimeline 요청
*/
private void getUserTimeline() {
Twitter mTwit = BasicInfo.TwitInstance;
try {
final List<Status> statuses = mTwit.getUserTimeline();
mHandler.post(new Runnable() {
public void run() {
statusAdapter.setListItems(statuses);
statusAdapter.notifyDataSetChanged();
}
});
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
다시 로그인 if문에서 로그인 true 이면 인증을 설정후 트위터 정보를 가져오고, showUserTimeline 메소드를 호출한다.
if (BasicInfo.TwitLogin) {
Log.d(TAG, "twitter already logged in.");
Toast.makeText(getBaseContext(), "twitter already logged in.",
Toast.LENGTH_LONG).show();
try {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthAccessToken(BasicInfo.TWIT_KEY_TOKEN);
builder.setOAuthAccessTokenSecret(BasicInfo.TWIT_KEY_TOKEN_SECRET);
builder.setOAuthConsumerKey(BasicInfo.TWIT_CONSUMER_KEY);
builder.setOAuthConsumerSecret(BasicInfo.TWIT_CONSUMER_SECRET);
Configuration config = builder.build();
TwitterFactory tFactory = new TwitterFactory(config);
BasicInfo.TwitInstance = tFactory.getInstance();
Toast.makeText(getBaseContext(), "twitter connected.", Toast.LENGTH_LONG).show();
} catch (Exception ex) {
ex.printStackTrace();
}
showUserTimeline();
onpause 와 onResume 에서 정보를 SharedPreferences 를 이용하여 저장한다.
protected void onPause() {
super.onPause();
saveProperties();
}
protected void onResume() {
super.onResume();
loadProperties();
}
private void saveProperties() {
SharedPreferences pref = getSharedPreferences("TWIT", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("TwitLogin", BasicInfo.TwitLogin);
editor.putString("TWIT_KEY_TOKEN", BasicInfo.TWIT_KEY_TOKEN);
editor.putString("TWIT_KEY_TOKEN_SECRET", BasicInfo.TWIT_KEY_TOKEN_SECRET);
editor.commit();
}
private void loadProperties() {
SharedPreferences pref = getSharedPreferences("TWIT", MODE_PRIVATE);
BasicInfo.TwitLogin = pref.getBoolean("TwitLogin", false);
BasicInfo.TWIT_KEY_TOKEN = pref.getString("TWIT_KEY_TOKEN", "");
BasicInfo.TWIT_KEY_TOKEN_SECRET = pref.getString("TWIT_KEY_TOKEN_SECRET", "");
}
글을 작성후 버튼을 클릭하면 updateStatus 메소드를 호출한다.
writeBtn = (Button) findViewById(R.id.writeBtn);
writeBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String statusText = writeInput.getText().toString();
if (statusText.length() < 1) {
Toast.makeText(getApplicationContext(), "글을 입력하세요.",
Toast.LENGTH_LONG).show();
return;
}
updateStatus(statusText);
}
});
writeInput = (EditText) findViewById(R.id.writeInput);
updateStatus 메서드는 updateStatusThread 의 객체를 생성후 간단하게 트위터와 연동처리로 데이터를 넘겨주고
showUserTimeline 메소드를 를 호출하여 어뎁타로 데이터 처리후 리스트 다시 갱신 해 준다.
private void updateStatus(String statusText) {
UpdateStatusThread thread = new UpdateStatusThread(statusText);
thread.start();
}
class UpdateStatusThread extends Thread {
String statusText;
public UpdateStatusThread(String inText) {
statusText = inText;
}
public void run() {
try {
Status status = BasicInfo.TwitInstance.updateStatus(statusText);
final Date curDate = status.getCreatedAt();
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "글을 업데이트했습니다 :" +
" " + BasicInfo.DateFormat.format(curDate),
Toast.LENGTH_SHORT).show();
showUserTimeline();
}
});
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
전체 코드
class BasicInfo
package org.androidtown.sns.twitapp;
import java.text.SimpleDateFormat;
import twitter4j.Twitter;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
public class BasicInfo {
public static final String TWIT_API_KEY = "xRoDCNvHVfoQToAWyebf4g";
public static final String TWIT_CONSUMER_KEY = "xRoDCNvHVfoQToAWyebf4g";
public static final String TWIT_CONSUMER_SECRET = "LooMN0gPSrc0j1ddX8AV8tmxBsA28rLWxNhFo0pNJg";
public static final String TWIT_CALLBACK_URL = "http://android-town.org";
public static final int REQ_CODE_TWIT_LOGIN = 1001;
public static boolean TwitLogin = false;
public static Twitter TwitInstance = null;
public static AccessToken TwitAccessToken = null;
public static RequestToken TwitRequestToken = null;
public static String TWIT_KEY_TOKEN = "";
public static String TWIT_KEY_TOKEN_SECRET = "";
public static String TwitScreenName = "";
public static SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy년 MM월 dd일 HH시 mm분");
}
class MainActivity
package org.androidtown.sns.twitapp;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Date;
import java.util.List;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
/**
* 트위터 연동 방법에 대해 알 수 있습니다.
*
* @author Mike
*/
public class MainActivity extends ActionBarActivity {
public static final String TAG = "MainActivity";
TextView nameText;
Button connectBtn;
StatusListView statusList;
StatusListAdapter statusAdapter;
Button writeBtn;
EditText writeInput;
Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connectBtn = (Button) findViewById(R.id.connectBtn);
connectBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
connect();
}
});
nameText = (TextView) findViewById(R.id.nameText);
statusList = (StatusListView) findViewById(R.id.statusList);
statusAdapter = new StatusListAdapter(this, mHandler);
statusList.setAdapter(statusAdapter);
statusList.setOnDataSelectionListener(new OnDataSelectionListener() {
public void onDataSelected(AdapterView parent, View v, int position, long id) {
Status curItem = (Status) statusAdapter.getItem(position);
String curText = curItem.getText();
Toast.makeText(getApplicationContext(), "Selected : " +
curText, Toast.LENGTH_LONG).show();
}
});
writeBtn = (Button) findViewById(R.id.writeBtn);
writeBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String statusText = writeInput.getText().toString();
if (statusText.length() < 1) {
Toast.makeText(getApplicationContext(), "글을 입력하세요.",
Toast.LENGTH_LONG).show();
return;
}
updateStatus(statusText);
}
});
writeInput = (EditText) findViewById(R.id.writeInput);
}
private void updateStatus(String statusText) {
UpdateStatusThread thread = new UpdateStatusThread(statusText);
thread.start();
}
class UpdateStatusThread extends Thread {
String statusText;
public UpdateStatusThread(String inText) {
statusText = inText;
}
public void run() {
try {
Status status = BasicInfo.TwitInstance.updateStatus(statusText);
final Date curDate = status.getCreatedAt();
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "글을 업데이트했습니다 :" +
" " + BasicInfo.DateFormat.format(curDate),
Toast.LENGTH_SHORT).show();
showUserTimeline();
}
});
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
private void connect() {
Log.d(TAG, "connect() called.");
if (BasicInfo.TwitLogin) {
Log.d(TAG, "twitter already logged in.");
Toast.makeText(getBaseContext(), "twitter already logged in.",
Toast.LENGTH_LONG).show();
try {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthAccessToken(BasicInfo.TWIT_KEY_TOKEN);
builder.setOAuthAccessTokenSecret(BasicInfo.TWIT_KEY_TOKEN_SECRET);
builder.setOAuthConsumerKey(BasicInfo.TWIT_CONSUMER_KEY);
builder.setOAuthConsumerSecret(BasicInfo.TWIT_CONSUMER_SECRET);
Configuration config = builder.build();
TwitterFactory tFactory = new TwitterFactory(config);
BasicInfo.TwitInstance = tFactory.getInstance();
Toast.makeText(getBaseContext(), "twitter connected.", Toast.LENGTH_LONG).show();
} catch (Exception ex) {
ex.printStackTrace();
}
showUserTimeline();
} else {
RequestTokenThread thread = new RequestTokenThread();
thread.start();
}
}
/**
* RequestToken 요청 스레드
*/
class RequestTokenThread extends Thread {
public void run() {
try {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setDebugEnabled(true);
builder.setOAuthConsumerKey(BasicInfo.TWIT_CONSUMER_KEY);
builder.setOAuthConsumerSecret(BasicInfo.TWIT_CONSUMER_SECRET);
TwitterFactory factory = new TwitterFactory(builder.build());
Twitter mTwit = factory.getInstance();
final RequestToken mRequestToken = mTwit.getOAuthRequestToken();
String outToken = mRequestToken.getToken();
String outTokenSecret = mRequestToken.getTokenSecret();
Log.d(TAG, "Request Token : " + outToken + ", " + outTokenSecret);
Log.d(TAG, "AuthorizationURL : " + mRequestToken.getAuthorizationURL());
BasicInfo.TwitInstance = mTwit;
BasicInfo.TwitRequestToken = mRequestToken;
mHandler.post(new Runnable() {
public void run() {
Intent intent = new Intent(getApplicationContext(), TwitLogin.class);
intent.putExtra("authUrl", mRequestToken.getAuthorizationURL());
startActivityForResult(intent, BasicInfo.REQ_CODE_TWIT_LOGIN);
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
/**
* 다른 액티비티로부터의 응답 처리
*/
protected void onActivityResult(int requestCode,
int resultCode, Intent resultIntent) {
super.onActivityResult(requestCode, resultCode, resultIntent);
if (resultCode == RESULT_OK) {
if (requestCode == BasicInfo.REQ_CODE_TWIT_LOGIN) {
OAuthAccessTokenThread thread =
new OAuthAccessTokenThread(resultIntent);
thread.start();
}
}
}
class OAuthAccessTokenThread extends Thread {
Intent resultIntent;
public OAuthAccessTokenThread(Intent intent) {
resultIntent = intent;
}
public void run() {
try {
Twitter mTwit = BasicInfo.TwitInstance;
AccessToken mAccessToken =
mTwit.getOAuthAccessToken(BasicInfo.TwitRequestToken,
resultIntent.getStringExtra("oauthVerifier"));
BasicInfo.TwitLogin = true;
BasicInfo.TWIT_KEY_TOKEN = mAccessToken.getToken();
BasicInfo.TWIT_KEY_TOKEN_SECRET = mAccessToken.getTokenSecret();
BasicInfo.TwitAccessToken = mAccessToken;
BasicInfo.TwitScreenName = mTwit.getScreenName();
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(getBaseContext(), "Twitter connection succeeded : "
+ BasicInfo.TWIT_KEY_TOKEN, Toast.LENGTH_LONG).show();
showUserTimeline();
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private void showUserTimeline() {
Log.d(TAG, "showUserTimeline() called.");
connectBtn.setVisibility(View.GONE);
nameText.setVisibility(View.VISIBLE);
nameText.setText(BasicInfo.TwitScreenName);
// UserTimeline 요청
GetUserTimelineThread thread = new GetUserTimelineThread();
thread.start();
}
class GetUserTimelineThread extends Thread {
public void run() {
getUserTimeline();
}
/**
* UserTimeline 요청
*/
private void getUserTimeline() {
Twitter mTwit = BasicInfo.TwitInstance;
try {
final List<Status> statuses = mTwit.getUserTimeline();
mHandler.post(new Runnable() {
public void run() {
statusAdapter.setListItems(statuses);
statusAdapter.notifyDataSetChanged();
}
});
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
protected void onPause() {
super.onPause();
saveProperties();
}
protected void onResume() {
super.onResume();
loadProperties();
}
private void saveProperties() {
SharedPreferences pref = getSharedPreferences("TWIT", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("TwitLogin", BasicInfo.TwitLogin);
editor.putString("TWIT_KEY_TOKEN", BasicInfo.TWIT_KEY_TOKEN);
editor.putString("TWIT_KEY_TOKEN_SECRET", BasicInfo.TWIT_KEY_TOKEN_SECRET);
editor.commit();
}
private void loadProperties() {
SharedPreferences pref = getSharedPreferences("TWIT", MODE_PRIVATE);
BasicInfo.TwitLogin = pref.getBoolean("TwitLogin", false);
BasicInfo.TWIT_KEY_TOKEN = pref.getString("TWIT_KEY_TOKEN", "");
BasicInfo.TWIT_KEY_TOKEN_SECRET = pref.getString("TWIT_KEY_TOKEN_SECRET", "");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
interface OnDataSelectionListener
package org.androidtown.sns.twitapp;
import android.view.View;
import android.widget.AdapterView;
/**
* Interface that is called when an item is selected in DataListView
*
* @author Mike
*/
public interface OnDataSelectionListener {
public void onDataSelected(AdapterView parent, View v, int position, long id);
}
class StatusItemView
package org.androidtown.sns.twitapp;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class StatusItemView extends LinearLayout {
/**
* Icon
*/
private ImageView mIcon;
/**
* TextView 01
*/
private TextView mText01;
/**
* TextView 02
*/
private TextView mText02;
/**
* TextView 03
*/
private TextView mText03;
public StatusItemView(Context context) {
super(context);
// Layout Inflation
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.listitem, this, true);
// Set Icon
mIcon = (ImageView) findViewById(R.id.iconItem);
// Set Text 01
mText01 = (TextView) findViewById(R.id.dataItem01);
// Set Text 02
mText02 = (TextView) findViewById(R.id.dataItem02);
// Set Text 03
mText03 = (TextView) findViewById(R.id.dataItem03);
}
/**
* set Text
*
* @param index
* @param data
*/
public void setText(int index, String data) {
if (index == 0) {
mText01.setText(data);
} else if (index == 1) {
mText02.setText(data);
} else if (index == 2) {
mText03.setText(data);
} else {
throw new IllegalArgumentException();
}
}
/**
* set Icon
*
* @param icon
*/
public void setIcon(Drawable icon) {
mIcon.setImageDrawable(icon);
}
public void setIcon(Bitmap bitmap) {
mIcon.setImageBitmap(bitmap);
}
}
class StatusListAdapter
package org.androidtown.sns.twitapp;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.net.URL;
import java.util.Date;
import java.util.List;
import twitter4j.Status;
import twitter4j.User;
public class StatusListAdapter extends BaseAdapter {
public static String TAG = "StatusListAdapter";
private Context mContext;
private List<Status> mStatuses = null;
Handler mHandler;
public StatusListAdapter(Context context, Handler handler) {
mContext = context;
mHandler = handler;
}
public void setListItems(List<Status> list) {
mStatuses = list;
}
public int getCount() {
if (mStatuses == null) {
return 0;
} else {
return mStatuses.size();
}
}
public Object getItem(int position) {
if (mStatuses == null) {
return null;
} else {
return mStatuses.get(position);
}
}
public boolean areAllItemsSelectable() {
return false;
}
public boolean isSelectable(int position) {
return true;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
StatusItemView itemView;
if (convertView == null) {
itemView = new StatusItemView(mContext);
} else {
itemView = (StatusItemView) convertView;
}
try {
Status curStatus = mStatuses.get(position);
User user = curStatus.getUser();
String userName = user.getName();
String userScreenName = user.getScreenName();
URL url = new URL(user.getProfileImageURL());
Date date = curStatus.getCreatedAt();
String data = curStatus.getText();
itemView.setText(0, userScreenName);
String dateStr = BasicInfo.DateFormat.format(date);
itemView.setText(1, dateStr);
itemView.setText(2, data);
if (url != null) {
Log.d(TAG, "Bitmap URL : " + url);
GetBitmapThread thread = new GetBitmapThread(itemView, url);
thread.start();
}
} catch(Exception ex) {
ex.printStackTrace();
}
return itemView;
}
class GetBitmapThread extends Thread {
StatusItemView itemView;
URL url;
public GetBitmapThread(StatusItemView view, URL inUrl) {
itemView = view;
url = inUrl;
}
public void run() {
try {
final Bitmap curBitmap = BitmapFactory.decodeStream(url.openStream());
mHandler.post(new Runnable() {
public void run() {
itemView.setIcon(curBitmap);
}
});
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
class StatusListView
package org.androidtown.sns.twitapp;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;
public class StatusListView extends ListView {
/**
* DataAdapter for this instance
*/
private StatusListAdapter adapter;
/**
* Listener for data selection
*/
private OnDataSelectionListener selectionListener;
public StatusListView(Context context) {
super(context);
init();
}
public StatusListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/**
* set initial properties
*/
private void init() {
setOnItemClickListener(new OnItemClickAdapter());
}
/**
* set DataAdapter
*
* @param adapter
*/
public void setAdapter(BaseAdapter adapter) {
super.setAdapter(adapter);
}
/**
* get DataAdapter
*
* @return
*/
public BaseAdapter getAdapter() {
return (BaseAdapter)super.getAdapter();
}
/**
* set OnDataSelectionListener
*
* @param listener
*/
public void setOnDataSelectionListener(OnDataSelectionListener listener) {
this.selectionListener = listener;
}
/**
* get OnDataSelectionListener
*
* @return
*/
public OnDataSelectionListener getOnDataSelectionListener() {
return selectionListener;
}
class OnItemClickAdapter implements OnItemClickListener {
public OnItemClickAdapter() {
}
public void onItemClick(AdapterView parent, View v, int position, long id) {
if (selectionListener == null) {
return;
}
// call the OnDataSelectionListener method
selectionListener.onDataSelected(parent, v, position, id);
}
}
}
class TwitLogin
package org.androidtown.sns.twitapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class TwitLogin extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.twit_login);
WebView webview = (WebView) findViewById(R.id.webView);
webview.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (url != null && url.equals("http://mobile.twitter.com/")) {
finish();
} else if (url != null && url.startsWith(BasicInfo.TWIT_CALLBACK_URL)) {
String[] params = url.split("\\?")[1].split("&");
String oauthToken = "";
String oauthVerifier = "";
try {
if (params[0].startsWith("oauth_token")) {
oauthToken = params[0].split("=")[1];
} else if (params[1].startsWith("oauth_token")) {
oauthToken = params[1].split("=")[1];
}
if (params[0].startsWith("oauth_verifier")) {
oauthVerifier = params[0].split("=")[1];
} else if (params[1].startsWith("oauth_verifier")) {
oauthVerifier = params[1].split("=")[1];
}
Intent resultIntent = new Intent();
resultIntent.putExtra("oauthToken", oauthToken);
resultIntent.putExtra("oauthVerifier", oauthVerifier);
setResult(RESULT_OK, resultIntent);
finish();
} catch (Exception e)
{
e.printStackTrace();
}
}
}
});
Intent passedIntent = getIntent();
String authUrl = passedIntent.getStringExtra("authUrl");
webview.loadUrl(authUrl);
}
}
activit_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffffff" >
<LinearLayout
android:id="@+id/buttonLayout"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="10dp"
>
<Button
android:id="@+id/connectBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="연결하기"
android:textSize="18dp"
android:textStyle="bold"
android:textColor="#ff000000"
/>
<TextView
android:id="@+id/nameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text=""
android:textSize="18dp"
android:textStyle="bold"
android:textColor="#ff000000"
/>
</LinearLayout>
<org.androidtown.sns.twitapp.StatusListView
android:id="@+id/statusList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/buttonLayout"
android:layout_above="@+id/addLayout"
android:cacheColorHint="#00000000"
android:listSelector="#00000000"
/>
<LinearLayout
android:id="@+id/addLayout"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
>
<Button
android:id="@+id/writeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="글쓰기"
android:textSize="18dp"
android:textStyle="bold"
android:textColor="#ff000000"
/>
<EditText
android:id="@+id/writeInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text=""
android:textSize="18dp"
android:textStyle="bold"
android:textColor="#ff000000"
/>
</LinearLayout>
</RelativeLayout>
listitem.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageView
android:id="@+id/iconItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:layout_gravity="center_vertical"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentRight="true"
>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
>
<TextView
android:id="@+id/dataItem01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff888888"
android:textSize="12dp"
android:textStyle="bold"
/>
<TextView
android:id="@+id/dataItem02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:textColor="#ccf88107"
android:textSize="10dp"
android:textStyle="bold"
android:paddingRight="4dp"
/>
</RelativeLayout>
<TextView
android:id="@+id/dataItem03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#191775"
android:textSize="12dp"
android:padding="4dp"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
twit_login.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffffff"
>
<LinearLayout
android:id="@+id/titleLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="10dp"
>
<TextView
android:id="@+id/noticeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="트위터 로그인을 위해 아래 내용을 확인하세요."
android:textSize="16dp"
android:textStyle="bold"
android:textColor="#ff000000"
android:paddingLeft="10dp"
android:paddingRight="10dp"
/>
</LinearLayout>
<WebView
android:id="@+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="10dp"
android:layout_below="@+id/titleLayout"
/>
</RelativeLayout>
128강
129강
댓글 ( 4)
댓글 남기기