顯示具有 objective c 標籤的文章。 顯示所有文章
顯示具有 objective c 標籤的文章。 顯示所有文章

2015年11月25日 星期三

iOS 開發筆記 - 把玩 Chromecast SDK 播放網路連結(圖片、影片)

買了一隻 Chromecast ,除了試用產品外,也想試試看 Chromecast SDK 。快速翻了一下 iOS App Development - ios sender 文件,還是不得其門而入 XD 最後還是乖乖看範例程式:https://github.com/googlecast/CastVideos-ios

簡言之,我是使用 Cocoapods 管理 Chromecast SDK 的:

$ vim Podfile
pod 'google-cast-sdk'
pod 'google-cast-remote-display-sdk'


接著寫一點程式,參考 CastVideos-ios 內的 CastDeviceController 範例了解整個流程。

總之,若要簡單播放一個 URL ,需要依序完成以下動作:

  1. 搜尋 chromecast device 並實作 GCKDeviceScannerListener 偵測裝置
    • GCKFilterCriteria *filterCriteria = [GCKFilterCriteria criteriaForAvailableApplicationWithID:kGCKMediaDefaultReceiverApplicationID];
    • self.chromecastScanner = [[GCKDeviceScanner alloc] initWithFilterCriteria:filterCriteria];
    • [self.chromecastScanner addListener:self];
    • [self.chromecastScanner startScan];
  2. 透過 - (void)deviceDidComeOnline:(GCKDevice *)device 偵測到後,進行連線
    • self.chromecastManager = [[GCKDeviceManager alloc] initWithDevice:self.chooseDevice clientPackageName:[NSBundle mainBundle].bundleIdentifier];
    • self.chromecastManager.delegate = self;
    • [self.chromecastManager connect];
  3. 連線裝置後,透過 Launch application 跟 Chromecast Device 進行溝通
    • [self.chromecastManager launchApplication:kGCKMediaDefaultReceiverApplicationID];
  4. 透過 - (void)deviceManager:(GCKDeviceManager *)deviceManager didConnectToCastApplication:(GCKApplicationMetadata *)applicationMetadata sessionID:(NSString *)sessionID launchedApplication:(BOOL)launchedApplication; 偵測完成 chromecast app 程式啟動並建立 GCKMediaControlChannel
    • self.mediaControlChannel = [[GCKMediaControlChannel alloc] init];
    • self.mediaControlChannel.delegate = self;
    • [deviceManager addChannel:self.mediaControlChannel];
    • [self.mediaControlChannel requestStatus];
  5. 播放 Resource,以 http://www.w3schools.com/html/mov_bbb.mp4 為例
    • NSMutableArray *tracks = [[NSMutableArray alloc] init];
    • GCKMediaMetadata *metadata = [[GCKMediaMetadata alloc] initWithMetadataType:GCKMediaMetadataTypeGeneric];
    • GCKMediaInformation *mi = [[GCKMediaInformation alloc] initWithContentID:@"http://www.w3schools.com/html/mov_bbb.mp4" streamType:GCKMediaStreamTypeNone contentType:nil metadata:metadata streamDuration:0 mediaTracks:tracks textTrackStyle:[GCKMediaTextTrackStyle createDefault] customData:nil];
    • [self.mediaControlChannel loadMedia:mi autoplay:YES];

如此一來 Chromecast device 就會播放指定的連結啦。

2014年8月10日 星期日

iOS 開發筆記 - 透過 CocoaPods - FMDB / FMDatabase 管理 SQLite Databases

好久沒用 C/C++ 處理 SQLite 的操作,原本有意直接在 Objective-C 一樣寫 C 來處理,但想起來最近一直把玩 CocoaPods ,就搜尋一下,發現 FMDB 還滿多的推薦的,且 github.com/ccgus/fmdb 上頭也有很猛的人數 XD 就下海來使用 FMDB 啦!

主要看中 FMDB 的特色:提供 Data Sanitization 機制!就是寫 PHP 時,會透過 mysql_real_escape_string 來處理 raw data ,避免資料格式破壞 SQL 語法。

把玩筆記:

#import "FMDatabase.h"
// $ vim Podfile
// pod 'FMDB'

- (void)insert {
// Documents/test.db
NSString *dbPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"test.db"];
BOOL needInitTable = ![[NSFileManager defaultManager] fileExistsAtPath:dbPath];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
if ([db open]) {
// init table
if (needInitTable && ![db executeStatements:@"CREATE TABLE IF NOT EXISTS t (id VARCHAR(8), number INT)"]) {
NSLog(@"table init error");
return;
}

// insert data
if (![db executeUpdate:@"INSERT OR IGNORE INTO t (id, number) VALUES ( :id, :number )" withParameterDictionary:@{
@"id" : @"id_data",
@"number": @(12345)
}] ) {
NSLog(@"insert error");
}
[db close];
}
}

- (NSArray *)query {
// Documents/test.db
NSString *dbPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"test.db"];
BOOL needInitTable = ![[NSFileManager defaultManager] fileExistsAtPath:dbPath];
FMDatabase *db = [FMDatabase databaseWithPath:dbPath];
if (!needInitTable) {
if ([db open]) {
NSMutableArray *output = [[NSMutableArray alloc] init];
FMResultSet *rs = [db executeQuery:"SELECT id, number FROM test;"];
while ([rs next]) {
// records to NSArray
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];

item[@"id"] = [rs stringForColumn:@"id"];
item[@"number"] = @([rs intForColumn:@"number");

[output addObject:item];
}
[db close];
return output;
}
}
return @[];
}

2014年7月23日 星期三

iOS 開發筆記 - 使用 UITapGestureRecognizer / UISwipeGestureRecognizer 偵測 UIView Click/Tap/Swipe Event (手指點擊、滑動事件)

沒把玩過,趁颱風天筆記一下 :P

One Click (Single Tap):

- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tapGestureRecognizer;
tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)];
tapGestureRecognizer.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tapGestureRecognizer];
}

- (void)singleTap:(UIGestureRecognizer *)recognizer {
NSLog(@"singleTap: %@", NSStringFromCGPoint([recognizer locationInView:[recognizer.view superview]]));
}


Double Click (Double Tap):

- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tapGestureRecognizer;
tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap:)];
tapGestureRecognizer.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:tapGestureRecognizer];
}

- (void)doubleTap:(UIGestureRecognizer *)recognizer {
NSLog(@"doubleTap: %@", NSStringFromCGPoint([recognizer locationInView:[recognizer.view superview]]));
}


Swipe Up:

- (void)viewDidLoad {
[super viewDidLoad];
UISwipeGestureRecognizer *swipeGestureRecognizer;
swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeUp:)];
swipeGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
[self.view addGestureRecognizer:swipeGestureRecognizer];
}

- (void)swipeUp:(UIGestureRecognizer *)recognizer {
NSLog(@"swipeUp: %@", NSStringFromCGPoint([recognizer locationInView:[recognizer.view superview]]));
}


Swipe Down:

- (void)viewDidLoad {
[super viewDidLoad];
UISwipeGestureRecognizer *swipeGestureRecognizer;
swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeDown:)];
swipeGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown;
[self.view addGestureRecognizer:swipeGestureRecognizer];
}

- (void)swipeDown:(UIGestureRecognizer *)recognizer {
NSLog(@"swipeDown: %@", NSStringFromCGPoint([recognizer locationInView:[recognizer.view superview]]));
}


Swipe Left:

- (void)viewDidLoad {
[super viewDidLoad];
UISwipeGestureRecognizer *swipeGestureRecognizer;
swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)];
swipeGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeGestureRecognizer];
}

- (void)swipeLeft:(UIGestureRecognizer *)recognizer {
NSLog(@"swipeLeft: %@", NSStringFromCGPoint([recognizer locationInView:[recognizer.view superview]]));
}


Swipe Right:

- (void)viewDidLoad {
[super viewDidLoad];
UISwipeGestureRecognizer *swipeGestureRecognizer;
swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRight:)];
swipeGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeGestureRecognizer];
}

- (void)swipeRight:(UIGestureRecognizer *)recognizer {
NSLog(@"swipeRight: %@", NSStringFromCGPoint([recognizer locationInView:[recognizer.view superview]]));
}


其他部分,大概是注意 UIView 跟 UIViewController 內定已經有把 events 接收處理的事項,例如 UIScrollView 就有捲動事件,假設 UIScrollView 只有提供左右捲動的功能,那就偵測不到 SwipeLeft 跟 SwipeRight ,但 SwipeUp 跟 SwipeDown 仍可以。而 Single Tap 跟 Double Tap 之間,基本上兩者存在時,點擊兩下的過程中,Single Tap Action 跟 Double Tap Action 都會被執行,並且 Single Tap Action 會先被執行。

2014年3月12日 星期三

iOS 開發筆記 - NSData to HEX NSString

最近把玩 Apple Push Notification service 時,需要將 App 取得的 Device Token 轉成 HEX String 來使用。

- (NSString *)getHEX:(NSData *)data
{
    const unsigned char *dataBytes = [data bytes];
    NSMutableString *ret = [NSMutableString stringWithCapacity:[data length] * 2];
    for (int i=0; i<[data length]; ++i)
        [ret appendFormat:@"%02X", (NSUInteger)dataBytes[i]];
    return ret;

}

2014年3月11日 星期二

iOS 開發筆記 - 使用 MD5

忽然發現,自己在 iOS 上沒有用過 MD5 耶,一定是太少寫程式了 Orz

#import <CommonCrypto/CommonDigest.h>

- (NSString *)md5:(NSString *)str
{
    const char *cStr = [str UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5( cStr, strlen(cStr), result );
    return [NSString
            stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
            result[0], result[1],
            result[2], result[3],
            result[4], result[5],
            result[6], result[7],
            result[8], result[9],
            result[10], result[11],
            result[12], result[13],
            result[14], result[15]
            ];

}


驗證方式:

$ echo -n "string" | md5

參考資料:Calculate MD5 on iPhone