Upload
youngsu-son
View
10.460
Download
0
Embed Size (px)
DESCRIPTION
안드로이드 개발에 필요한 오픈소스
Citation preview
Series1
236676546050
1162950
2197563
3805989
6253991
2010 2011 2012 2013 2014 2015
갈수록 증가하는 모바일 Traffic
단위 TB/ 월Cisco (2012), Cisco Visual Networking Index
Openness
23
58 58 61 65 68 71
84
Android Qt Symbian MeegoMozilla Webkit Linux Eclipse
안드로이드의 개방성
Vision Mobile Report July, 2011- http://bit.ly/oTmEmF
Android 의 단점을 극복할 대체제들을 잘써야 한다 .
UI
Network
Common
BaaS
android-bindingandroid-action-bar
actionbar she-lock
side-naviga-tion
android ui patterns
gson (json)Simple (REST)
Facebook (fhalo)
Android billing (In app pur-
chase)roboguice
USERGRID (BaaS Open
Source)
microlog4android sensing
User BehaviorAnalytics
Agenda• 안드로이드 이해
– Binder (Broker 패턴 ) 그리고 Intent
• 오픈 소스 그리고 사례– Simple Framework (Restful)– microlog4android– 불편하지 않은 화면 갱신 (Publisher-Subscriber)– android-actionbar (+ actionbar sherlock)– Android Binding Framework– fHalo (facebook client famework)
• 분석 방법– Localytics 사용법– STAN 을 이용한 Android App 분석 방법
Client
in args operation()
out args,return
IDLSTUBS
BinderINTERFACE
IDLSKEL
Object Adapter
Binder
IDLCompiler
OBJREF
Object
Binder Architecture
1. AIDL 파일 생성
package aexp.aidl;
// Adder service interface. interface IAdderService
{int add( in int i1, in int i2 );
}
2. AIDL 툴로 Java 파일 생성
수동 코드 생성sdk/platforms/android- <n>/tools/aidl 에 간다
C:\Android-project\ApiDemos\src\com\example\android\apis\app>aidl -IC:\An-droid-project\ApiDemos\src\ IRemoteService.aidl
Eclipse 에서는 aidl 만 넣고 빌드하면 자동으로 소스 생성 됨
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" ); }
}
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>
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" ); } };
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;
}
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" );}
} ….
Broker
Bridge
pack_datauppack_dataforward_messagetransmit_message
calls
Server-sideProxy
pack_datauppack_datacall_servicesend_response
Client-sideProxy
pack_datauppack_datasend_requestreturn
Broker
main_event_loopupdate_repositoryregister_serviceacknowledgmentfind_serverFind_clientForward_requestForward_response
Server
initializeenter_main_looprun_serviceuse_Broker_API
Client
call_serverstart_taskuse_Broker_API
transfermessage
calls
calls
uses API
transfermessage
uses API
Registration
acknowledgment
register_service()
main_evnet_loop()
Service, BR, Activity… Broker
enter_main_loop()
startInitialize()
update_repository()
Sending Request
Client Client-Side Proxy
Server-Side Proxy
Broker Server
call_server
result
send_requestpack_data
forward_request
find_server
call_serviceunpack_data
run_service
pack_dataforward_response
find_clientreturn
unpack_data
Intent 로 Activity 호출
Intent intent = new Intent(getApplicationContext(), MyOtherActivi-
ty.class);startActivityForResult(intent, SHOW_SUBACTIVITY);
그런데 , Activity 이름이 바뀌면…
그래서 묵시적 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>
호출 Intent filemanager = new Intent("filemanager.action.PICKFILES");startActivity(filemanager);
Activity 만 되는게 아님
Microlog4android 사용법• http://code.google.com/p/microlog4android/downloads/ 에서
microlog4android-1.0.0.jar 다운
• Android 프로젝트에 jar 추가
• AndroidManifest.xml 에 android.permission.WRITE_EXTERNAL_STORAG E 추가
public class LogtestActivity extends Activity {static public Logger logger = LoggerFactory.getLogger(); @Override public void onCreate(Bundle savedInstanceState) { PatternFormatter formatter = new PatternFormat-ter(); formatter.setPattern( " %d{ISO8601} [%P] %m %T " ); logger.setLevel(Level.INFO); // write to LogCat LogCatAppender logCatAppender = new LogCatAp-pender(); 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);
같이 뭉쳐 다니는 파라메터는 ParameterObject 로
묶어라 !
AfterRefactoringCustomer
+AmountInvoicedIn(Period: DateRange)+AmountRecievedIn(Period: DateRange)+AmountOverDueIn(Period: DateRange)
BeforeReactoringCustomer
+AmountInvoicedIn(start: Date, end: Date)+AmountRecievedIn(start: Date, end: Date)+AmountOverDueIn(start: Date, end: Date)
XML 파싱 이렇게 ??<categoryList> <categorys> <category> <id>1</id> <name>AA</name> <date>2011-11-01</date> </category> <category> <id>2</id> <name>BB</name> <date>2011-12-10</date> </category> </categorys> </categoryList>
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())); }else if ("name".equals(tag)) { category.setName(xpp.nextText());
}else if ("date".equals(tag)) { category.setDate(xpp.nextText());
}else{if(XmlPullParser.TEXT == xp-
p.next())xpp.nextTag();
} } else break; }
이렇게 됩니다 .<categoryList> <categorys> <category> <id>1</id> <name>fruit</name> <date>201110051200</date> </category> <category> <id>2</id> <name>animal</name> <date>201110051200</date> </category> <category> <id>3</id> <name>food</name> <date>201110051200</date> </category> </categorys> </categoryList>
@Rootpublic class CategoryList {
@ElementListprivate ArrayList<Category> categorys;
public void setCategorys(ArrayList<Category> categorys) {
this.categorys = categorys;}
public ArrayList<Category> getCategorys() {return categorys;
}}
이렇게 됩니다 .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())); }else if ("name".equals(tag)) { category.setName(xpp.nextText());
}else if ("date".equals(tag)) { category.setDate(xpp.nextText());
}else{if(XmlPullParser.TEXT == xp-
p.next())xpp.nextTag();
} } else break; }
Serializer serializer = new Persister();Reader reader = new StringReader(xmlData);CategoryList categoryList = serializer.read(CategoryList.class, reader, false);
Activ-ity
Con-tents
Provider
XXXAdapter
1. Register
SyncSer-vice
Notifi-cation
2. Insert
3. Notification
4. GetData..
@Overridepublic Uri insert(Uri uri, ContentValues values) {
String tableName;Uri contentUri;long id;
switch(matcher.match(uri)){case SITES:
tableName = Bookmark.sites._TABLENAME;contentUri = Bookmark.sites.CONTENT_URI;break;
default:throw new IllegalArgumentException();
}
id = mDB.insert(tableName, null, values);if(id > 0){
Uri itemUri = ContentUris.withAppendedId(contentUri, id);
return itemUri;}else
throw new SQLException();}
ContentValues values = new ContentValues();values.put(Bookmark.sites.NAME, stk[i][0]);values.put(Bookmark.sites.ADDRESS, stk[i][1]);getContentResolver().insert(Bookmark.sites.CONTENT_URI, values);getContentResolver().notifyChange(Bookmark.sites.CONTENT_URI, null);
# 5. UI Patterns
http://bit.ly/QyDjMV
다양한 안드로이드 UI 오픈소스들을 소개
예제 2 android-binding-frame-
work
http://code.google.com/p/android-bind-ing/ http://bit.ly/cxxwCF
94
About Graph API• Graph API
– 소셜 그래프의 Object( 친구 , 페이지 , 사진 등 ) 를 다루는 API
• Graph API 의 구조– https://graph.facebook.com/OBJECT_ID/
CONNECTION_TYPE
• ID 는 사용자 , 페이지 , 이벤트 , 사진 등의 Object ID– 약 20 개의 Object 를 지원– 모든 Object 의 ID 는 unique 하다– JSON 형태로 응답을 받는다
95
Graph API Example• https://graph.facebook.com/100001066448386/
• https://graph.facebook.com/40796308305/
신재명 ID
코카콜라 페이지 ID
96
Graph API - Connection
• Graph API 의 구조– https://graph.facebook.com/OBJECT_ID/CONNECTION_TYPE
• Connection 이란 ?– Object 의 연관 ( 관계 ) 개념
• User object 의 Connection 종류– Family, friends, album, likes, posts …– User object 경우 약 25 개의 Connection 을 제공– https://developers.facebook.com/docs/reference/api/user/ 참고
97
Connection - Example• Graph API 예시
– https://graph.facebook.com/100001066448386/friends
그럼 보안문제는 ???
98
Access Token
• 페이스북 API 를 사용하기 위해 Access Token(인증 ) 이 필요하다 .
• Graph API Explorer 를 통하여 쉽게 Access To-ken 을 받아올 수 있음
About Graph API
• Graph API Explorer– Access Token 받을 수 있다–각종 Graph API 를 테스트 해볼 수 있다
https://developers.facebook.com/tools/explorer#!/tools/explorer
101
Access Token
• 페이스북 API 를 사용하기 위해 Access Token(인증 ) 이 필요하다 .
• Graph API Explorer 를 통하여 쉽게 Access To-ken 을 받아올 수 있음
친구 리스트 가져오기– Rest FB
• Connection<User> myFriends = facebookClien-t.fetchConnection("me/friends", User.class);
– fHalo• Connection<Friends> friends =
user.friends();
피드 올리기– Rest FB
• FacebookType publishMessageResponse =facebookClient.publish("me/feed", FacebookType.-class,Parameter.with("message", "RestFB test"), Parame-ter.with(“caption", “caption test"), Parameter.with(“description", “description test"),);
– fHalo• Feed feed = new feed();
feed.setMessage("Message Test"); feed.setCaption("Caption Test"); feed.setDescrip-tion("Description Test"); user.publishFeed(me, feed);
• http://bit.ly/KnZzpx 에서 소스코드 다운
• Android 프로젝트 src/ 폴더에 소스코드 추가
• AndroidManifest.xml 에 퍼미션 추가 <uses-permission
android:name="android.permission.INTERNET“>
• 클래스 내부에 session object 추가
• Main Activity 에 Import
• OnCreate 함수에 아래 소스 추가
import com.localytics.an-droid.*;
private LocalyticsSession localytic-sSession;
public void onCreate(Bundle savedInstanceState){ .
.
.
this.localyticsSession = new LocalyticsSession(this.getApplicationContext(),
"APP KEY FROM STEP 2");this.localyticsSession.open(); // open the sessionthis.localyticsSession.upload(); // upload any data
.
.
.
}
• onResume 메소드 Override
• onPause 메소드 Overridepublic void onPause(){
this.localyticsSession.close();this.localyticsSession.upload();super.onPause();
}
public void onResume(){
super.onResume();this.localyticsSes-sion.open();
}
3 만 피트 vs 0 피트의 뷰 .
3 만 피트• 다이어그램의 Line 의 의미는 ?
• 의존성 ?• 데이터 흐름 ?• 버스와 같은 공유자원 ?
0 피트• 너무 상세한 정보임 .• 전체적인 구조를 보지
못함 .
STAN (Structure Analysis for Java)
STAN - http://stan4j.com/eclipse/eclipse-integration.html
Demo
Instability
•패키지의 움직일 수 있는 여력을 판단하는 지표
•다른 패키지에 영향을 미치지 않고 , 해당 패키지를 쉽게 변경 할 수 있는가 ?
•Instability I = Ce / (Ca+Ce)
•Ce = Efferent Coupling (Ingoing Dependencies)•Ca = Afferent Coupling (Outgoing Dependencies )
Instability
Instability I = Ce / (Ca+Ce)
당신의 패키지가 다른 사람이 많이 쓴다면 , 즉 Outgoing, Ca 가 많다면 , 여러분의 패키지는 변경하기 어렵다 .
반대로 Outgoing 하는 Ca 가 적고 , Ingoing( 다른 패키지만 사용만 하는 ) Ce,여러분의 패키지는 쉽게 변경해도 된다 .
즉 0.0 에서 0.3 이면 안정적인 버전 , 0.7 에서 1.0 이면 불안정적인 상태다
당신의 패키지를
누군가 많이 쓰고 있다면
바꾸기 쉽지 않다 .
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 만 있다 .
그 외 용어
•Tangled Complexity•순환 참조가 있어 Boundary 를 깰 때
•Cyclomatic Complexity•분기 문이 많아 hotspot 이 될 가망성이 높은 곳