<Android> Volley 이미지 불러오기 예제

Android Volley ImageLoader

Volley uses ImageLoader to load images from network, and also to cache them into your Android phone’s in-memory cache by using the LruCache class. A good approach would be to use Android ImageLoader in a singleton pattern, as same cache should be used throughout the application. Also if used in a singleton pattern your cache would not be activity dependent. Hence whenever you close and open the activity, your images could be picked up from the cache, saving network requests. Now this brings up a question, how to make this volley singleton class? please have a look at the code below:

In the above class you may see that a CustomVolleyRequestQueue is set up which can return an object of ImageLoader. The class above also creates an ImageCache which works with normal volley cache, but only caching images for requests. Please note here: I just modified the singleton class from my previous Volley Example. Therefore as a whole, the above class can be used to make any type of Android volley requests, be it a JsonRequest, ImageRequest, or just a simple StringRequest.

Android Volley NetworkImageView

A new view introduced with Android volley is NetworkImageView. As a matter of fact this view replaces the standard ImageView, when comes to the usage of volley. Android Volley NetworkImageView is designed in such a way that it creates an image request, sends it and even displays the image, after it is downloaded from the URL. Also it cancels the request on its own if it is detached from the view hierarchy. Hence no need to handle the request cancellations with Volley NetworkImageView. Have a look at the layout for this Android Volley ImageLoader and NetworkImageView Example, it just includes a NetworkImageView instead of ImageView:

Next lets have a look at the code for the main activity class:

As you may see in the above class I used an instance of CustomVolleyRequestQueue to get the volley ImageLoader object. Further I just specified the URL through setImageUrl method of NetworkImageView. This handles all the functionality by itself.

Want to display images in a ListView using volley?

If you need to display images in a ListView just use the setImageUrl method of NetworkImageView in the getView method of your adapter. This will handle all your image requests automatically. Just a reminder, don’t forget to use the  NetworkImageView instead of normal ImageView.

Screenshot of Android Volley ImageLoader Example:
Android Volley NetworkImageView

 

 

 

 

 

출처:http://www.truiton.com/2015/03/android-volley-imageloader-networkimageview-example/


1. AndroidManifest.xml 에 권한 추가하기


<uses-permission
  android:name="android.permission.CAMERA" />
<uses-permission
  android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


2. main.xml 레이아웃 만들기


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<Button
android:id="@+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="이미지 가져오기"
/>
<ImageView
android:id="@+id/image"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_gravity="center"
android:layout_margin="50dp"
android:background="#eee"
/>
</LinearLayout>


3. 소스 코드 작성


package pe.kr.theeye.cameracrop;

import java.io.File;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class CameraCropActivity extends Activity implements OnClickListener
{
  private static final int PICK_FROM_CAMERA = 0;
  private static final int PICK_FROM_ALBUM = 1;
  private static final int CROP_FROM_CAMERA = 2;

  private Uri mImageCaptureUri;
  private ImageView mPhotoImageView;
  private Button mButton;

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

    mButton = (Button) findViewById(R.id.button);
    mPhotoImageView = (ImageView) findViewById(R.id.image);

    mButton.setOnClickListener(this);
  }

  /**
   * 카메라에서 이미지 가져오기
   */
  private void doTakePhotoAction()
  {
    /*
     * 참고 해볼곳
     * http://2009.hfoss.org/Tutorial:Camera_and_Gallery_Demo
     * http://stackoverflow.com/questions/1050297/how-to-get-the-url-of-the-captured-image
     * http://www.damonkohler.com/2009/02/android-recipes.html
     * http://www.firstclown.us/tag/android/
     */

    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    // 임시로 사용할 파일의 경로를 생성
    String url = "tmp_" + String.valueOf(System.currentTimeMillis()) + ".jpg";
    mImageCaptureUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), url));

    intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
    // 특정기기에서 사진을 저장못하는 문제가 있어 다음을 주석처리 합니다.
    //intent.putExtra("return-data", true);
    startActivityForResult(intent, PICK_FROM_CAMERA);
  }

  /**
   * 앨범에서 이미지 가져오기
   */
  private void doTakeAlbumAction()
  {
    // 앨범 호출
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
    startActivityForResult(intent, PICK_FROM_ALBUM);
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data)
  {
    if(resultCode != RESULT_OK)
    {
      return;
    }

    switch(requestCode)
    {
      case CROP_FROM_CAMERA:
      {
        // 크롭이 된 이후의 이미지를 넘겨 받습니다.
        // 이미지뷰에 이미지를 보여준다거나 부가적인 작업 이후에
        // 임시 파일을 삭제합니다.
        final Bundle extras = data.getExtras();

        if(extras != null)
        {
          Bitmap photo = extras.getParcelable("data");
          mPhotoImageView.setImageBitmap(photo);
        }

        // 임시 파일 삭제
        File f = new File(mImageCaptureUri.getPath());
        if(f.exists())
        {
          f.delete();
        }

        break;
      }

      case PICK_FROM_ALBUM:
      {
        // 이후의 처리가 카메라와 같으므로 일단  break없이 진행합니다.
        // 실제 코드에서는 좀더 합리적인 방법을 선택하시기 바랍니다.

        mImageCaptureUri = data.getData();
      }

      case PICK_FROM_CAMERA:
      {
        // 이미지를 가져온 이후의 리사이즈할 이미지 크기를 결정합니다.
        // 이후에 이미지 크롭 어플리케이션을 호출하게 됩니다.

        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(mImageCaptureUri, "image/*");

        intent.putExtra("outputX", 90);
        intent.putExtra("outputY", 90);
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("scale", true);
        intent.putExtra("return-data", true);
        startActivityForResult(intent, CROP_FROM_CAMERA);

        break;
      }
    }
  }

  @Override
  public void onClick(View v)
  {
    DialogInterface.OnClickListener cameraListener = new DialogInterface.OnClickListener()
    {
      @Override
      public void onClick(DialogInterface dialog, int which)
      {
        doTakePhotoAction();
      }
    };

    DialogInterface.OnClickListener albumListener = new DialogInterface.OnClickListener()
    {
      @Override
      public void onClick(DialogInterface dialog, int which)
      {
        doTakeAlbumAction();
      }
    };

    DialogInterface.OnClickListener cancelListener = new DialogInterface.OnClickListener()
    {
      @Override
      public void onClick(DialogInterface dialog, int which)
      {
        dialog.dismiss();
      }
    };

    new AlertDialog.Builder(this)
      .setTitle("업로드할 이미지 선택")
      .setPositiveButton("사진촬영", cameraListener)
      .setNeutralButton("앨범선택", albumListener)
      .setNegativeButton("취소", cancelListener)
      .show();
  }}


테스트 이미지는 생략하겠습니다. 위의 소스로 충분히 좋은 설명이 될 수 있을것이라 생각합니다. 두번의 Intent 호출을 통해 이미지를 촬영하고 크롭을 하는 과정을 거치게 됩니다. 테스트 해보니 잘 되는군요.

참고 : http://stackoverflow.com/questions/1973359/android-crop-an-image-after-taking-it-with-camera-with-a-fixed-aspect-ratio

출처:http://theeye.pe.kr/archives/1285

원문: http://stackoverflow.com/questions/31954437/cant-type-into-android-studios-built-in-terminal

 

 

1. 터미널 열기

   다들 아시겠지만, 윈도우 8부터 윈도우의 검색기능이 강화되었습니다. 단축키는 window+q 를 누르시면 바로 검색 할 수 있습니다.

   이 검색창에서 cmd입력하여 cmd창을 열어줍니다.







2.속성

  cmd창의 제목표시줄에서 마우스 우클릭을 하면 다음과 같이 속성(P)가 보입니다.

  속성창으로 들어가 줍니다.






3. 레거시 콘솔 체크

  여기에서 레거시 콘솔을 체크해줍니다. 다시 실행해야 한다는데 저 말은 윈도우 재 부팅이 아닌 cmd창을 다시 시작 하라는 말입니다.







4. 안드로이드 스튜디오

  이제 안드로이드 스튜디오에서 신나게 타이핑을 합니다.

  참고: 만약 안되실 경우 X를 눌러 터미널 종료 후 다시 실행하시면됩니다.


참조:http://storyofdream.tistory.com/129

우체국 오픈API를 이용하여 우편번호를 얻어오는 안드로이드 예제입니다.

 먼저 우체국 오픈API를 사용하기 위해 아래 사이트에서 인증키를 발급받읍시다!

http://biz.epost.go.kr/customCenter/custom/custom_9.jsp?subGubun=sub_3&subGubun_1=cum_17&gubun=m07 

다음으로 안드로이드 프로젝트를 생성합니다.

이 때, AndroidManifest.xml 에 다음과 같이 권한을 설정해둡시다! (인터넷을 사용해야 하니까..!)

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>

 그 다음 주소를 사용자로부터 입력받고

우체국 오픈API로부터 받아온 우편주소를 출력하는 액티비티는 다음과 같이 구성하였습니다.

 

activity_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}">

<TextView
android:id="@+id/textPost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="주소입력 예)정릉동" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<EditText
android:id="@+id/addressedit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:ems="10">

<requestFocus />
</EditText>

<Button
android:id="@+id/btnsearch"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="검색" />
</LinearLayout>

<ListView
android:id="@+id/addresslist"
android:layout_width="match_parent"
android:layout_height="wrap_content"></ListView>
</LinearLayout>

 

마지막으로 메인액티비티 코드입니다.

 

우체국 오픈API로부터 받아온 우편주소는 XML형태이기 때문에

Dom을 사용하여 쉽게 정보를 뽑아내고 있습니다.

 

안드로이드는 기본적으로 네트워크 통신은 스레드에서만 하기를 권장하므로 

AsyncTask를 사용하여 구현하였습니다. 

 

MainActivity.java

package worldpay.com.post;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

import org.apache.http.HttpResponse;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class MainActivity extends Activity {

//우체국 오픈api인증키
private String key = "우체국 API키";
private TextView addressEdit;
private Button searchBtn;
private ListView addressListView;
private ArrayAdapter<String> addressListAdapter;
//사용자가 입력한 주소
private String putAddress;
//우체국으로부터 반환 받은 우편주소 리스트
private ArrayList<String> addressSearchResultArr = new ArrayList<>();


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

addressEdit = (EditText) findViewById(R.id.addressedit);
searchBtn = (Button) findViewById(R.id.btnsearch);
addressListView = (ListView) findViewById(R.id.addresslist);
searchBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

getAddress(addressEdit.getText().toString());
}
});


}

private void getAddress(String kAddress) {
putAddress = kAddress;
new GetAddressDataTask().execute();
}

private class GetAddressDataTask extends AsyncTask<String, Void, HttpResponse> {
@Override
protected HttpResponse doInBackground(String... urls) {
HttpResponse response = null;
final String apiurl = "http://biz.epost.go.kr/KpostPortal/openapi";
ArrayList<String> addressInfo = new ArrayList<String>();
HttpURLConnection conn = null;
try {
StringBuffer sb = new StringBuffer(3);
sb.append(apiurl);
sb.append("?regkey=" + key + "&target=post&query=");
sb.append(URLEncoder.encode(putAddress, "EUC-KR"));
String query = sb.toString();
URL url = new URL(query);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("accept-language", "ko");
DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
byte[] bytes = new byte[4096];
InputStream in = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (true) {
int red = in.read(bytes);
if (red < 0) break;
baos.write(bytes, 0, red);
}
String xmlData = baos.toString("utf-8");
baos.close();
in.close();
conn.disconnect();
Document doc = docBuilder.parse(new InputSource(new StringReader(xmlData)));
Element el = (Element) doc.getElementsByTagName("itemlist").item(0);
for (int i = 0; i < ((Node) el).getChildNodes().getLength(); i++) {
Node node = ((Node) el).getChildNodes().item(i);
if (!node.getNodeName().equals("item")) {
continue;
}
String address = node.getChildNodes().item(1).getFirstChild().getNodeValue();
String post = node.getChildNodes().item(3).getFirstChild().getNodeValue();
Log.w("jaeha", "address = " + address);
addressInfo.add(address + "\n우편번호:" + post.substring(0, 3) + "-" + post.substring(3));
}
addressSearchResultArr = addressInfo;
publishProgress();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null) conn.disconnect();
} catch (Exception e) {
}
}
return response;
}

@Override
protected void onProgressUpdate(Void... values) {

//TODO Auto-generated method stub

super.onProgressUpdate(values);
String[] addressStrArray = new String[addressSearchResultArr.size()];
addressStrArray = addressSearchResultArr.toArray(addressStrArray);
addressListAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, addressStrArray);
addressListView.setAdapter(addressListAdapter);
}
}
}

Gradle 설정을 SDK 23으로 올리고 빌드를 하고 나니 첫번째 에러가  org.apache.http 를 찾을수 없다는 에러입니다. 

마시멜로(안드로이드 6.0)에는 더 이상 org.apache.http 모듈이 포함되지 않습니다. 필자의경우에는 전체 소스중에 딱 한 모듈에서 apache http 모듈을 사용하고 있어서 실제로는 HttpURLConnection으로 변경하는 작업으로 대응했습니다.


9월 Google Developers Summit에서 들었지만 역시 격어보니 앞으로 마시멜로 대응할 걱정이 샘솟는군요...

다행히도 안드로이드 M 오픈 테스트 랩에 참여해서 테스트를 할 수 있었는데 레거시모드로 동작했을때 필자의 앱들은 특별한 문제를 일으키지 않았습니다....만, 사용자가 임의로 퍼미션을 날려버리게되면 더 이상 앱이 진행되지 않는 상황이 발생하긴 했습니다. SDK 23 에뮬레이터 이미지를 이용해서라도 테스트해보시길 추천드립니다.



HOW?

하지만 구글님은 역시 해결책을 제공해 주고 있습니다. 가장 간단한 방법은 "org.apache.http.legacy" 라이브러리를 추가하면 됩니다. 실행하려는 모듈의 build.gradle 파일을 열고 아래의 이미지 처럼 한줄만 추가해주면 됩니다.



 useLibrary 'org.apache.http.legacy'


빌드는 성공했지만 아래 그림처럼 아직도 실제 소스에서는 라이브러리 클래스를 찾지 못한다고 에러가 보입니다.


사실 이상태에서 바로 빌드를하면 정상적으로 빌드가 되지만 안드로이드 스튜디오의 구문해석기가 에러를 뿜었기 때문에

dependencies에 아래처럼 라이브러리를 추가합니다.

*이 부분은 gradle wrapper가 버전업되거나 android studio가 업데이트 되면 생략해도 될 것으로 보입니다.

이 과정을 생략한다고 해도 실제로 빌드할때 문제가 발생하지는 않습니다.

(필자는 gradle 1.3.0과 안드로이드 스튜디오 1.4 베타버전을 사용중입니다.)

dependencies {
provided 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.

http.client:4.1.2'
}

지도 서비스 이용시 GPS 설정을 하지 않으면 현재 위치 기능을 이용할 수 없다.

앱 실행시 GPS 설정이 되어 있지 않으면 설정 화면으로 이동하게 해주는 코드..

해당 함수를 원하는 위치에서 콜 해주면 된다.

앱에서 자동으로 설정해주면 더 좋겠지만 개인정보 때문에 구글에서 막아둔 것 같다

//GPS 설정 체크
   private boolean chkGpsService() {
    
    String gps = android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
      
    Log.d(gps, "aaaa");  
    
    if (!(gps.matches(".*gps.*") && gps.matches(".*network.*"))) {
   
     // GPS OFF 일때 Dialog 표시 
     AlertDialog.Builder gsDialog = new AlertDialog.Builder(this); 
     gsDialog.setTitle("위치 서비스 설정");   
     gsDialog.setMessage("무선 네트워크 사용, GPS 위성 사용을 모두 체크하셔야 정확한 위치 서비스가 가능합니다.\n위치 서비스 기능을 설정하시겠습니까?"); 
     gsDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int which) { 
       // GPS설정 화면으로 이동 
       Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); 
       intent.addCategory(Intent.CATEGORY_DEFAULT); 
       startActivity(intent); 
      } 
     })
     .setNegativeButton("NO", new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog, int which) {
       return;
      }
     }).create().show();
     return false;
    
    } else { 
     return true; 
    } 
   }

서브 액티비티에서 메인 액티비티로 데이터 전송하기

ActivitySub.java


 



public void onClick (View v) {

switch (v.getId()) {

case R.id.btnBack :

Intent intent = new Intent ();

intent.putExtra("TextMsg", mEdit.getText().toString());

int nNumber = 42561654;

intent.putExtra("IntMsg", nNumber);

setResult(Activity.RESULT_OK, intent);

finish();

break;

}

}





MainActivity.java




 


public class MainActivity extends Activity {

EditText mEdit;

final static int ACT_SUB = 0;

}





public void onClick(View v) {

Intent intent = new Intent (getapplicationContext(), ActivitySub.class);

intent.putExtra("TextMsg", mEdit.getText().toString());


startActivityForResult(intent, ACT_SUB);

}



@Override

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {


        switch (requestCode) {

        case ACT_SUB:

        if (resultCode == Activity.RESULT_OK) {

        mEdit.setText(data.getStringExtra("TextMsg"));

        String strMSG="Number : ";

        strMSG += data.getIntExtra("IntMsg", 1);

        Toast.makeText(getApplication(),

        strMSG, Toast.LENGTH_SHORT().show();

        }

         break;

        }

    }




Volley image 원형으로 만들기

 

 CircularNetworkImageView .java

 

 

 


 

 

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;

import com.android.volley.toolbox.NetworkImageView;

public class CircularNetworkImageView extends NetworkImageView {
	Context mContext;

	public CircularNetworkImageView(Context context) {
		super(context);
		mContext = context;
	}

	public CircularNetworkImageView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		mContext = context;
	}

	public CircularNetworkImageView(Context context, AttributeSet attrs,
			int defStyle) {
		super(context, attrs, defStyle);
		mContext = context;
	}

	@Override
	public void setImageBitmap(Bitmap bm) {
		if(bm==null) return;
		setImageDrawable(new BitmapDrawable(mContext.getResources(),
				getCircularBitmap(bm)));
	}

	/**
	 * Creates a circular bitmap and uses whichever dimension is smaller to determine the width
	 * <br/>Also constrains the circle to the leftmost part of the image
	 * 
	 * @param bitmap
	 * @return bitmap
	 */
	public Bitmap getCircularBitmap(Bitmap bitmap) {
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		int width = bitmap.getWidth();
		if(bitmap.getWidth()>bitmap.getHeight())
			width = bitmap.getHeight();
		final int color = 0xff424242;
		final Paint paint = new Paint();
		final Rect rect = new Rect(0, 0, width, width);
		final RectF rectF = new RectF(rect);
		final float roundPx = width / 2;

		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(color);
		canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);

		return output;
	}

}
 

 


In XML:->
<yourPackageName.CircularNetworkImageView android:layout_width="60dp" android:layout_height="60dp" android:id="@+id/userImgClass" />

In Activity:->
 CircularNetworkImageView thumbnail = ((CircularNetworkImageView) convertView.findViewById(R.id.main_activity_listview_item_thumbnail));

if you don't use your package name in XML u'll get ClassCastException

Android - 연락처 가져오기

http://blackroom.egloos.com/225754

몇 일전에 연락처 가져오기 기능이 필요하여 만든 샘플 코드.

실로 간단하다.

- 메인 Activity                      - 연락처 Activity
  1. 연락처 버튼 클릭 --------> 2. 연락처와 리스트에 뿌리기
  4. 연락처 정보 받음 <-------- 3. 연락처 선택. 

기능 구현을 위한 주요 요소를 살펴보면 
  1. AndroidManifest.xml: 당연히 연락처를 읽어 드리기 권한이 필요하다.(읽는 것만 가능, 쓰기 위해서는 따로 쓰기 권한이 필요)
      - <uses-permission android:name="android.permission.READ_CONTACTS" />

  2. 연락처 쿼리 후 가져오기 

private ArrayList<Contact> getContactList() {

Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;

String[] projection = new String[] {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID, // 연락처 ID -> 사진 정보 가져오는데 사용
ContactsContract.CommonDataKinds.Phone.NUMBER,        // 연락처
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME }; // 연락처 이름.

String[] selectionArgs = null;

String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC";

Cursor contactCursor = managedQuery(uri, projection, null,
selectionArgs, sortOrder);

ArrayList<Contact> contactlist = new ArrayList<Contact>();

if (contactCursor.moveToFirst()) {
do {
String phonenumber = contactCursor.getString(1).replaceAll("-",
"");
if (phonenumber.length() == 10) {
phonenumber = phonenumber.substring(0, 3) + "-"
+ phonenumber.substring(3, 6) + "-"
+ phonenumber.substring(6);
} else if (phonenumber.length() > 8) {
phonenumber = phonenumber.substring(0, 3) + "-"
+ phonenumber.substring(3, 7) + "-"
+ phonenumber.substring(7);
}

Contact acontact = new Contact();
acontact.setPhotoid(contactCursor.getLong(0));
acontact.setPhonenum(phonenumber);
acontact.setName(contactCursor.getString(2));

contactlist.add(acontact);
} while (contactCursor.moveToNext());
}

return contactlist;

}

전체 샘플 소스 -> ContactsSample.zip

참조:http://egloos.zum.com/blackroom/v/225754

+ Recent posts