More Related Content Similar to 안드로이드 오픈소스 그리고 패턴 (20) More from YoungSu Son (20) 안드로이드 오픈소스 그리고 패턴 16. Agenda
• 안드로이드 이해
– Binder (Broker 패턴) 그리고 Intent
• 오픈 소스 그리고 사례
– Simple Framework (Parameter Object)
– 불편하지 않은 화면 갱신 (Publisher-Subscriber)
• 분석 방법
– Localytics 사용법
– STAN을 이용한 Android App 분석 방법
24. Binder Architecture
IDL
Compiler
in args
operation()
Client Object
OBJ
REF out args,
return
IDL
SKEL
IDL Binder
STUBS INTERFACE Object Adapter
Binder
26. 1. AIDL 파일 생성
package aexp.aidl;
// Adder service interface.
interface IAdderService
{
int add( in int i1, in int i2 );
}
27. 2. AIDL 툴로 Java 파일 생성
수동 코드 생성
sdk/platforms/android- <n>/tools/aidl 에 간다
C:Android-projectApiDemossrccomexampleandroidapisapp>aidl -IC:Android-
projectApiDemossrc IRemoteService.aidl
Eclipse에서는 aidl만 넣고 빌드하면 자동으로 소스 생성 됨
28. 3. Service Class 구현
……
public class AdderServiceImpl extends Service {
@Override
public IBinder getBinder() { return mBinder; }
@Override
public void onCreate() { super.onCreate(); Log.d( "ADDERSERVICEIMPL","onCreate" ); }
/** The IAdderService is defined through IDL */
private final IAdderService.Stub mBinder = new IAdderService.Stub() {
public int add( int i1, int i2 ) {
return i1+i2; }
};
@Override
protected void onDestroy() {
super.onDestroy( Log.d( "ADDERSERVICEIMPL","onDestroy" ); }
}
29. 4. Manifest에 서비스 등록
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="aexp.aidl">
<application>
<activity class=".AIDLServiceActivity" android:label="AIDLServiceActivity">
<intent-filter>
<action android:value="android.intent.action.MAIN" />
<category android:value="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service class=".AdderServiceImpl"/>
</application>
</manifest>
30. 5. Client에 호출을 위해
Binder로 이름 찾는 로직
class AdderServiceConnection implements ServiceConnection
{
public void onServiceConnected(ComponentName className,
IBinder boundService )
{
service = IAdderService.Stub.asInterface((IBinder)boundService);
Log.d( "ADDERSERVICECLIENT","onServiceConnected" );
}
public void onServiceDisconnected(ComponentName className)
{
service = null;
Log.d( "ADDERSERVICECLIENT","onServiceDisconnected" );
}
};
31. 6. 시작, 해제 로직 넣을 것
private void initService()
{
conn = new AdderServiceConnection();
Intent i = new Intent();
i.setClassName( "aexp.aidl", "aexp.aidl.AdderServiceImpl" );
bindService( i, null, conn, Context.BIND_AUTO_CREATE);
}
private void releaseService()
{
unbindService( conn );
conn = null;
}
32. 7. 클라이언트에서 서비스 호출하기
private void invokeService( int i1, int i2 ) {
TextView t = (TextView)findViewById(R.id.invokeserv_result);
if( service == null )
t.setText( "Service not available" );
else {
try {
int result = service.add( i1,i2 );
t.setText( Integer.toString( result ) );
} catch( DeadObjectException ex ) {
t.setText( "Service invocation error" );
}
} ….
33. Broker
transfer transfer
message message
Client-side Broker Server-side
Proxy Proxy
main_event_loop
pack_data pack_data
update_repository
uppack_data uppack_data
register_service
send_request call_service
acknowledgment
return send_response
find_server
Find_client
calls Forward_request
Forward_response
uses API calls uses API calls
Client Bridge Server
pack_data initialize
call_server
uppack_data enter_main_loop
start_task
forward_message run_service
use_Broker_API
transmit_message use_Broker_API
34. Registration
Service, BR, Activity… Broker
start
Initialize() main_evnet_loop()
register_service()
update_repository()
acknowledgment
enter_main_loop()
35. Sending Request
Client Client-Side Broker Server-Side Server
Proxy Proxy
call_server
send_request
pack_data
forward_request
find_server
call_service
unpack_data
run_service
forward_response pack_data
return find_client
unpack_data
result
36. 사용하기
힘든 Binder..
Intent는 Binder를
쉽게 사용할 수 있는 추상화 도구.
38. Intent로 Activity 호출
Intent intent =
new Intent(getApplicationContext(), MyOtherActivity.class);
startActivityForResult(intent, SHOW_SUBACTIVITY);
그런데, Activity 이름이 바뀌면…
39. 그래서 묵시적 Intent
Manifest 파일에 Intent Filter 등록
<activity android:name="DirectoryDialog"
android:theme="@android:style/Theme.Translucent">
<intent-filter>
<action android:name="filemanager.action.PICKFILES" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Activity 만 되는
</activity>
호출
Intent filemanager = new Intent("filemanager.action.PICKFILES");
게 아님
startActivity(filemanager);
47. public class LogtestActivity extends Activity {
static public Logger logger = LoggerFactory.getLogger();
@Override
public void onCreate(Bundle savedInstanceState) {
PatternFormatter formatter = new PatternFormatter();
formatter.setPattern( " %d{ISO8601} [%P] %m %T " );
logger.setLevel(Level.INFO);
// write to LogCat
LogCatAppender logCatAppender = new LogCatAppender();
logCatAppender.setFormatter(formatter);
logger.addAppender(logCatAppender);
// write to text file of SD-card.
FileAppender fileAppender = new FileAppender();
fileAppender.setAppend( true );
fileAppender.setFileName( "microlog4android.log" );
fileAppender.setFormatter(formatter);
logger.addAppender(fileAppender);
52. XML 파싱 이렇게??
while(true) {
<categoryList> int eventType = xpp.nextTag();
<categorys> if(eventType == XmlPullParser.START_TAG) {
<category> String tag = xpp.getName();
<id>1</id> if("id".equals(tag)) {
<name>AA</name> category.setId(Integer.parseInt(xpp.nextText()));
<date>2011-11-01</date> }else if ("name".equals(tag)) {
</category> category.setName(xpp.nextText());
<category> }else if ("date".equals(tag)) {
<id>2</id> category.setDate(xpp.nextText());
<name>BB</name> }else{
<date>2011-12-10</date> if(XmlPullParser.TEXT == xpp.next())
</category> xpp.nextTag();
</categorys> }
</categoryList> }
else
break;
}
54. 이렇게 됩니다.
<categoryList> @Root
<categorys> public class CategoryList {
<category>
<id>1</id> @ElementList
<name>fruit</name> private ArrayList<Category> categorys;
<date>201110051200</date>
</category> public void setCategorys(ArrayList<Category> categorys)
<category> {
<id>2</id> this.categorys = categorys;
<name>animal</name> }
<date>201110051200</date>
</category> public ArrayList<Category> getCategorys() {
<category> return categorys;
<id>3</id> }
<name>food</name> }
<date>201110051200</date>
</category>
</categorys>
</categoryList>
55. 이렇게 됩니다.
while(true) {
int eventType = xpp.nextTag();
if(eventType == XmlPullParser.START_TAG) {
String tag = xpp.getName();
if("id".equals(tag)) {
category.setId(Integer.parseInt(xpp.nextText()));
Serializer serializer =}else if ("name".equals(tag)) {
new Persister();
Reader reader = newcategory.setName(xpp.nextText());
StringReader(xmlData);
CategoryList categoryList if ("date".equals(tag)) {
}else = serializer.read(CategoryList.class, reader,
false);
category.setDate(xpp.nextText());
}else{
if(XmlPullParser.TEXT == xpp.next())
xpp.nextTag();
}
}
else
break;
}
61. Sync Notificati
Service on
2. Insert
Activity
1. Register
XXX
Adapter 3. Notification
Contents
Provider
4. GetData..
62. @Override
public Uri insert(Uri uri, ContentValues values) {
String tableName;
Uri contentUri;
long id;
switch(matcher.match(uri)){
case SITES:
tableName = Bookmark.sites._TABLENAME;
ContentValues values = new ContentValues();
contentUri = Bookmark.sites.CONTENT_URI;
values.put(Bookmark.sites.NAME, stk[i][0]);
break;
values.put(Bookmark.sites.ADDRESS, stk[i][1]);
default:
getContentResolver().insert(Bookmark.sites.CONTENT_URI, values);
throw new IllegalArgumentException();
getContentResolver().notifyChange(Bookmark.sites.CONTENT_URI, null);
}
id = mDB.insert(tableName, null, values);
if(id > 0){
Uri itemUri = ContentUris.withAppendedId(contentUri, id);
return itemUri;
}else
throw new SQLException();
}
72. 이외에도..
• New vs Returning
• Carrier
• Country
• OS Version
74. • http://bit.ly/KnZzpx 에서 소스코드 다운
• Android 프로젝트
src/폴더에 소스코드 추가
• AndroidManifest.xml에 퍼미션 추가
<uses-permission
android:name="android.permission.INTERNET“>
75. • Main Activity에 Import
import com.localytics.android.*;
• 클래스 내부에 session object 추가
private LocalyticsSession localyticsSession;
• OnCreate 함수에 아래 소스 추가
public void onCreate(Bundle savedInstanceState)
{ .
.
.
this.localyticsSession = new LocalyticsSession(this.getApplicationContext(),
"APP KEY FROM STEP 2");
this.localyticsSession.open(); // open the session
this.localyticsSession.upload(); // upload any data
.
.
.
}
76. • onResume 메소드 Override
public void onResume()
{
super.onResume();
this.localyticsSession.open();
}
• onPause 메소드 Override
public void onPause()
{
this.localyticsSession.close();
this.localyticsSession.upload();
super.onPause();
}
83. 3만 피트 vs 0 피트의 뷰.
3만 피트
• 다이어그램의 Line의 의미는?
• 의존성?
• 데이터 흐름?
• 버스와 같은 공유자원?
0 피트
• 너무 상세한 정보임.
• 전체적인 구조를 보지 못함.
88. Instability
•패키지의 움직일 수 있는 여력을 판단하는
지표
•다른 패키지에 영향을 미치지 않고,
해당 패키지를 쉽게 변경 할 수 있는가?
•Instability I = Ce / (Ca+Ce)
•Ce = Efferent Coupling (Outgoing Dependencies)
•Ca = Afferent Coupling (Ingoing Dependencies )
89. Instability
Instability I = Ce / (Ca+Ce)
당신의 패키지가 다른 사람이 많이 쓴다면,
즉 Outgoing, Ce가 많다면, 여러분의 패키지는 변경하기 어렵다.
반대로 Outgoing하는 Ce가 적다면, 여러분의 패키지는 쉽게 변경해도 된다.
즉 0.0에서 0.3이면 안정적인 버전, 0.7에서 1.0이면 불안정적인 상태다
90. Abstractness
Interface(Abstract) 와 Concrete Class를 비교
A = (#abstract classes / total # of classes)
•Abstract class = interface, abstract다 포함
•Total # class = abstract class + concrete class
•0 이면 concrete class만 있다.
•1 이면 abstract class만 있다.
91. 다시 보는 그래프
다른데서 많이 쓰는
녀석이니 조금 더
abstract를 높여야
돼!
92. 그 외 용어
•Tangled Complexity
•순환 참조가 있어 Boundary를 깰 때
•Cyclomatic Complexity
•분기 문이 많아 hotspot이 될 가망성이 높은 곳
94. # 7. UI Patterns
다양한 안드로이드 UI 기법을 소개
http://bit.ly/QyDjMV
99. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
100. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
101. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
102. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
103. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
104. 스크린샷1 스크린샷2 XML 기능 Action Action예제 색변경
Editor's Notes http://myossdevblog.blogspot.com/2009/03/microlog4android.html