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

Categories: Android

1 Comment

travel · August 20, 2016 at 11:43 am

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 *