Android Basic

1.. Android Application 상태 유지 기법

아래는 Activity 의 life Cycle 이다. Android 는 Process 의 관리를 Android Frame Work이 수행하기 때문에 개별Application 에서는 메모리 부족 등에 의한 급작스러운 시스템의 종료를 대비할 필요가 있다.

Activity 의 생성을 위한 자원의 Loading 및 Setting 을onCreate()에서 App 이 종료시에 필요한process 처리를 onPause() 에서 한다는 것은 틀린 이야기는 아니지만 onCreate와 onPause 에 코드가 집주되는 것을 막고 확실한 Application의 상태유지를 위해서는 아래의 두 가지 상태를 이용할 필요가 있다.

onsaveInstanceState : Activity가 종료되는 시점에 불려진다. 순서로는 onPause() 다음에 실행

onRestoreInstanceState : Activity 가 다시 화면으로 올라오는 경우 불려진다. onCreate 다음 실행

위의 두 상태에서는 Instance 의 저장을 위해 Parcelable 을 상속받는 Bundle 객체를 이용하며

이에 대한 설명은 뒤쪽에서 하도록 한다.

  1. Fragment

Android 3.0 이하에서는 화면은 즉 Activity 이고 모든 logic 처리를 Activity 안에서 수행을 하였다면 Android 3.0 이상의 버전에서는 Activity 안에 복수개의 별도의 생명 주기를 갖는Fragment 를

포함하여 개발하도록 UI 개발 사상이 바뀌었다. 기본적인 사용방법은 아래와 같다.

– Fragment를 상속받는 클래스를 생성한다.

– 생성한 Fragment 를 layout 혹은 java 코드를 통해 Activity 에 등록한다.

(1) Activity 에 Fragment 등록하기

  1. A) Fragment Class 정의

Fragment 는 Activity 와 마찬가지로 일반 Fragment , ListFragment 등 다양한 종류의 Fragment 가 존재하며, 기본적인 Fragment 의 경우 아래와 같은 callback Class 들을 갖는다.

@Override

public void onAttach(Activity activity) {

super.onAttach(activity); }

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState); }

@Override

public void onSaveInstanceState(Bundle outState) {

super.onSaveInstanceState(outState);

}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

{

return tv;

}

@Override

public void onActivityCreated(Bundle savedInstanceState) {

super.onActivityCreated(savedInstanceState);

}

@Override

public void onStart() {

super.onStart();

}

@Override

public void onResume() {

super.onResume();

}

@Override

public void onPause() {

super.onPause();

}

@Override

public void onStop() {

super.onStop();

}

@Override

public void onDestroyView() {

super.onDestroyView();

}

@Override

public void onDestroy() {

super.onDestroy();

}

@Override

public void onDetach() {

super.onDetach();

}

  1. B) layout XML 에 등록하여 사용하는 방법

<fragment class=”edu.jaen.android.fragment.layout.FragmentLayout$TitlesFragment”

android:id=”@+id/titles”

android:layout_width=”match_parent”

android:layout_height=”match_parent” />

  1. B) Java 에서 동적으로 포함시키는 방법

DetailsFragment details = new DetailsFragment();

details.setArguments(getIntent().getExtras());

getFragmentManager().beginTransaction().add(android.R.id.content,

details).addToBackStack(null).commit();

@Sample@ : 1. Fragment 폴더 참조

  1. Action Bar

API11 부터 기존의 title bar에 메뉴, tab 등의 기능을 추가하여 강력한 기능을 포함한 Action Bar Class 가 제공된다 .기본적인 사용방법은 아래와 같다.

– menu 형태를 layout 혹은 java 코드로 생성

– activity 의 onCreateOptionsMenu, onOptionsItemSelected 에서 생성한 메뉴 혹은 TAB을 Activity 에 추가한다.

(1) action bar 에 메뉴 등록

  1. A) xml 에 메뉴를 정의

Menu -> item -> menu(sub) -> item(sub)과 같은 형식으로 xml 에 정의할 수 있다.

<menu xmlns:android=“http://schemas.android.com/apk/res/android”

android:actionViewClass=“android.widget.HorizontalScrollView”>

<item android:id=“@+id/action_sort”

android:icon=“@android:drawable/ic_menu_sort_by_size”

android:title=“@string/action_bar_sort”

android:showAsAction=“always”>

<menu>

<item android:id=“@+id/action_sort_size”

android:icon=“@android:drawable/ic_menu_sort_by_size”

android:title=“@string/action_bar_sort_size”

android:onClick=“onSort”/>

<item android:id=“@+id/action_sort_alpha”

android:icon=“@android:drawable/ic_menu_sort_alphabetically”

android:title=“@string/action_bar_sort_alpha”

android:onClick=“onSort”/>

</menu>

</item>

</menu>

  1. b) java 에서 동적으로 추가

menu.add(“Normal item1”);

menu.add(“Normal item2”);

menu.add(“Normal item3”);

MenuItem actionItem = menu.add(“Action Button”);

actionItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

actionItem.setIcon(android.R.drawable.ic_menu_share);

 

(2) Activity 에서의 처리

  1. A) Menu Event 처리

onCreateoptionMenu 와 onOptionsItemSelected Event API11 이전 버전과 동일하지만

actionItem.setShowAsAction메서드를 실행함으로써 ActionBar 로 메뉴를 올려 보낼 수 있다.

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// java에서 동적으로 등록

menu.add(“Normal item3”);

MenuItem actionItem = menu.add(“Action Button”);

actionItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

actionItem.setIcon(android.R.drawable.ic_menu_share);

// xml layout inflating

MenuInflater inflater = getMenuInflater();

inflater.inflate(R.menu.actions, menu);

return true;

}

@Override

public booleanonOptionsItemSelected(MenuItem item) {

 

// 선택된 메뉴에 대한 기능 처리

return true;

}

 

  1. B) Tab 추가

ActionBar 의 addTab 메서드를 이용하여 동적으로 tab을 추가 할 수 있으며 Fragment와의 연동을 통해 API 11 이전 TabActivity 기능을 대체 할 수 있다.

final ActionBar bar = getActionBar();

final int tabCount = bar.getTabCount();

final String text = “Tab ” + tabCount;

bar.addTab(bar.newTab().setText(text).setTabListener(new TabListener(new TabContentFragment(text))));

@Sample@ : ActionBar 폴더 참조

  1. Loader

읽는 즉시즉시 출력가능하도록 간단한 메서드들을 지원한다. Thread 와 유사한 개념으로 안드로이드에서 지원하는 Loding을 위한 클래스

(1) LoadManager 등을 Implement

– implements OnQueryTextListener, LoaderManager.LoaderCallbacks

(2) init method 호출

– getLoaderManager().initLoader(id, Bundle arg, callback);

(3) call back method 정의

A)onCreateLoader

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

Uri baseUri;

if (mCurFilter != null) {

baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,

Uri.encode(mCurFilter));

} else {

baseUri = Contacts.CONTENT_URI;

}

String select = “((” + Contacts.DISPLAY_NAME + ” NOTNULL) AND (”

+ Contacts.HAS_PHONE_NUMBER + “=1) AND (”

+ Contacts.DISPLAY_NAME + ” != ” ))”;

return newCursorLoader(getActivity(), baseUri,

CONTACTS_SUMMARY_PROJECTION, select, null,

Contacts.DISPLAY_NAME + ” COLLATE LOCALIZED ASC”);

}

B)onLoadFinished

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

 

mAdapter.swapCursor(data);

 

if (isResumed()) {

setListShown(true);

} else {

setListShownNoAnimation(true);

}

}

C)onLoadReset

public voidonLoaderReset(Loader<Cursor> loader) {

mAdapter.swapCursor(null);

}

@Sample@ : 8.LoaderCursor

  1. Intent

Intent 는 Android Framework 과 통신하기 위한 통신객체로 Android 에서 Intent로 다른 Activity를 호출하는 과정은 아래와 같이 일어난다.

(Activity -> Intent 호출 ->Android Frame Work -> Target Activity)

Android 가 Target Action을 호출하는 방법은 명시적 호출방법과 암묵적 호출방식이 있다.

명시적 호출방법은 package 명을 직접 지정하여 호출하는 방식이고, 암묵적 호출방식은 category, action, data 의 조건을 가지고 broad casting 방식으로 호출하는 것이다.

(1) 명시적 호출방식

ComponentName n=new ComponentName(“edu.diana.audio”,”edu.diana.audio.AudioAct”);

i.setComponent(n);

startActivity(i);-

(2) 암묵적 호출방식

i.addCategory(Intent.CATEGORY_DEFAULT);

i.setAction(Intent.ACTION_VIEW);

i.setData(Uri.parse(“poscocctvmobapp:”));

startActivity(i);

(3) Android-manifest 설정

<intent-filter>

<action android:name=“android.intent.action.VIEW”/>

<category android:name=“android.intent.category.DEFAULT”/>

<category android:name=“android.intent.category.BROWSABLE”/>

<data android:scheme=“poscocctvmobapp” />

</intent-filter>

(4) Intent 호출시 Flag 를 통한 TASK 관리

Task 는 android process 들의 실행 순서를 관리하는 것을 말한다. 쉬운 예로 H/W back 버튼을 누를 경우 이전에 사용했던 App 들을 화면상단으로 호출하는 것과 같은 현상을 볼 수 있다.

이러한 task 는 Android ActivityManager 에서 수행하고 있으며, Task 는 Intent 호출 시 Flag 값과

Android-Manifest 에서LuchMode 를 정의함으로써 컨트롤 할 수 있다 .

  1. A) flag

flag 를 통해서 task 관리 가능, bit연산으로 복수의 flag 세팅 가능

-intent.FLAG_ACTIVITY_RECORDER_TO_FRONT : 같은 놈은 위로 올린다.

-intent.FLAG_ACTIVITY_CLEART_TOP : 호출 대상 위에 있는 task 삭제 (호출 대상까지 삭제하고

대상을 다시 만든다)

– intent.FLAG_ACTIVITY_CLEART_TOP|intent.FLAG_ACTIVBITY_SINGLE_TOP : (호출 대상을 삭제하지

않고 위를 전체 삭제)

-intent.FLAG_ACTIVITY_NEW_TASK : 새로운 테스크 생성, service 및broadcast_receiver 에서

Activity를 실행하는 경우 사용

  1. B) LunchMode      

-standard : 동일한 프로세스가 중복하여 쌓일수 있다.

– singleTop : 동일한 프로세스를 연속으로 두번 누르는 경우 동일한 것은 스택에 쌓지 않음

– singleTask : 호출된 Activity 를 시작점으로 새로운 task생성

– singleinstance : 독립적으로 하나의 activity 만 존재함 (ex : 런쳐)

Cf) lunchMode – task명 : 테스크 명을 지정하지 않으면(Activity-Task afifinity) 기본적으로 Package 명을 따라간다. task 명이 같은 경우

  1. 자원공유

(1) 파일 자체를 공유하는 방법

– 기본적으로 DB, FILE 등은 Linux 권한 정책에 따라 다른 어플리케이션에서 읽을 수 없다 .    

– 기본적으로 Cache, File, DB 는 자신의 Context 영역에 정의된다.

– 다른 Context 의 자료를 가지고 싶다면. createPackageContext를 사용해서 다른 컨택스트를

생성해서 데이터를 접근할 수 있다 (단, 권한은 있어야 한다. )

– 단, 파일만들기 단계에서(createPackageContext) 권한을 주면 다른 어플리케이션에서 직접

Access 가 가능하다.

– 특정한 프로제트를 지정하여 서로 접근가능하도록 하고 싶다…-> userID 를 공유해야 한다.

android.os.Process.myUid(), Android_manifiest : shared user id 를 공유하도록 하면 됨.

(2) jar 를 통한 외부 라이브러리 공유

– 안드로이드는 프레임웍이기 때문에 정해진 폴더만 빌드시에 묶는다.

– 확인 방법은 폴더에 A 모양이 있는지를 확인한다.

– 보통의 경우 libs 아래 jar 파일을 포함시키고 path 를 걸어준다.

(3) apk 파일 공유

– 라이브러리 세팅 : 프로젝트 선택 – propoerties – android – isLib 체크

– 라이브러리 사용 : 프로젝트 선택 – propoerties – android – add

(4) DB 공유 – Content-Provider 사용

DB자체를 공유하는 것이 아닌 contentProvider를 사용하여 데이터를 공유할 수 있다.

Android에서 제공하는 주소록과 같은 것들이 이러한 형태로 사용자에게 데이터를 제공하고

있다. Content Provider 는 아래와 같은 구조로 동작한다.

Activity ( contentResolver사용)

->URI(target지정) ,update(),delete(),query(),insert() 메서드 사용

-> ContentProvider 는 해당 메서드에 대한 처리

.

– Content-Provider의 이름은 고유해야 한다.

-SQLLiteOpenHelper의 경우 Android Frame work 에서 관리하지 않는 클래스이다.

– 그렇기 때문에content-provider 를 상속받아 구현을 하면 Frame 을 통해 접근이 가능하다.

-content-provider 의 미구현 메서드는 insert, update, delete-query

-content-provider를 호출하기 위한 클래스는 contentResolver 이다.

-> context.getContentResolver 를 통해서 구한다.

-> insert(URI, ), update(URI, ), delete, quert 메서드 지원…

  1. android 에서 기본적으로 제공하는 URI 는 android.provider 에서 찾는다.

– 타겟 Content-Provider 는 Android-Manifest 등록 시 authority 를 등록해야 한다.

-> URI : content://<정의한authority>/path(table명)

<provider android:name=“MyContentProvider” android:authorities=“com.ict”

android:exported=“true”></provider>

-Content-Provider 생성후 manifiest 의 export 속성을 true 로 정의해 주어야 한다.

-Provider 는 각 Method 에서 path 명을 이용하여 서비스를 분기처리 할 수 있다.

@SAMPLE@ : Content-Provider 폴더 참조

  1. Broadcast Receiver

BroadcastReceiver는 베터리 상태, 충전, wifi접속, 문자 등 각종 Broadcast Event 에 대응하기

위하여 사용한다. Broadcast Receiver를 구성하는 방법은 아래와 같다.

  1.   A) Receiver 생성

– Receiver 측의 Android-Manifest 에 등록하거나 Java 상에서 등록한다.

– BroadcastReceiver 를 상속받아 onReceive(Context context, Intent intent)

메서드를 오버라이딩 한다.

  1.   B) Broadcast 호출

– Android-Manifest 에 Braodcast Messgage 전송 퍼미션을 추가한다 .

<uses-permission android:name=“android.permission.BROADCAST_STICKY”>

– context method 인 sendOrderedBroadcast,sendStickyBroadcast등을 사용하여 간단히

호출 가능하다.

(1) Broadcast Receiver생성 방법

  1. A) android-manifest.xml 에 등록

아래와 같이Android-Manifest에 등록하는 경우 Android Framework에서 발생하는 모든

메시지에 대해서 반응한다.

<receiver

android:name=“edu.jaen.android.receiver.OneShotAlarm1”

android:process=“:remote”>

<intent-filter android:priority=“1”>

<action android:name=“com.jaen.REGISTER” />

</intent-filter>

</receiver>

  1. B) Activity 에서 Regist

Java 에서 내부적으로 등록하는 경우 Android Framework이 알고 있지 못하기 때문에 아래와

같이 BraodcastReceiver 를 등록하기 전에는 동작하지 않는다. (로컬하게 사용하고 싶을 경우)

Context c=getApplicationContext();

IntentFilter f=new IntentFilter(“com.jaen.REGISTER”); //action

f.setPriority(500); // 우선순위 부여

c.registerReceiver(a2, f); //receiver 등록

  1. C) BroadCastting 요청 방법

사용자가 Braodcast 메시지를 호출하는 경우 크게 3가지 방법으로 호출이 가능하다.

– sendBroadCast() : 동일한 action 을 갖고 있는 Broadcast 가 여러 개 있을 경우 Random

– sendOrderedBroadcast(): 여러 개가 있을 경우 우선순위에 의해 순차적으로 실행

– sendStickyBroadcast() : 호출 시점에 Receiver가 없어도 신규 등록을 기다리고 있다가 실행

  1. D) Intent Flag 를 이용한 Broadcast 제어

intent 에서 호출 시 flag 를 사용하여 제어를 할 수 있다.

-FLAG_RECEIVER_REGISTED_ONLY : Android_Manifiest 에 정의되어 있는 receiver는 무시한다.

-FLAG_RECEIVER_REPLACE_PENDING : 동일한 intent 가 연속적으로 전달될 경우 처음과

마지막 것만 인식함

-FLAG_INCLUDE_STOPPED_PACKAGE : (Package가 Stopped)정지되어 있는 PROCESS 는

실행되지 않는 경우가 있다. 이런 경우 사용한다.

 

@SAMPLE@ : BroadCastReceiver 폴더 참조

  1. Widget – Service

Widget은 기본적으로 HomeApplication 과의 통신을 통해서 동작한다. Android 에서는 이러한 복잡한 통신 과정을 간단하게 처리할 수 있도록appWidgetProvider 를 제공한다.,

아래는 기본적인 Widget 의 동작 과정이다.

Service -> RemoteView -> AppWidgetProvider-> Home Program

(1) Android-Manuifest.xml 정의

아래와 같은 Manifest 에 정의를 하게 되면 Android Home 에서 Widget 설치 메뉴에 등록이 됨

Meta-data 에 보면 Home에서 Widget 의 UI 를 정의하는 xml 이 정의 되는 것을 볼 수 있다.

<receiver

android:enabled=“true”

android:label=스마일! 이벤트

android:name=“edu.jaen.android.wiget.event.WidgetReceiver”>

<intent-filter >

<action android:name=“android.appwidget.action.APPWIDGET_UPDATE”/>

</intent-filter>

<meta-data

android:name=“android.appwidget.provider”

android:resource=“@xml/smileinfo”/>

</receiver>

(2) [resource].xml 정의

Widget 의 크기Resizable 여부를 정의하고 Widget에서 사용할layout 등을 정의할 수 있다.

<?xml version=“1.0”encoding=“utf-8”?>

<appwidget-provider xmlns:android=“http://schemas.android.com/apk/res/android”

android:minWidth=“40dip”

android:minHeight=“110dip”

android:resizeMode=“vertical|horizontal”

android:updatePeriodMillis=“0”

android:initialLayout=“@layout/smile”>

</appwidget-provider>

(3) layout 정의

Layout 은 기존에Activity 나 Fragment 의 Layout 을 정의하는 것과 크게 다르지 않다.

<?xml version=“1.0”encoding=“utf-8”?>

<RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”

android:id=“@+id/mainlayout”

android:layout_width=“wrap_content”

android:layout_height=“fill_parent”

android:orientation=“vertical”>

<ImageView

android:id=“@+id/smileImage”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:src=“@drawable/smile”/>

<TextView

android:id=“@+id/smileText”

android:layout_width=“fill_parent”

android:layout_height=“wrap_content”

android:layout_alignRight=“@+id/smileImage”

android:layout_below=“@id/smileImage”

android:gravity=“center”

      android:text=“Smile”

android:textColor=“#ffff00”

android:textSize=“15sp”/>

</RelativeLayout>

(4)AppWidgetProvider 상속 클래스생성

3번 까지의 과정을 통해서 Widget을 Home 화면에 출력하였다면 이제 유동적으로 이벤트 처리나 데이터 갱신을 위하여 AppWidgetProvider 와 Service 를 이용하여야 한다.

AppWidgetProvider 는Home 과 Service 사이의 통신을 도와주며 통신을 위해서는 RemoteView객체를 생성하여 교환한다.

public class WidgetReceiver extends AppWidgetProvider {

public void onUpdate(Context context, AppWidgetManager appWidgetManager,

int[] appWidgetIds)

{

}

static void appWidgetUpdate(Context context, int appWidgetId, int imgId,

CharSequence text) {

}

@Override

public void onEnabled(Context context) {

super.onEnabled(context);

}

@Override

public void onDisabled(Context context) {

super.onDisabled(context);

}

@Override

public void onDeleted(Context context, int[] appWidgetIds) {

super.onDeleted(context, appWidgetIds);

}

}

(5)RemoteView 생성

  1. A) RemoteView를 생성

RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.smile);

views.setImageViewResource(R.id.smileImage, imgId);

views.setTextViewText(R.id.smileText, text);

  1. B) AppWidgetManger 생성

AppWidgetManager wm = AppWidgetManager.getInstance(context);

C)Service 실행할 Intent 생성

Intent intentImage = new Intent(context, ImageService.class);

intentImage.putExtra(“wId”, appWidgetId);

D)다른 프로그램이Intent를 실행할 수 있도록 PendinIntent 생성

PendingIntent pendingImage = PendingIntent.getService(context,appWidgetId, intentImage, 0);

E)RemoteView onClickPendingIntent Listener 추가

views.setOnClickPendingIntent(R.id.smileImage, pendingImage);

F)AppWidgetManager의 updateAppWidget() 메서드를 통해 HOST로 View Update

wm.updateAppWidget(appWidgetId, views);

@Sample@ : 6. AppWigetEvent 폴더를 참조한다.

  1. 상태유지 기법과 Parcelable

상태 유지 기법으로는 Preference ,Data Base, File , network 를 사용하는 방법과 Android 의 System Memory 를 사용하는 기법이 있다.

또, Activity 에서 상태를 유지하기 위해 onSaveInstanceState, onRestoreInstanceState 상태를 이용할 수 있다.

여기서는 Android의System Memory를 이용하여 데이터를 복구하는 방법에 대해서 이야기 하고자 한다. 기본적으로 Activity와 Android FrameWork은 기본적으로 통신을 기반으로 하고 있기 때문에 Seralized 된 객체만이 전송가능하며 특별히 Android 에서는 Parcelable 이라는 개념을 사용하고 있다.

(1) Parcelable 이란?

– 기본적으로 안드로이드는 Activity 간에 Intent 통신을 사용한다.

– 통신에서 객체를 전송하기 위해서는 Serialized 가 되어 있어야 한다.

– Serialized의 단점은 속도가 느리다는 것인데 이것의 단점을 보완한 것이 Parcelable 이다.

-Android 에서는 이러한 Parcelabel 의 개념을 사용하여 Bundle 이라는 객체를 사용하고 있다

(2) onCreate, onSaveInstance 에서의 Bundle 타입 파라메터

  1. A) save call back 에서 Bundle 에 Parcelable 객체를 저장할 수 있다.

  저장된 객체는 Android FrameWork 의 System Memory 공간에 저장된다.

@Override

protected void onSaveInstanceState(Bundle outState) {

// TODO Auto-generated method stub

super.onSaveInstanceState(outState);

bundle.putParcelableArrayList(“list”, pList);

}.

  1. B) Bundle 객체에서 Parcelable 객체를 꺼내어 데이터를 복구한다.

  저장된 객체는 Android FrameWork 의 System Memory 공간에 저장된다.

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

pList = bundle.getParcelableArrayList(“list”);

}

(2) 기존에 Android 에 정의된 Pacelable 객체를 이용

– Bundle 은 기본적으로 Parcelable 객체이기 때문에 그냥 사용하면 된다…

ArrayList<HashMap<String, String>> selectedChildList = null;

ArrayList<Bundle> currentList = null;

Bundle bundle = null;

HashMap<String, String> item = null;

Object[] keyArray = null;

if(mChildList != null && mChildList.size() > 0)

{

selectedChildList = mChildList.get(groupPosition); if(selectedChildList != null && selectedChildList.size() > 0)

{

currentList = new ArrayList<Bundle>();

for(int i = 0; i < selectedChildList.size(); i++) {

item = selectedChildList.get(i);

bundle = new Bundle();

keyArray = (Object [])item.keySet().toArray();

for(int j = 0; j < keyArray.length; j++)

{

bundle.putString(String.valueOf(keyArray[j]), item.get(keyArray[j]));

}

currentList.add(bundle);

}

}

(3) Parcelable 객체를 생성하여 사용하기

– 기본적으로 Parcelable 을 Implements 받아 생성하며 몇 가지 필수적인 Method 를 Overide 하여 구현하여야 한다.

– writeToParcel: 통신시 Android FrameWork에서 호출되는 메서드로 Seraliazable 하도록 직접 사용자가 데이터를 set 해주어야 한다. (이때 순서가 매우 중요, CREATE 와 일치해야 함)

– CREATEOR : 리턴하고자 하는 객체 타입으로 복원하는 메서드 또한 Overide 하여 구현 필요

public class Point implements Parcelable{

float x;

float y;

boolean isDraw;

public Point(float f, float g, boolean isDraw) {

this.x = f;

this.y = g;

this.isDraw = isDraw;

}

@Override

public int describeContents() {

// TODO Auto-generated method stub

return 0;

}

@Override

public void writeToParcel(Parcel dest, int flags) {

// TODO Auto-generated method stub

dest.writeFloat(x);

dest.writeFloat(y);

dest.writeBooleanArray(new boolean[]{isDraw});

}

public static Creator<Point> CREATOR = newCreator<Point>() {

@Override

public Point createFromParcel(Parcel source) {

// TODO Auto-generated method stub

float x = source.readFloat();

float y = source.readFloat();

boolean[] ba = new boolean[1];

source.readBooleanArray(ba);

return new Point(x,y,ba[0]);

}

@Override

public Point[] newArray(int size) {

// TODO Auto-generated method stub

return new Point[size];

}

};

}

@Sample@ : CustomView 폴더 참조

  1. binding 과 Service 를 Custom Provider

– 이미 ServiceBind 기능을 이용하여 Service 와 Activity 간의 Interactive 한 통신이 가능하다.

샘플코드는 아래와 같은 구조로 동작한다. .

Activity -> Resolver-> (Bind) -> Service (onCreate() -> onBind()-> onUnBind()) ->onDestory());

Service 쪽에서 Bind() 가 되면 Resolver 측에는 onServiceConnected() Callback 이 호출되며 Bind

변수를 리턴한다. 이 Bind 변수를 Interface로 Castinf하여 Service 측과 메서드 기반의 통신이 가능하다. 이때, 주고 받을 수 있는 객체는 당연히 통신 기반이기 때문에 Parcelable 객체만 가능

(1) Activity ->Resolver

샘플코드 에서 Activity 에 구현되는 내용은 별 것 없다. Resolver 에 구현된 몇 가지 메서드들을 호출할 뿐이다 .

myResolver = new MyResolver(this);

Button btn01 = (Button)this.findViewById(R.id.btn_01);

btn01.setOnClickListener(newOnClickListener() {

@Override

public void onClick(View v) {

myResolver.insert();

}

});

(1) Resolver ->Service

샘플코드에서 Resolver 는 어떤 인터페이스도 클래스도 상속 받지 않는다. Resolver에서 하는 역할은 3가지로 요약된다. Service Binding, ServiceConnection 객체를 통한Binding 객체 생성, Binding 객체를 이용한Service method 호출 3가지로 요약된다.

  1. A) Service 바인딩

Intent i = new Intent();

ComponentName cn = new ComponentName(“com.example.a10.bindtestmyservice”,”com.example.a10.bindtestmyservice.MainService”);

i.setComponent(cn);

//바인딩

context.bindService(i, conn, Context.BIND_AUTO_CREATE);

  1. B) AIDL 생성

다른 패키지 간에 Method 방식으로 Direct 호출은 굉장히 복잡한 일이다. 그래서 Android Frame Work 에서는 AIDL 을 지원한다 .

– AIDL 확장자의 파일을src/package 아래 생성한다.

– gen 폴더 아래 java 파일이 자동 생성되는 것을 볼 수 있다 .

– Service 를 제공받고자 하는 쪽에서도 동일하게 AIDL 파일을 생성해야 한다.

– 단, Service 를 제공하는 쪽과 동일한 Package 명을 사용해야 한다는 점은 유의

– 아래는 AIDL 파일의 예제이다.

package com.example.a10.bindtestmyservice;

interface AidlProvider

{

void insert();

void update();

void delete();

void query();

}

  1. C) ServiceConnection생성

ServiceConnection 클래스는 두 개의 Overiding method 를 지원하는데 onServerConnected()

에서는 Bind 클래스를 return 받을 수 있다.

우리가 정의한 update, query, delete, insert 4개의 method 를 활용하기 위해서 (B)에서 생성한 AIDL 클래스를 사용한다.

AidlProvider provider = AidlProvider.Stub.asInterface(Binder bind)

이렇게 생성된 provider 는 bind.insert();bind.update();bind.delete();bind.query();

메서드를 사용할 수 있다 .

private ServiceConnection conn = new ServiceConnection() {

@Override

public void onServiceDisconnected(ComponentName name) {

Toast.makeText(context, “-ServiceDisconncted”, 10).show();

}

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

Toast.makeText(context, “-ServiceConneted”, 10).show();

bind = AidlProvider.Stub.asInterface(service);

}

};

@Sample@ : AIDL 폴더 참조

  1. USER-PERMISSION

(1) 자신이 생성한 Applcation 에 Permission 지정

<permission

android:description=”@string/permdesc_required”

android:label=”권한이 요구됩니다.”

android:name=”edu.jaen.permission”

android:protectionLevel=”signature”

/>

(2) Permission 획득

<uses-permission android:name=”edu.jaen.permission”/>

@Sample@ : B2.PermissionClient, B2.PermissionProject

  1. 기타

(1) 하위 버전 OS 환경에서 상위버전 기능 사용하기

– android-support_v4 : 하위 버전에서 상위 OS 기능을 사용할 수 있도록 External 형태로 라이브러리가 제공된다. 해당 Lib 는APK 에 포함되어 하위 OS 에서도 동작 할 수 있도록 한다.

(2) ApplicationManager

(3) SQLLite

1 thought on “Android Basic

  1. Wow, wonderful blog layout! How long have you
    been blogging for? you make blogging look easy. The overall look of your web site is excellent, let alone
    the content!

Leave a Reply

Your email address will not be published. Required fields are marked *