오늘은 심심해서 Android 4.x에 새로 추가된것들에 대해서 보고 있었는데, 그중에 재미난것이 하나 있어서 코딩해볼까?? 하고 eclipse를 열었다.


그런데, 코딩할필요가 없었다.





이유는 아예 AnalogClock view를 지원하고 있다. 좋다!!!! 아무것도 할것 없이 그냥 아래 view 만 추가해주면 모든게 끝난다.


<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" >


    <AnalogClock xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/analog"

    android:layout_width="match_parent"

    android:layout_height="match_parent" >

    </AnalogClock>


</RelativeLayout>


'코딩하고 > Android' 카테고리의 다른 글

DB관리하기 - Provider 사용하기  (0) 2012.11.21
Fragment 다루기 (아주 심플하게..)  (0) 2012.11.15
HttpClient 사용하기  (0) 2012.10.25
File Observer 사용하기  (0) 2012.10.21
ActionBar로 Tab 만들기  (19) 2012.10.19
블로그 이미지

커뉴

이 세상에서 꿈 이상으로 확실한 것을, 인간은 가지고 있는 것일까?

,

자바 표준으로 URL class등을 사용하여 네트워크 리소스를 사용할수도 있지만, 각종 설정들을 조절하고 더 사용하기 쉬운방법이 있는데, 그것이 바로 HttpClient Class를 사용하는 방법이다.


GET, POST 메소드등을 빈번하게 구분해서 사용하고, 각종 http 네트워크 리소스들을 사용자화 해서 개발할 필요가 있다면, URL class를 사용하는 것도 좋지만, HttpClient를 사용하는 방법도 알아두는 것도 권할만하다.


참고로, 내가 참여하고 있는 프로젝트는 HttpClient Class만을 사용하여 각종 데이터 싱크등을 구현하였다.


사용하는 법 자체는 쉽다.


package com.hopeisagoodthing.samplehttpclient;

import java.io.IOException;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {
	private static final String TAG = "MainActivity";
	private static TextView textView = null;
	private static Handler handler = new Handler(){
		public void handleMessage(final Message msg) {			
			textView.setText(Integer.toString((Integer) msg.obj));
		};		
	};

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);	
		textView = (TextView) findViewById(R.id.result_text);
		Thread thread = new Thread(mRunnable);
		thread.start();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.activity_main, menu);
		
		return true;
	}	
	
	private Runnable mRunnable = new Runnable() {
		@Override
		public void run() {
			try {
				final String url = "http://coolkim.tistory.com";
				final HttpGet get = new HttpGet(url);
				final HttpClient httpClient = getHttpClient();
				final HttpResponse httpResponse = httpClient.execute(get);
				handleResponse(httpResponse);
			} catch (ClientProtocolException e) {
				Log.e(TAG, "ERROR : ClientProtocolException");

			} catch (IOException e) {
				Log.e(TAG, "ERROR :  IOException");
			}

		}
	};

	private HttpClient getHttpClient() {
		HttpClient httpClient = null;
		try {
			final HttpParams params = new BasicHttpParams();

			// PARAMS
			HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
			HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
			HttpConnectionParams.setConnectionTimeout(params, 1000 * 30); // 30s timeout.
			HttpConnectionParams.setSoTimeout(params, 1000 * 30); // 30s timeout.
			HttpConnectionParams.setSocketBufferSize(params, 512 * 1024);
			HttpConnectionParams.setStaleCheckingEnabled(params, false);
			HttpClientParams.setRedirecting(params, false);
			params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);

			// SCHEME
			final SchemeRegistry registry = new SchemeRegistry();
			registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
			registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

			final ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

			httpClient = new DefaultHttpClient(ccm, params);
		} catch (Exception e) {
			httpClient = new DefaultHttpClient();
		}

		return httpClient;
	}
	
	private void handleResponse(final HttpResponse httpResponse) {
		final int status = httpResponse.getStatusLine().getStatusCode();
		
		try {			
			Message msg = handler.obtainMessage();
			msg.obj = status;
			handler.sendMessage(msg);			
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}	
}


블로그 이미지

커뉴

이 세상에서 꿈 이상으로 확실한 것을, 인간은 가지고 있는 것일까?

,

특정한 폴더들의 파일 변경을 모니터링을 해야 하는 경우가 있다면, Android에서는 File Observer를 사용할수 있다.


단말이 켜져있는 상태에서만 해당 변경에 대한 이벤트르 전달 받을수 있기 때문에, 단말이 꺼져있거나, 모니터를 하지 않다가 다시 모니터를 시작할 경우에는, 


모니터를 하고 있단 디렉토리의 변경사항을 따로 추적 관리하는 방법도 준비되어야 한다. (해쉬값을 뽑아둔다던가... 하는 방법)



package com.hopeisagoodthing.fileobserver;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileObserver;
import android.util.Log;

public class FileObserverActivity extends Activity {
	private FileObserver observer;
	private static final String pathToWatch = Environment.getExternalStorageDirectory().toString();
	private static final String TAG = "FileObserverActivity";

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

		observer = new FileObserver(pathToWatch) {

			@Override
			public void onEvent(int event, String path) {

				Log.d(TAG, "File Changed --> Path = " + pathToWatch +"/"+ path);
				Log.d(TAG, "File Changed --> Event = " + event);
			}
		};
		observer.startWatching();
	}
}
블로그 이미지

커뉴

이 세상에서 꿈 이상으로 확실한 것을, 인간은 가지고 있는 것일까?

,

Android에서 Action Bar를 이용하여 아래와 같은 탭 액티비티를 만들수 있다.

물론 이전에도 Tab Host등을 이용하고 여러개의 액티비티들을 이용해서 탭을 만들수 있었지만, 지금 처럼 아주 간결하게 만들기가 쉽지는 않았다.


액티비티 하나에 Fragment들을 탭의 개수 만큼 구현하고, 그리고 가장 중요한 ActionBar 모드를 ActionBar.NAVIGATION_MODE_TABS로 설정해주면 간단하게 탭을 구현할수 있다.





너무 간단하니까.. 바로 소스를 보고 따로 구현하도록 하면 될듯하다.

 1. 탭들을 등록하고 관리하는 Activity 하나.

 2. 탭들을 표현할 Fragment 들이 탭의 개수만큼(위에서는 3개)

 3. TabListener 하나.




FragmentTabs Activity.

package com.hopeisagoodthing.actionbar.tab;

import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;

public class FragmentTabs extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		final ActionBar actionBar = getActionBar();
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

		actionBar.addTab(actionBar
				.newTab()
				.setText("Tab1")
				.setTabListener(
						new TabListener<FragmentTab1>(this, "tab1",
								FragmentTab1.class)));
		actionBar.addTab(actionBar
				.newTab()
				.setText("Tab2")
				.setTabListener(
						new TabListener<FragmentTab2>(this, "tab3",
								FragmentTab2.class)));
		actionBar.addTab(actionBar
				.newTab()
				.setText("Tab3")
				.setTabListener(
						new TabListener<FragmentTab3>(this, "tab3",
								FragmentTab3.class)));

		if (savedInstanceState != null) {
			actionBar.setSelectedNavigationItem(savedInstanceState.getInt(
					"selectedTab", 0));
		}
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putInt("selectedTab", getActionBar()
				.getSelectedNavigationIndex());
	}
}



FragmentTab1

package com.hopeisagoodthing.actionbar.tab;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FragmentTab1 extends Fragment {
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.simple, container, false);
		View tv = v.findViewById(R.id.text);
		((TextView) tv).setText("coolkim.tistory.com");
		return v;
	}
}



FragmentTab2

package com.hopeisagoodthing.actionbar.tab;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FragmentTab2 extends Fragment {
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.simple, container, false);
		View tv = v.findViewById(R.id.text);
		((TextView) tv).setText("Hope is a good thing.");
		return v;
	}
}



FragmentTab3

package com.hopeisagoodthing.actionbar.tab;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FragmentTab3 extends Fragment {
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.simple, container, false);
		View tv = v.findViewById(R.id.text);
		((TextView) tv).setText("Simple Tab");
		return v;
	}
}



TabListener

package com.hopeisagoodthing.actionbar.tab;

import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ActionBar.Tab;
import android.widget.Toast;

public class TabListener<T extends Fragment> implements ActionBar.TabListener {

	private final Activity mActivity;
	private final String mTag;
	private final Class<T> mClass;
	private Fragment mFragment;

	public TabListener(Activity activity, String tag, Class<T> clz) {
		mActivity = activity;
		mTag = tag;
		mClass = clz;

		mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
		if (mFragment != null && !mFragment.isDetached()) {
			FragmentTransaction fragmentTransaction = mActivity
					.getFragmentManager().beginTransaction();
			fragmentTransaction.detach(mFragment);
			fragmentTransaction.commit();
		}
	}

	public void onTabSelected(Tab tab, FragmentTransaction fragmentTransaction) {
		if (mFragment == null) {
			mFragment = Fragment.instantiate(mActivity, mClass.getName(), null);
			fragmentTransaction.add(android.R.id.content, mFragment, mTag);
		} else {
			fragmentTransaction.attach(mFragment);
		}
	}

	public void onTabUnselected(Tab tab, FragmentTransaction fragmentTransaction) {
		if (mFragment != null) {
			fragmentTransaction.detach(mFragment);
		}
	}

	public void onTabReselected(Tab tab, FragmentTransaction fragmentTransaction) {
		Toast.makeText(mActivity, "onTabReselected!", Toast.LENGTH_SHORT)
				.show();
	}
}

'코딩하고 > Android' 카테고리의 다른 글

HttpClient 사용하기  (0) 2012.10.25
File Observer 사용하기  (0) 2012.10.21
App에서 SystemProperties 가지고 오는 방법  (1) 2012.10.18
검색 API 사용하기 - twitter api  (0) 2012.10.05
검색 API 사용하기 - google api  (0) 2012.10.05
블로그 이미지

커뉴

이 세상에서 꿈 이상으로 확실한 것을, 인간은 가지고 있는 것일까?

,

오늘은 Naver에서 제공하는 검색 api를 사용해보자.


네이버는 다른 검색 엔진과는 다르게 XML 로만 결과를 제공해주고 있는것 같다, 개인적으로 JSON 사용하는 것을 좋아하는데, Naver에 실망했다 .ㅠ.ㅠ

모든 클래스를 다 똑같이 만들려고 했는데 ... XML파서를 넣어줘야 .....


아래 코드도 크게 다르지 않게 그대로 필요한 부분만 가져다 쓰면 되고, 쿼리 결과를 처리하는 부분이 xml파싱하는 부분이라서, 가장 간단한 방법으로 파싱했다.


http://dev.naver.com/openapi/ --> 네이버 api 사이트

http://dev.naver.com/openapi/apis/search/rank --> 검색 api만 사용하려면 여기로..


네이버도 api를 사용하기 위해서는 개발자의 api key를 발급받아야  한다.


검색 api등등을 사용할때는 사실 많은 공부가 필요하지 않은것 같다, 아래 샘플 코드를 가지고 가서 필요한 부분만 검색하기만 하면 되니까.




package com.hopeisagoodthing.searchtool;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import android.util.Log;


public class NaverSearch implements ISearch
{
	private static final String TAG = "NaverSearch";
	private static final String BASE_URL = "http://openapi.naver.com/search?";
	private static final String API_KEY="여기에 역시 자신의 api key를 넣어준다.";
	private static final String[] TARGETS = new String[]{"webkr","news","blog","cafearticle"};
	private static final int START = 1;
	private static final class PARAM{
		private static final String API_KEY = "key=";	// always start with this parameter!!!
		private static final String QUERY = "&query=";
		private static final String TARGET = "&target=";
		private static final String START = "&start=";
		private static final String DISPLAY = "&display=";
	}	
	
	private final List<String> mAnalyzedList = new ArrayList<String>();
	
	
	
	@Override
	public List<String> getAnalyze(final String query, final int resultSize, final IAnalyzer analyzer) {
		boolean inDesc = false;	
		String desc = null;
		mAnalyzedList.clear();
		
		for(String target : TARGETS)
		{
			URL url = null;
			try {
				url = new URL(	BASE_URL + 
									PARAM.API_KEY+API_KEY + 
									PARAM.QUERY + URLEncoder.encode(query, "UTF-8") +
									PARAM.TARGET+ target+
									PARAM.START+START+
									PARAM.DISPLAY+resultSize);
				
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}		
			
			try {			
				final XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance();
				final XmlPullParser parser = parserCreator.newPullParser();
				parser.setInput(url.openStream(), null);
				
				int parserEvent = parser.getEventType();
				
				Log.e(TAG,"NAVER Result START============================================================");
				while (parserEvent != XmlPullParser.END_DOCUMENT) {
					switch (parserEvent) {
					case XmlPullParser.START_TAG:
						if (parser.getName().equals("description")) {
							inDesc = true;
						}
						
						break;

					case XmlPullParser.TEXT:
						if (inDesc) {
							desc = parser.getText();
							inDesc = false;
							analyzer.analyze(desc, mAnalyzedList);
						}
						
						break;
					case XmlPullParser.END_TAG:				
						break;
					}
					try {
						parserEvent = parser.next();
					} catch (XmlPullParserException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				Log.e(TAG,"NAVER Result END============================================================");
			} catch (XmlPullParserException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return mAnalyzedList;		
	}	
}
블로그 이미지

커뉴

이 세상에서 꿈 이상으로 확실한 것을, 인간은 가지고 있는 것일까?

,