황현동 블로그 개발, 인생, 유우머

170501 안드로이드 스터디 정리

Tags:







[toc]




play book url

https://play.google.com/store/books/details?id=_8ajAgAAQBAJ




안드로이드 초기역사

  • 2005 : 구글이 안드로이드 인수
  • 2007 : v.1.0 (early look sdk) 발표
  • 2009.4 : v1.5
    • 소프트웨어 키보드
    • 미디어 레코딩
    • 위젯
  • 2009.6 : v1.6
  • 2009.7 : v2.0
    • tts
  • v2.3
    • wifi 핫스팟
    • sd card 앱설치 지원
    • OpenGL ES 2.0 지원
    • NFC 지원
  • v3.0
    • 듀얼코어 지원
    • 프래그먼트 소개
  • v4.0
    • Roboto 폰트 추가
    • Wifi Direct 제공
      • P2P 서비스를 위함




달빅 VM

  • jvm 구현체 –(최적화)–> 달빅vm
  • .class 파일 –(달빅vm)–> .dex 파일




안드로이드 소프트웨어 스택

Application
Java SDK
리소스, 위치, UI, 컨텐트프로바이더, 패키지매니저
달빅VM
native 라이브러리
OpenGL, WebKit, FreeType, SSL, libc, SQLite,
Media(패킷비디오기반, www.packetvideo.com, OpenCore),
SurfaceManager …
리눅스 커널
디바이스 드라이버, 리소스관리, 전력관리 …




안드로이드 컴포넌트

  • intent
    private static void _StartGoogle(Activity activity)
    {
      var intent = new Intent(Intent.ACTION_VIEW);
      intent.setData(Uri.Parse("http://google.com"));
      activity.startActivity(intent);
    }
    




애플리케이션 생애주기

  • 액티비티 시작
  • onCreate
  • onStart
  • onResume
  • onPause
  • onStop
  • onDestroy
  • 액티비티 종료




리소스

  • 문자열 리소스
    • /res/values/strings.xml
        <resource>
            <string name=hello> hello
            <string name=app_name> hello message
      
        R.string.hello
      
  • 레이아웃 리소스
    • /res/layout/main.xml

        <LinearLayout 
            orientation=vertical 
            layout_width=fill_parent
            layout_height=fill_parent
            <TextView
                id=@+id/text1
                ...
            <Button
                id=@+id/b1
                ...
      
        onCreate
            this.setContentView(R.layout.main);
            var tv = (TextView)this.findViewById(R.id.text1);
            tv.setText("...");
      




핵심 안드로이드 리소스

  • 문자열
    • /res/values/…
    • R.string.*
  • 이미지
    • /res/drawable/…
    • *.jpg, *.png, *.gif
    • *.9.png
    • R.drawable.*
  • xml
    • /res/xml/…
    • *.xml
    • R.xml.*
  • raw 리소스
    • /res/raw/…
    • R.raw.*
  • 에셋
    • /assets/…/…/…/*
    • 임의의 깊이가 가능함
    • 실제 리소스는 아니고 그냥 일반 파일
    • 리소스 ID 생성 안함
    • /assets 를 제외한 상대경로로 접근해야 함




이미지 리소스

<Button
	id=@+id/button1
	background=@drawable/sample_image
var d = activity.getResource().getDrawable(R.drawable.sample_image);
button.setBackgroundDrawable(d);
button.setBackgroundResource(R.drawable.sample_image)




모서리가 둥근 직사각형

  • /res/drawable/my_rounded_rect.xml

      <shape
          <solid color=#ff123456
          <stroke width=3dp color=...
          <corners radius=13dp
          <padding left=10dp top=10dp right=10dp bottom=10dp
    
var d = (GradientDrawable)activity.getResources().getDrawable(R.my_rounded_rect);
tv.setBackgroundDrawable(d);




raw 리소스

String _GetStringFromRawFile(activity)
	var is = activity.getResource().openRawResource(R.raw.test);
	var os = new ByteArrayOutputStream();
	...
	var str = os.toString();
	return str;




asset

String _GetStringFromAssetFile(activity)
	var is = activity.getAssets().open("test.txt");
	var os = new ByteArrayOutputStream();
	...
	var str = os.toString();
	return str;




시스템 DB 파일

  • /data/data/*/databases
    • alarms.db
    • contracts.db
    • downloads.db
    • settings.db




헬퍼클래스에 정의된 URI

  • MediaStore.Images.Media.INTERNAL_CONTENT_URI
    • content://media/internal/images
  • MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    • content://media/external/images
  • ContactsContract.Contacts.CONTENT_URI
    • content://com.android.contacts/contacts




주소록 DB 읽기

  • 23 번 주소록 읽기

      var uri23 = Uri.withAppendedPath(ContactsContract.Contacts.CONTENTS_URI, "23");
      var cur = activity.managedQuery(uri23, null, null, null);
      var idxName = cur.getColumnIndex(Contacts.DISPLAY_NAME_PRIMARY);
      var name = cur.getString(idxName);
    
      var uri = ContactsContract.Contacts.CONTENTS_URI;
      var cur = activity.managedQuery(uri23, null, "id=?", new String[] {23});
      var idxName = cur.getColumnIndex(Contacts.DISPLAY_NAME_PRIMARY);
      var name = cur.getString(idxName);
    
  • 모든 주소록 읽기

      var uri = ContactsContract.Contacts.CONTENTS_URI;
      var cur = activity.managedQuery(uri23, null, null, null);
      var idxName = cur.getColumnIndex(Contacts.DISPLAY_NAME_PRIMARY);
    	
      for(cur.moveToFirst(); !cur.isAfterLast(); cur.moveNext())
      {
          var name = cur.getString(idxName);
      }
    




레코드 삽입

var values = new ContentValues();
values.put("title", "new title");
values.put("note", "new note");

var cr = activity.getContentResolver();
var uri = ContactsContract.Contacts.CONTENTS_URI;
var newUri = cr.insert(uri, values);




레코드 갱신/삭제

cr.update
cr.delete

인텐트 기초

MyActivity
{
	onCreate
	{
		var intent = this.getIntent();
		...
	}
}
<activity name=.MyActivity
	<intent-filter
		<action name=com.myapp.intent.action.My
		<category name=android.intent.category.DEFAULT
_InvokeMyActivity(activity)
{
	var actionName = "com.myapp.intent.action.My"
	var intent = new Intent(actionName);
	activity.startActivity(intent);
}




기본 인텐트

_InvokeWebBrowser(activity)
{
	var intent = new Intent(Intent.ACTION_VIEW);
	intent.setData(Uri.Parse("http://google.com"));
	activity.startActivity(intent);
}
_InvokeCall(activity)
{
	var intent = new Intent(Intent.ACTION_CALL);
	intent.setData(Uri.Parse("tel:02-1234-5678"));
	activity.startActivity(intent);
}




간단한 메뉴

MyActivity
{
	onCreateOptionMenu(menu)
	{
		var menuIdx = Menu.FIRST;
		var item1 = menu.add(menuIdx, menuIdx, menuIdx, "first menu");
		menuIdx++;
		var item2 = menu.add(menuIdx, menuIdx, menuIdx, "second menu");
	}

	onOptionMenuSelected(item)
	{
		if(item.getItemId() == Menu.FIRST)
		{
		}
		else if(item.getItemId() == (Menu.FIRST + 1))
		{
		}
	}
}	




클래스 이름으로 인텐트 호출

_InvokeMyActivity(activity)
{
	var intent = new Intent(activity, MyActivity.class);
	activity.startActivity(intent);
}




인텐트 카테고리

  • CATEGORY_DEFAULT
    • 묵시적 인텐트로 실행가능하게
  • CATEGORY_LAUNCHER
    • "android.intent.category.LAUNCHER"
    • 시작화면을 지정
  • CATEGORY_HOME
    • 홈스크린에 표시




실행가능한 앱 모두 열거

_EnumAllAppsAndStartMy(activity)
{
	var mainIntent = new Intent(Intent.ACTION_MAIN, null);
	mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
	var pm = activity.getPackageManager();
	var actList = pm.queryIntentActivities(mainIntent, 0);

	for (var ri : actList)
	{
		var packName = ri.activityInfo.packageName;
		var clsName = ri.activityInfo.name;

		if(clsName.Contains(".My"))
		{
			var newIntent = new Intent();
			newIntent.setClassName(packName, clsName);
			activity.startActivity(newIntent);
			break;
		}
	}
}




어떤앱을 실행할지 묻기

_QueryAnyApp(activity)
{
	var mainIntent = new Intent(Intent.ACTION_MAIN, null);
	mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
	activity.startActivity(mainIntent);
}




어떤홈을 실행할지 묻기

_QueryAnyHome(activity)
{
	var mainIntent = new Intent(Intent.ACTION_MAIN, null);
	mainIntent.addCategory(Intent.CATEGORY_HOME);
	activity.startActivity(mainIntent);
}




TextView 자동링크

tv.setAutoLinkMask(Linkify.ALL);
tv.setText("please visit http://google.com .")




AutoCompleteTextView

<AutoCompleteTextView id=@+id/actv
tv.setAutoLinkMask(Linkify.ALL);
tv.setText("please visit http://google.com .");

var strAdapter = new ArrayAdapter<String>(
	this,
	android.R.layout.simple_dropdown_item_1line,
	new String[] {"en", "ko", "jp", "ch", ...});

tv.setAdapter(strAdapter);




Button

<Button ...
var btn = (Button)thisActivity.findViewById ...
btn.setOnClickListener( new OnClickListener() {
	public void onClick(v) {
		var i = new Intent(Intent.ACTION_VIEW,
			Uri.parse("http://google.com"));		
		thisActivity.startActivity(i);
	}
})




ImageButton

<ImageButton
	...
	src=@drawable/icon
imgBtn = findById ...
imgBtn.setImageResource(R.drawable.icon);




ToggleButton

<ToggleButton
	textOn
	textOff




CheckBox

<CheckBox
cb.setOnChecedChangeListener(
	new CompoundButton.OnCheckedChangeListener() {
		onCheckedChanged(cb, isChecked) {
			...
		}
	}
)




RadioButton

<RadioGroup
	orientation=vertical
	<RadioButton
		text=...
	<RadioButton
		text=...
	<RadioButton
		text=...
var myRadioGroup = findById ...
var id = myRadioGroup.getCheckedRadioButtonId();
myRadioGroup.setOnCheckedChangedListener( 
	...
);




ImageView

<ImageView
	id=@+id/img1
	src=@drawable/icon

<ImageView
	id=@+id/img2
	layout_width=125dp
	layout_height=25dp
	src=#555555

<ImageView
	id=@+id/img3

<ImageView
	id=@+id/img4
	src=@drawable/img4
	scaleType=centerInside
	maxWidth=35dp
	maxHeight=50dp
img3 = ...
img3.setImageResource(R.drawable.img3);

img3.setImageBitmap(
	BitmapFactory.decodeResource(
		thisActivity.getResourec(), 
		R.drawable.img3));

img3.setImageDrawable(
	Drawable.createFromPath("/mnt/sdcard/img3.png"));

img3.setImageURI(
	Uri.parse("file://mnt/sdcard/img3.png"));




DatePicker, TimePicker

<DatePicker
<TimePicker
dp.getMonth();
...

var timeF = new java.util.Formatter();
timeF.format(
	"%02d:%02d:%02d", 
	tp.getCurrentHour(), 
	tp.getCurrentMinute(), 
	tp.getCurrentSecond());
var timeStr = timeF.toString();




스타일과 테마

<string name=styled_text><i>이탤릭</i>스타일 <b>볼드</b>스타일</string>
tv.setText(
	R.string.styled_text, 
	TextView.BufferType.SPANNABLE);
et.setText(...);
var spn = (Spannable)et.getText();

spn.setSpan(
	new BackgroundColorSpan(Color.RED), 
	0, 
	7, 
	Spanable.SPAN_EXCLUSIVE_EXCLUSIVE);

spn.setSpan(
	new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 
	0, 
	7, 
	Spanable.SPAN_EXCLUSIVE_EXCLUSIVE);




뷰에서 스타일 사용

  • /res/values/…

      <resources
          <style name=error_text
              <item name=layout_width>fill_parent
              <item name=layout_height>fill_parent
              <item name=textColor>#ff0000
              <item name=typeface>monospace
    
  • /res/layout/…

      <TextView
          style=@style/error_text
    




레이아웃 관리자

  • LinearLayout
  • TableLayout
  • RelativeLayout
  • FrameLayout
  • GridLayout




LinearLayout

<LinearLayout
	<EditText 
		layout_height=wrap_content 
		layout_weight=0
	<EditText 
		layout_height=wrap_content 
		layout_weight=100
	<EditText 
		layout_height=wrap_content 
		layout_weight=0
  • 그외의 속성
    • layout_gravity
    • gravity




메뉴

MyActivity
	onCreateOptionMenu( menu )
	{
		super ...
		menu.add(0, 0, 0, "menu0");
		menu.add(1, 1, 1, "menu1");
		var menuItem2 = menu.add(2, 2, 2, "menu2");
		menuItem2.setIcon(R.drawable.menuItem2);
	}

	onOptionItemSelected( item )
	{
		var mid = item.getItemId();
	}




컨텍스트 메뉴

MyActivity
	onCreate
	{
		var tv = ...
		thisActivity.registerForContextMenu(tv);
	}

	onCreateContextMenu(menu, v, menuInfo)
	{
		menu.setHeaderTitle("contextMenu");
		menu.add(100, 100, 100, "contextMenuItem100");
	}

	onContextItemSelected(item)
	{
		if(item.getItemId() == 100)
		{
			...
		}
	}




다이얼로그

AlertDialog.Builder




토스트

Toast.
	makeText(thisActivity, "toast message", Toast.LENGTH_LONG).
	show();




탭-액션바

MyActivity
	onCreate
		var ab = thisActivity.getActionBar();
		ab.setTitle
		ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

		var t0 = ab.newTab();
		t0.setText
		t0.setTabListener
		ab.addTab(t0);

		var t1 = ab.newTab();
		t1.setText
		t1.setTabListener
		ab.addTab(t1);




탭-액션바에 메뉴를 위치시키려면

showAsAction=ifRoom
//showAsAction=ifRoom
//showAsAction=never
//showAsAction=always




리스트-액션바

MyActionBarAdapter 
	extends ArrayAdapter<String>
	implements SinnableAdapter
{
	MyActionBarAdapter(ctx)
	{
		super(
			ctx, 
			android.R.simple_sppiner_item, 
			new String[] {"one", "two"});

		this.setDropDownResource(
			android.R.layout.simple_spinner_dropdown_item);
	}

	getDropdownView(position, convertView, perentView)
	{
		return super.getDropDownView(
			position, 
			convertView, 
			parentView);
	}
}
MyActivity
	onCreate
		var ab = thisActivity.getActionBar();
		ab.setTitle
		ab.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

		ab.setListNavigationCallbacks(
			new MyActionBarAdapter(this),
			new ActionBar.OnNavigationListener 
			{
				onNavigationItemSelected(itemPosition, itemId) 
				{
				}
			}
		);




표준-액션바

MyActivity
	onCreate
		var ab = thisActivity.getActionBar();
		ab.setTitle
		ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);

		var t0 = ab.newTab();
		t0.setText
		t0.setTabListener
		ab.addTab(t0);

		var t1 = ab.newTab();
		t1.setText
		t1.setTabListener
		ab.addTab(t1);




검색-액션바

MyActivity
{
	onCreateMenu
	{
		var menuItem = create ...
		menuItem.id = id/menu_search ...
		var searchView = (SearchView)menuItem.getActionView();
		var searchMgr = (SearchManager)thisActivity.getSystemService(
			Context.SEARCH_SERVICE);
		var cn = new ComponentName(thisActivity, MyActivity.class);
		var info = searchMgr.getSearchInfo(cn);
		searchView.setSearchInfo(info);
		searchView.setIconifiedByDefault(false);
	}

	onCreate
	{
		var queryIntent = thisActivity.getIntent();
		var queryAction = queryIntent.getAction();
		
		if (queryAction == Intent.ACTION_SEARCH)
		{
			var queryString = queryIntent.getStringExtra(
				SearchManager.QUERY);
		}
	}
}	
  • /res/xml/searchable.xml
<searchable
	label=...
	hint=...
  • AndroidManifest.xml
<activity name=.MyActivity
	<intent-filter
		<action name=android.intent.action.SEARCH
	<meta-data 
		name=android.app.searchable
		resource=@xml/searchable