'분류 전체보기'에 해당되는 글 366건
- 2013.11.03 Java, Objective C, C# 언어적 차이점 정리 2
- 2013.09.24 안드로이드 풀소스 부분 빌드
- 2013.09.13 Windows Push Notification Service(WNS)
- 2013.09.12 WinRT용 Cryptograph API Bouncy Castle
- 2013.09.04 DVB SI 구조분석
- 2013.08.29 iPhone Static Framework 1
- 2013.08.28 library끼리 duplicated symbol error발생 시 2
- 2013.07.15 va args 21
- 2013.07.15 sqlite3 요약
- 2013.07.11 파일경로로 음악파일 정보 얻기
안드로이드 오픈소스를 풀빌드하려고 하면 몇시간씩 걸리게 된다. 최초 빌드는 그렇게하겠지만 일부만 수정한 경우는 일부만 빌드하고자할것이다.
1. 안드로이드 소스 디렉토리로 이동한다.
2. 빌드환경을 셋팅
#. build/envsetup.sh
3. 빌드타겟을 설정한다. 환경마다 조금씩 다르겠지만 choosecombo나 lunch로 하게 되어 있다.
4. 부분빌드를 수행한다.
부분빌드는 Android.mk파일을 대상으로 진행한다. 빌드하고자 하는 부분의 Android.mk파일을 mmm으로 실행한다.
#mmm packages/app/Launcher2
mm은 해당 경로로이동 후 빌드하는것으로 mmm과 이 부분만 제외하고 동일한 작업을 한다.
빌드결과는 다음 경로아래에 lib이나 app에 위치하게 된다.
out/target/product/MODELNAME/system
http://msdn.microsoft.com/en-us/library/windows/apps/hh913756.aspx
윈도우 스토어앱을 위한 푸시서비스에 대한 MS문서 정리임
윈도우푸시서비스는 3rd party개발자가 자신의 클라우스서비스를 통해 토스트, 타일, 뱃지 또는 데이터를 전송할 수 있는 방안을 제공한다.
어떻게 동작하나?
다음 그림이 설명하고 있다.
1. 앱이 Notification Client Platform에 푸시채널을 요청한다.
2. Notification Client Platform은 WNS에 새로운 푸시채널을 질의하여 URI형태로 반환한다.
3. 앱은 푸시채널URI를 얻게 된다.
4. 당신의 클라우드서비스에 이 URI를 전달한다. 이 때 보안은 알아서 하길 바란다.
5. 클라우드서비스에서 업데이트내용을 전송하려면 채널URI로 SSL을 통해 HTTP POST request를 수행한다. 이 과정은 인증이 필요하다.
6. WNS는 request를 받아서 해당 디바이스에 전달한다.
Bouncy Castle은 자바와 C#을 지원하는
암호화관련 거의 모든 API들이 총 망라되어 있는 오픈소스이다.
아래 주소는 그 중에서 WinRT와 WP8의 오피셜사이트이다.
http://w8bouncycastle.codeplex.com/
EPG를 추출하기 위해 필요한 DVB-SI에 대해 분석한다.
주요 섹션은 다음과 같다.
NIT 현재 네트워크(방송국)에서 송출되는 모든 네트워크정보를 표현 BAT 1개이상의 채널을 하나의 그룹으로 지정함 SDT 서비스(채널)의 정보를 포함 EIT 특정서비스에 해당하는 프로그램(이벤트)의 정보를 송출함. TDT, TOT는 시간값을 송출하며 수신기는 자신의 시간을 이 값을 사용하며 맞출 수 있다.
NIT나 BAT는 부가적인 정보로 간주하고 SDT와 EIT로 프로그램가이드를 구성하는 방법에 대해 정리하겠다.
SDT 구조
service_description_section(){
table_id
section_syntax_indicator
reserved_future_use
reserved
section_length
transport_stream_id
reserved
version_number
current_next_indicator
section_number
last_section_number
original_network_id
reserved_future_use
for (i=0;i<N;i++){
service_id
reserved_future_use
EIT_schedule_flag
EIT_present_following_flag
running_status
free_CA_mode
descriptors_loop_length
for (j=0;j<N;j++){
descriptor()
}
}
CRC_32
}
PID는 0x011이며 table_id는 0x42(actual), 0x46(other)가 있다.
EIT_schedule_flag : 1이면 서비스의 EIT schedule 정보가 현재 TS에 포함됨을 의미한다. TR101 211에 더 자세한 정보가 기술되어 있다. 0이면 현재 TS에 EIT schedule정보가 없음을 의미한다.
EIT_present_following_flag : 1이면 서비스의 EIT present following정보가 현재 TS에 포함됨을 의미한다. TR101 211에 더 자세한 정보가 기술되어 있다. 0이면 현재 TS에 EIT present following 정보가 없음을 의미한다.
running_status : 서비스의 현재 상태를 나타낸다.
0 |
undefined |
1 |
not running |
2 |
starts in a few seconds(e.g. for video recording) |
3 |
pausing |
4 |
running |
5 |
reserved for future use |
EIT
PID는 0x0012이고 table_id다음과 같다.
-
1) actual TS, present/following event information = table_id = "0x4E";
-
2) other TS, present/following event information = table_id = "0x4F";
-
3) actual TS, event schedule information = table_id = "0x50" ~ "0x5F";
-
4) other TS, event schedule information = table_id = "0x60" ~ "0x6F".
event_information_section(){
table_id
section_syntax_indicator
reserved_future_use
reserved
section_length
service_id
reserved
version_number
current_next_indicator
section_number
last_section_number
transport_stream_id
original_network_id
segment_last_section_number
last_table_id
for(i=0;i<N;i++){
event_id
start_time
duration
running_status
free_CA_mode
descriptors_loop_length
for(i=0;i<N;i++){
descriptor()
}
}
CRC_32
}
service_id : 이벤트가 소속되는 서비스(채널)아이디
segment_last_section_number : sub_table을 가지는 경우 마지막섹션의 개수. 아닌경우 last_section_number와 동일하다.
last_table_id : table이 하나로만 구성되면 이 table과 동일 table_id이며 여러개로 구성된 경우 마지막 table_id를 나타낸다.
event_id : 이벤트를 구별하는 아이디
start_time : 프로그램 시작시간, UTC시간이며 시작시간이 정해지지 않은 경우 모든 비트가 1이다. 앞에서부터 16비트가 년월일이고 MJD포맷이다. 이어서 24비트가 4비트씩 시분초를 의미한다.
EXAMPLE 1: 93/10/13 12:45:00 is coded as "0xC079124500".
duration : 프로그램 방영시간. 24비트로 4비트씩 시분초를 의미한다.
running_status : 현재 상태를 의미한다.
free_CA_mode : 스크램블 여부를 의미한다.
Descriptors
각 섹션별로 추가적인 정보들이 디스크립터로 기술이 된다. 상당히 많은 디스크립터들이 정의되어 있으며 이 중에 필요한 디스크립터들만 추출해도 EPG정보구성에는 문제가 없다.
디스크립터 목록에 대한 정보는 tr101211에 기술되어 있고, 디스크립터에 대한 상세한 구조는 en_300468에 기술되어 있다.
SDT와 EIT의 디스크립터 목록은 다음과 같다.
SDT descriptors
- Announcement support descriptor
- Bouquet name descriptor
- CA identifier descriptor
- Country availability descriptor
- Data broadcast descriptor
- Linkage descriptor
- Mosaic descriptor
- Multilingual service name descriptor
- NVOD reference descriptor
- Service descriptor
- Service availability descritor
- Telephone descriptor
- Timeshifted service descriptor
EIT descriptor
- CA identifier descriptor
- Component descriptor
- Content descriptor
- Data broadcast descriptor
- Extended event descriptor
- Linkage descriptor
- Multilingual component descriptor
- Parental rating descriptor
- PDC decriptor
- Short event descriptor
- Telephone descriptor
- Time shifted event descriptor
아이폰 코드공유의 문제점
모두다 알다시피 애플은 개발자에세 아이폰용 프레임웍을 만들 수 있는 기회를 제공하지 않는다. 하지만 많은 경우 서로 다른 프로젝트나 개발자들에게 코드를 배포해야 하는 경우가 있다.
대안
몇가지 코드공유나 배포를 위한 방안이 있다.
첫번째는 코드자체를 공유 및 배포 가능하게 하는것이다. 이 방법은 XCode가 관련 매커니즘을 제공하지만 개발자가 디펜던시나 헤더파일 경로등을 추가로 해주어야 하는 불편함이 있다.
두번째는 코드가 아니라 static library로 배포하는것이다. 잘 알려진 방법이고 리눅스/유닉스 개발자를 비롯해서 아주 많은 개발자들에게 익숙한 방법이다. 하지만 몇가지 불편함이 있는데. static library는 C/C++코드로 작성이 되어지고 Objective-C의 property나 category를 사용할 수 없다. category를 static library에 추가하려면 명시적으로 링커옵션을 주어야 한다.
-ObjC
-all_load
개발자가 위 옵션을 깜박하면 런타임에러가 발생하게 된다."unrecognized selector sent to instance"
Static Framework
가장 좋은 방법은 'static framework'라고 생각한다. 이 방법은 컴파일러에게 이 라이브러리가 일반적인 아이폰 프레임웍인것처럼 인식하도록 하는 것이다. 공유하고 싶은 static library가 있다면 아주 쉽게 framework으로 만들 수 있다. 그리고 이런 프레임웍은 개발자에게 프로젝트에 추가하는것 말고 추가로 아무것도 시키지 않는다.
어떻게 만들지??
XCode에서 프레임웍으로 빌드하는 방법을 제공하지 않으므로 XCode MacOS framework template로 빌드해야 한다. 일반적인 프레임웍과 동일한 구조를 가지며 몇가지 추가적인 절차가 있다.
1. simulator와 device용을 하나로 만듦
2. framework bundle에 이전 단계에서 프레임웍 번들로 추가한다.
쉽게 작업하기 위해 쉘스크립트를 사용할것이다. lipo유틸을 사용할것인데 이 유틸은 라이브러리 여러개를 하나로 묶어주는 유틸리티이다. 마지막에 이 파일은 프레임웍번들에 복사되고 전용 링크가 생성될것이다.
FRAMEWORK=”${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework”
lipo \”${BUILD_DIR}/${CONFIGURATION}-iphoneos/libDev.a” “${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib Sim.a” -create -output “${FRAMEWORK}/Versions/Current/${PRODUCT_NAME}”cd “${FRAMEWORK}” && ln -sf “Versions/Current/${PRODUCT_NAME}” ./
3rd party library를 사용하다보면 서로 같은 심볼을 사용하게 되어서 아래와 같은 링크에러가 나는 경우가 종종 있다.
ld: duplicate symbol .objc_class_name_CJSONScanner in /Users/myappOne/TapjoyConnect/Frameworks/libTapjoyConnectSimulatorRewardInstall_Ads_Pinch.a(CJSONScanner.o) and /Developer/Projects/BuildOutput/Debug-iphonesimulator/OtherLibrary_d.a(CJSONScanner.o)
$ lipo -info libTapjoy.a
Architectures in the fat file: libTapjoy.a are: armv6 i386
armv6와 i386를 지원하는것을 알 수 있다. 여기서 armv6를 extract한다.
$ lipo -extract_family armv6 -output libTapjoy-armv6.a libTapjoy.a
$ mkdir armv6
$ cd armv6
$ ar -x ../libTapjoy-armv6.a
같은 방법으로 다른 라이브러리의 동일아키텍쳐를 extract하는데 같은 디렉토리에 한다. 그리고 다음과 같이 다시 recombine한다.
$ libtool -static -o ../lib-armv6.a *.o
아키텍쳐별로 이 과정을 마친 후 다시 lipo로 합친다.
$ cd ..
$ lipo -create -output lib.a lib-armv6.a lib-i386.a
#import <Cocoa/Cocoa.h> @interface NSMutableArray (variadicMethodExample) - (void) appendObjects:(id) firstObject, ...; // This method takes a nil-terminated list of objects. @end @implementation NSMutableArray (variadicMethodExample) - (void) appendObjects:(id) firstObject, ... { id eachObject; va_list argumentList; if (firstObject) // The first argument isn't part of the varargs list, { // so we'll handle it separately. [self addObject: firstObject]; va_start(argumentList, firstObject); // Start scanning for arguments after firstObject. while (eachObject = va_arg(argumentList, id)) // As many times as we can get an argument of type "id" [self addObject: eachObject]; // that isn't nil, add it to self's contents. va_end(argumentList); } } @end |
출처 : http://nickeys.tistory.com/archive/201108
SQL DB 엔진의 주 목적은 SQL문장을 평가 하는 것이다. 그걸 위해서, 개발자는 두 개의 객체에 대해 알 필요가 있다:
1) The database connection object: sqlite3
2) The prepared statement object: sqlite3_stmt
엄격히 따지자면, prepared_statement 객체는 꼭 필요한건 아니긴 하지만 편의를 위해서 wrapper 인터페이스들(sqlite3_exec 또는 sqlite3_get_table등)이 사용될 수 있다. 그래도, prepared statements에 대한 이해는 SQLite를 잘 사용하기 위해선 필수적이다.
The database connection과 prepared statement 객체들은 아래에 나열된 C/C++ 인터페이스 루틴의 소 집합에 의해 조작된다.
● sqlite3_open()
● sqlite3_prepare()
● sqlite3_step()
● sqlite3_column()
● sqlite3_finalize()
● sqlite3_close()
위의 루틴들의 리스트는 실재 존재하는 것이 아닌(actual) 개념적이라는 것을 알아 두자. 이 루틴들은 다양한 버전이 존재한다. 예를 들면, 사실 약간 다르긴 하지만 같은 용도의, 세 개의 분리된 루틴들(sqlite3_open(), sqlite3_open16(), sqlite3_open_v2())이 있고 위의 리스트 에서는 sqlite3_open()이라는 싱글 루틴을 보여준다. 위의 리스트에서 보여지는 "sqlite_column()"은 다양한 타입의 열 데이터를 추출하는데 사용되는 루틴들의 전체 군에 대한 place holder이다.
각각의 코어 인터페이스들의 요약이 있다:
sqlite3_open() 이 루틴은 SQLite DB파일을 열고 DB 연결 객체를 반환 한다. 이 루틴은 응용프로그램이 빈번하게 제일 먼저 호출 하는데, 대부분의 SQLite API들의 선행 조건이기 때문이다. 많은 SQLite 인터페이스들은 첫 번째 인자로 DB 연결에 대한 포인터를 요구한다. 이 루틴은 DB 객체의 생성자 역할을 한다고 할 수 있겠다.
sqlite3_prepare() 이 루틴은 SQL 문장을 prepared statement 객체로 전환하고 그 객체에 대한 포인터를 반환한다. 이 인터페이스는 앞에서 sqlite3_open()을 호출해서 만들어진 DB 연결 객체의 포인터와 SQL 문장을 포함한 문자열을 인자로 받는다. 이 API는 실재로 SQL 문장을 평가하는 것이 아니고 단지, SQL 문장에 대한 평가를 준비하는 단계이다.
새로운 응용 프로그램에서 sqlite3_prepare()의 사용은 추천되지 않는다는 것을 알아두라. 대신 sqlite3_prepare_v2()를 사용하는 게 낫다.
sqlite3_step() 이 루틴은 sqlite3_prepare() 인터페이스에서 생성된 prepared statement를 평가한다. 해당 문장은 결과의 첫 번째 행에 대한 포인터에 대해 평가 된다. 다음 열에 대해 계속해서 진행하려면, sqlite3_step()을 다시 호출하라. 해당 문장이 끝날 때까지sqlite3_step()을 계속 수행하라. 결과를 반환하지 않는 문장들(INSERT, UPDATE, DELETE)은 sqlite3_step()을 한번 호출해도 완료 된다.
sqlite3_column() 이 루틴은 sqlite3_step()에 의해 평가되고 있는 prepared statement에 대한 결과 집합의 현재 튜플로 부터 한 열을 반환한다. sqlite3_step()은 매번 새로운 결과 집합 튜플에서 멈추는데, 이 루틴은 해당 튜플에서 모든 열들의 값을 찾기 위해 여러번 호출 될 수 있다(한 튜플은 여러 열로 이뤄 지므로). 위에서 명시 된 것 처럼, SQLite API에는 "sqlite3_column()" 함수와 같은 것은 정말로 없다. 대신, 여기서 sqlite3_column()을 호출하는 것은 다양한 타입의 결과 집합으로 부터 한 값을 반환하는 함수들의 전체 집합에 대한 place holder라는 것이다. 그 결과(문자열이나 BLOB데이터일 경우)의 사이즈와 결과 집합에 있어 열의 수를 반환하는 함수 군에는 여러 루틴들이 있다.
● sqlite3_column_blob()
● sqlite3_column_bytes()
● sqlite3_column_bytes16()
● sqlite3_column_count()
● sqlite3_column_double()
● sqlite3_column_int()
● sqlite3_column_int64()
● sqlite3_column_text()
● sqlite3_column_text16()
● sqlite3_column_type()
● sqlite3_column_value()
sqlite3_finalize() 이 루틴은 sqlite3_prepare()의 호출로 부터 만들어진 prepared statement를 파괴한다. 모든 prepared statement는 메모리 누수를 막기 위해서 이 루틴을 호출해서 파괴되어야 한다.
sqlite3_close() 이 루틴은 이전에 sqlite3_open()을 호출함으로써 만들어진 DB연결을 닫는다. 모든 해당 연결에 관련된 prepared statement들은 해당 연결이 닫히기 전에 종결 되어야 한다.
private void getMusicMetaInfo(String fileStr) {
Uri fileUri = Uri.parse(fileStr);
String filePath = fileUri.getPath();
Cursor c = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null,"_data ='" + filePath + "'",null,null);
c.moveToNext();
if(c.getCount()>0) {
int id = c.getInt(0);
Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,id);
Log.d(LOG_TAG, fileStr + "'s uri : " + uri.toString());
Cursor cur = managedQuery(uri, null, null, null, null);
if(cur.moveToFirst()) {
Log.d(LOG_TAG, "==============================");
// int artistColumn = cur.getColumnIndex(MediaStore.Audio.AlbumColumns.ARTIST);
Log.d(LOG_TAG, "타이틀 : " + cur.getString(cur.getColumnIndex(MediaStore.Audio.AudioColumns.TITLE)));
Log.d(LOG_TAG, "아티스트 : " + cur.getString(cur.getColumnIndex(MediaStore.Audio.AlbumColumns.ARTIST)));
Log.d(LOG_TAG, "앨범 : " + cur.getString(cur.getColumnIndex(MediaStore.Audio.AlbumColumns.ALBUM)));
Log.d(LOG_TAG, "재생시간 : " + cur.getString(cur.getColumnIndex(MediaStore.Audio.AudioColumns.DURATION)));
Log.d(LOG_TAG, "==============================");
}
}
c.close();
Log.d(LOG_TAG, "");
}