본문 바로가기

android/Twitter

Android app에서 Twitter 연동하기 (개선-로그인을 한번만 하자)


http://jeehun.egloos.com/4024788
상단에 원본 링크 입니다. 아래 포스트는 제가 작성한 것이 아니고 egloos.com에 접속되지 않는 분들은 위한 글임을 미리 밝혀 둡니다.
너무 잘 작성된 예제라서 가져옴을 다시 알려드립니다.


안녕하세요 지헌입니다.
트위터 로그인 유지에 대해 몇몇 분들이 질문을 해주셔서
이전의 TwitterCon 앱을 수정해보도록 하겠습니다.
강렬눈썹님의 코멘트를 약간 참고 했습니다만 방식은 약간 틀립니다.

수정은 기존의 TwitterCon2.java 만 수정하도록 하겠습니다.
아.. Util.java 클래스가 하나 추가되는군요

먼저 Util.java 클래스를 만듭니다.
쉐어드 프레퍼런스에 값을 저장하고 읽어오는 메서드를 만듭니다.
****************************** Util.java *********************************
package com.android.twittercon;

import android.app.Activity;
import android.content.SharedPreferences;

public class Util
{
// 전체 어플에 공용으로 적용되는 SharedPreferences에 Key, Value로 값을 저장한다. Value는 String이다.
public static void setAppPreferences(Activity context, String key, String value)
{
SharedPreferences pref = null;
pref = context.getSharedPreferences(C.LOG_TAG, 0);
SharedPreferences.Editor prefEditor = pref.edit();
prefEditor.putString(key, value);

prefEditor.commit();
}

// 전체 어플에 공용으로 적용되는 SharedPreferences에서 String 값을 가져온다.
public static String getAppPreferences(Activity context, String key)
{
String returnValue = null;

SharedPreferences pref = null;
pref = context.getSharedPreferences(C.LOG_TAG, 0);

returnValue = pref.getString(key, "");

return returnValue;
}
}
************************************************************************

다음은 C.java 파일을 수정합니다.
*******************************C.java***********************************
package com.android.twittercon;

public class C
{
public static final String LOG_TAG = "TwitterCon";
public static final String TWITTER_API_KEY = "트위터 API Key";
public static final String TWITPIC_API_KEY = "트윗픽 API Key";
public static final String TWITTER_CONSUMER_KEY = "트위터 컨슈머 키";
public static final String TWITTER_CONSUMER_SECRET = "트위터 컨슈머 시크릿 키;
public static final String TWITTER_CALLBACK_URL = "http://m.daum.net";
public static final String MOVE_TWITTER_LOGIN = "com.android.twittercon.TWITTER_LOGIN";
public static final int TWITTER_LOGIN_CODE = 10;
public static final String TWITTER_LOGOUT_URL = "http://api.twitter.com/logout";
public static final String TWITTER_ACCESS_TOKEN = "twitter_access_token";
public static final String TWITTER_ACCESS_TOKEN_SECRET = "twitter_access_token_secret";

public static boolean D = true;
}
************************************************************************

다음은 TwitterCon2.java 파일을 수정합니다.
login() 부분과 onActivityResult() 부분만 수정하면 됩니다.
login은 다음과 같이 수정합니다.
login()이 원래 수행하고있던 역할은 트위터 webview를 통해 로그인을 하고
그 결과를 받아서 (onActvityResult) mAccessToken 객체를 만들어 주는 것이었습니다.
우리는 이미 한번 로그인 했을 경우 쉐어드 프레퍼런스에 로그인 할때 받아온
액세스 토큰과 액세스 토큰 시크릿 키를 저장해 놓을 것이기 때문에
로그인은 아래와 같이 쉐어드 프레퍼런스에서 토큰과 시크릿을 가져와
있으면 이것을 이용해 mAccessToken 객체를 생성시켜 줍니다.
그러면 나중에 글을 쓰는 메서드는 수정할 필요 없이 동일한 방식으로
처리가 가능합니다.
private void login()
{
try
{
String accessToken = Util.getAppPreferences(this, C.TWITTER_ACCESS_TOKEN);
String accessTokenSecret = Util.getAppPreferences(this, C.TWITTER_ACCESS_TOKEN_SECRET);

if (accessToken != null && !"".equals(accessToken) && accessTokenSecret != null && !"".equals(accessTokenSecret))
{
mAccessToken = new AccessToken(accessToken, accessTokenSecret);

Log.v(C.LOG_TAG, "accessToken : " + mAccessToken.getToken());
Log.v(C.LOG_TAG, "accessTokenSecret : " + mAccessToken.getTokenSecret());
}
else
{
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey(C.TWITTER_CONSUMER_KEY);
cb.setOAuthConsumerSecret(C.TWITTER_CONSUMER_SECRET);
TwitterFactory factory = new TwitterFactory(cb.build());
mTwitter = factory.getInstance();
mRqToken = mTwitter.getOAuthRequestToken(C.TWITTER_CALLBACK_URL);
Log.v(C.LOG_TAG, "AuthorizationURL >>>>>>>>>>>>>>> " + mRqToken.getAuthorizationURL());

Intent intent = new Intent(this, TwitterLogin.class);
intent.putExtra("auth_url", mRqToken.getAuthorizationURL());
startActivityForResult(intent, C.TWITTER_LOGIN_CODE);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}

그리고 onActvityResult 메서드에서도 로그인 성공후 쉐어드 프레퍼런스에
액세스 토큰과 토큰 시크릿을 저장하는 처리를 해줍니다.
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);

// 액티비티가 정상적으로 종료되었을 경우
if(resultCode == RESULT_OK)
{
if (requestCode == C.TWITTER_LOGIN_CODE)
{
try
{
mAccessToken = mTwitter.getOAuthAccessToken(mRqToken, data.getStringExtra("oauth_verifier"));

Log.v(C.LOG_TAG, "Twitter Access Token : " + mAccessToken.getToken());
Log.v(C.LOG_TAG, "Twitter Access Token Secret : " + mAccessToken.getTokenSecret());

Util.setAppPreferences(this, C.TWITTER_ACCESS_TOKEN, mAccessToken.getToken());
Util.setAppPreferences(this, C.TWITTER_ACCESS_TOKEN_SECRET, mAccessToken.getTokenSecret());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}

TwitterCon2.java 의 전체 소스는 다음과 같습니다.
************************* TwitterCon2 ****************************
package com.android.twittercon;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import twitter4j.auth.AccessToken;
import twitter4j.auth.OAuthAuthorization;
import twitter4j.auth.RequestToken;
import twitter4j.media.ImageUpload;
import twitter4j.media.ImageUploadFactory;
import twitter4j.media.MediaProvider;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class TwitterCon2 extends Activity implements View.OnClickListener
{
private Twitter mTwitter;
private RequestToken mRqToken;
private AccessToken mAccessToken;
private Button mBtnLogin, mBtnFeed, mBtnLogout;
private EditText mEtContent;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

mEtContent = (EditText) findViewById(R.id.etContent);

mBtnLogin = (Button) findViewById(R.id.btnLogin);
mBtnFeed = (Button) findViewById(R.id.btnFeed);
mBtnLogout = (Button) findViewById(R.id.btnLogout);

mBtnLogin.setOnClickListener(this);
mBtnFeed.setOnClickListener(this);
mBtnLogout.setOnClickListener(this);
}

// 버튼 클릭 이벤트 처리
@Override
public void onClick(View v)
{
switch(v.getId())
{
case R.id.btnLogin: // Twitter login
login();
break;
case R.id.btnFeed: // Twitter에 글쓰기
write();
break;
case R.id.btnLogout: // Twitter logout
logout();
break;
default:
break;
}
}

private void login()
{
try
{
String accessToken = Util.getAppPreferences(this, C.TWITTER_ACCESS_TOKEN);
String accessTokenSecret = Util.getAppPreferences(this, C.TWITTER_ACCESS_TOKEN_SECRET);

if (accessToken != null && !"".equals(accessToken) && accessTokenSecret != null && !"".equals(accessTokenSecret))
{
mAccessToken = new AccessToken(accessToken, accessTokenSecret);

Log.v(C.LOG_TAG, "accessToken : " + mAccessToken.getToken());
Log.v(C.LOG_TAG, "accessTokenSecret : " + mAccessToken.getTokenSecret());
}
else
{
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true);
cb.setOAuthConsumerKey(C.TWITTER_CONSUMER_KEY);
cb.setOAuthConsumerSecret(C.TWITTER_CONSUMER_SECRET);
TwitterFactory factory = new TwitterFactory(cb.build());
mTwitter = factory.getInstance();
mRqToken = mTwitter.getOAuthRequestToken(C.TWITTER_CALLBACK_URL);
Log.v(C.LOG_TAG, "AuthorizationURL >>>>>>>>>>>>>>> " + mRqToken.getAuthorizationURL());

Intent intent = new Intent(this, TwitterLogin.class);
intent.putExtra("auth_url", mRqToken.getAuthorizationURL());
startActivityForResult(intent, C.TWITTER_LOGIN_CODE);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}

private Configuration getConfiguration(String apiKey)
{
return new ConfigurationBuilder().setMediaProviderAPIKey(apiKey).build();
}

private void write()
{
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "example.jpg";
InputStream is = null;

try
{
if (new File(path + File.separator + fileName).exists())
is = new FileInputStream(path + File.separator + fileName);
else
is = null;


ConfigurationBuilder cb = new ConfigurationBuilder();
String oAuthAccessToken = mAccessToken.getToken();
String oAuthAccessTokenSecret = mAccessToken.getTokenSecret();
String oAuthConsumerKey = C.TWITTER_CONSUMER_KEY;
String oAuthConsumerSecret = C.TWITTER_CONSUMER_SECRET;
cb.setOAuthAccessToken(oAuthAccessToken);
cb.setOAuthAccessTokenSecret(oAuthAccessTokenSecret);
cb.setOAuthConsumerKey(oAuthConsumerKey);
cb.setOAuthConsumerSecret(oAuthConsumerSecret);
Configuration config = cb.build();
OAuthAuthorization auth = new OAuthAuthorization(config);

TwitterFactory tFactory = new TwitterFactory(config);
Twitter twitter = tFactory.getInstance();
ImageUploadFactory iFactory = new ImageUploadFactory(getConfiguration(C.TWITPIC_API_KEY));
ImageUpload upload = iFactory.getInstance(MediaProvider.TWITPIC, auth);

if (is != null)
{
String strResult = upload.upload("example.jpg", is, mEtContent.getText().toString());
twitter.updateStatus(mEtContent.getText().toString() + " " + strResult);
}
else
twitter.updateStatus(mEtContent.getText().toString());
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
is.close();
}
catch (Exception e)
{}
}
}

private void logout()
{
Intent intent = new Intent(C.MOVE_TWITTER_LOGIN);
intent.putExtra("auth_url", C.TWITTER_LOGOUT_URL);
startActivity(intent);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);

// 액티비티가 정상적으로 종료되었을 경우
if(resultCode == RESULT_OK)
{
if (requestCode == C.TWITTER_LOGIN_CODE)
{
try
{
mAccessToken = mTwitter.getOAuthAccessToken(mRqToken, data.getStringExtra("oauth_verifier"));

Log.v(C.LOG_TAG, "Twitter Access Token : " + mAccessToken.getToken());
Log.v(C.LOG_TAG, "Twitter Access Token Secret : " + mAccessToken.getTokenSecret());

Util.setAppPreferences(this, C.TWITTER_ACCESS_TOKEN, mAccessToken.getToken());
Util.setAppPreferences(this, C.TWITTER_ACCESS_TOKEN_SECRET, mAccessToken.getTokenSecret());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
}
******************************************************************

이상과 같이 코딩하고 실행시키면 처음에는 트위터 로그인 창이 뜨지만
그 다음부터는 저장된 액세스 토큰과 토큰 시크릿을 가지고 액세스 토큰 객체를 만들어서
글을 쓰는데 사용할 수 있게 됩니다.

그럼 이상으로 마치겠습니다.