안드로이드

 

 

 

 

 

 

      

 

 

 

메시징 서비스

트위터 로그인 후 트위터 글 보기

등록


https://apps.twitter.com/


=> 페이지 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강

 

 

 

 

 

about author

PHRASE

Level 60  머나먼나라

팔자 도망은 독 안에 들어도 못 한다 , 제가 타고난 운명에 따라야지, 억지로 되는 것이 아니라는 말.

댓글 ( 4)

댓글 남기기

작성