2014年7月28日 星期一

改變Estimote beacon的uuid

Here is how to do this:
1. First, start ranging for the beacons using startRangingBeaconsInRegion: with the ESTBeaconManager class: http://estimote.github.io/iOS-SDK/Classes/ESTBeaconManager.html
2. Then use connectToBeacon method in ESTBeacon class:  http://estimote.github.io/iOS-SDK/Classes/ESTBeacon.html
3. Finally change the UUID using
writeBeaconProximityUUID:withCompletion: method in ESTBeacon class:http://estimote.github.io/iOS-SDK/Classes/ESTBeacon.html
This way you can change:
- UUID only
- UUID and major
- UUID, major and minor

2014年7月25日 星期五

2014年7月23日 星期三

有時候會因為找不到segue的identifier name而crach

http://stackoverflow.com/questions/11874200/nsinvalidargumentexception-receiver-has-no-segue-with-identifier

這似乎是因為xcode的bug造成的,上面的回答是如果你run之前先clean專案,就會正常。

2014年7月21日 星期一

取得app版本和build

the "Version":
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
and the "Build":
NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey];

2014年7月20日 星期日

isKindOfClass, respondsToSelector

-(BOOL) isKindOfClass: classObj 判斷是否為某個類別或是其子類別的instance
-(BOOL) isMemberOfClass: classObj 判斷是否為某個類別的instance
-(BOOL) respondsToSelector: selector 判斷該instance是否有實作該命名的方法
+(BOOL) instancesRespondToSelector: selector 判斷該類別是否有實作該命名的方法
-(id) performSelector: selector

 //將你的方法包成selector
SEL sel = @selector (start:) ;
//判斷該instance是否有start:方法
if ([obj respondsToSelector:sel]) 
{
//執行selector方法
[obj performSelector:sel withObject:self]; 

2014年7月11日 星期五

利用Notification判斷裝置是否進入背景執行

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActiveBackground:) name:UIApplicationDidBecomeActiveNotification object:nil];
}

-(void)appDidEnterBackground:(NSNotification *)_notification
{
    isAppInBackground = YES;
    NSLog(@"App is in background");
}

-(void)appDidBecomeActiveBackground:(NSNotification *)_notification
{
    isAppInBackground = NO;
    NSLog(@"App is in foreground");
    [[UIApplication sharedApplication] cancelAllLocalNotifications];

}

2014年7月10日 星期四

還原程式碼工具

//反組譯工具 Java Decompiler
JD-GUI0.3.6_Portable.exe

//反解apk工具 apkstudio
vpz-apkstudio-net-3.5

//利用url抓取apk
http://apps.evozi.com/apk-downloader/

硬體端常識

印刷電路板 PCB (Printed Circuit Board):能將電子零組件連接在一起,使其發揮整體功能。

電子產品認證
製造商才可以申請模組認證,模組是由不同個電子元件組成的COB(chip on board),提供不同腳位可以接上不同的基板使用。
代理商只能申請end product的產品認證,一但申請完之後,就不可再變更產品內容。
藍牙一個profile要一萬NTD

2014年7月6日 星期日

能否使用App搜尋附近的wifi資訊

無法,正式的App只能抓到目前連線的wifi資訊,除非JB才可以(已經有人寫好一支app叫stumbler)。

As far as I know you can get the information about the current connected Wi-Fi using CNCopySupportedInterfaces and CNCopyCurrentNetworkInfo of CaptiveNetwork. You can refer to:How do I use CaptiveNetwork to get the current WiFi Hotspot Name for more information.
Without the use of private library (Apple80211) you can only get the SSID of the network your device is currently connected to.
You could have a look at iphone-wireless project if you are interested in Apple80211. There exists a sample app "Stumber" which does exactly what you want. But you cannot use this in your app if you want to publish to App Store because as it uses private APIs. Apple rejects apps those use private APIs.

截自http://stackoverflow.com/questions/10317028/find-available-wi-fi-networks

iOS Developer Library的範例

Reachability

https://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html
在這個Sample你可以得到「即時監控目前是否有網路連線」的code

Run loops概念

你可以把Run loop想像成是一個較為複繁的while(true)迴圈。它其實就是開一個特別的Thread,專門用來跑一些需要長時間監控的系統事件。例如,螢幕方向的改變、NSTimer的計時、手指點擊動作的觸發、或是網路連線的建立等等。

你也可以為它添加額外的事件來源,例如sockets or stream,接下來iOS會負責接管其他的事情。

Bonjour協定

Bonjour是一種Apple制定的協定,它可以讓裝置之間可以搜尋到其他遵守這個協定的裝置。

它是使用NSNetServices和CFNetServices的APIs,透過這個APIs使它可以用publishing service告知他自己的名稱以及可以用來連線的ip跟port。而其他裝置要用browsing來找到它。

2014年7月4日 星期五

iBeacon心得

1.只支援iOS7以上。Android 4.3以上。

2.只支援iPhone4S以上、iPad 第三代以上、iPad mini、iPod touch第五代以上。

3.iOS7.0.6 無法支援背景移除之後的定位更新,所以無法觸發ibeacon
iOS7.1.2可以在背景可以在移除之後,仍然能監控定位更新,所以能觸發ibeacon

4.iOS 7.1.1以前,會有手機完成掃不到ibeacon的問題,要重開機之後才能掃到,升級7.1.2之後這個問題就不再發生。

5.iBeacon : What is the difference between didEnterRegion and didDetermineState(CLRegionStateInside)
結論:
didEnterRegion / didExitRegion觸發時機

  1. 當地區轉移時,才觸發這二個方法

didDetermineState

  1. didEnterRegion / didExitRegion被呼叫時,被觸發
  2. 當requestStateForRegion被呼叫時,也會觸發
  3. 當BeaconRegion的notifyEntryStateOnDisplay被設為YES時,當使用者打開iPhone螢幕時,也會被觸發。


The location manager calls this method whenever there is a boundary transition for a region. It calls this method in addition to calling the locationManager:didEnterRegion: and locationManager:didExitRegion: methods. The location manager also calls this method in response to a call to its requestStateForRegion: method, which runs asynchronously.
So didDetermineState should get called whenever didEnterRegion/didExitRegion do. In addition, if you explicitly request the state via requestStateForRegion it will be called.
There's one other behaviour that triggers this method: if you're monitoring a region on which you've enabled the notifyEntryStateOnDisplay property, the method will be called whenever the user wakes their device manually, and they are within the region you are monitoring. From the documentation
When set to YES, the location manager sends beacon notifications when the user turns on the display and the device is already inside the region. These notifications are sent even if your app is not running. In that situation, the system launches your app into the background so that it can handle the notifications. In both situations, the location manager calls the locationManager:didDetermineState:forRegion: method of its delegate object.

6.監控beacon region的方法
使用startMonitoringForRegion:或startRangingBeaconsInRegion來啟用進入離開region的監控:
二種方式的差別在於Monitoring是以GPS的監控頻率(未知)為主,而RangingBeacons是以藍牙收廣播頻率為主(一秒一次)

//只要有狀態(unknown, inside, outside)改變時觸發:
- (void)locationManager:(CLLocationManager *)manager
      didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
//進入區域時觸發:
- (void)locationManager:(CLLocationManager *)manager
          didExitRegion:(CLRegion *)region
//離開區域時觸發:
- (void)locationManager:(CLLocationManager *)manager
         didEnterRegion:(CLRegion *)region

使用startRangingBeaconsInRegion來啟用beacon在region內的監控:
只要有手機有掃到你指定的beacon,didRangeBeacons就會被觸發,你可以在其中讀取目前beacon的狀態
- (void)locationManager:(CLLocationManager *)manager
        didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
CLBeaconRegion
You can monitor beacon regions in two ways. To receive notifications when a device enters or exits the vicinity of a beacon, use the startMonitoringForRegion: method of your location manager object. While a beacon is in range, you can also call the startRangingBeaconsInRegion: method to begin receiving notifications when the relative distance to the beacon changes.

在重開機之後會發生問題:
一,location沒有被立刻啟動,會無法偵測。
二,要重新開關一次藍牙,才會收到ibeacon,有可能是藍牙有休眠機制?

使用peripheralDataWithMeasuredPower:nil和startAdvertising來實作beacon:
time_t t;

srand((unsigned) time(&t));
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:_beaconRegion.proximityUUID major:rand() minor:rand()
                                                                identifier:_beaconRegion.identifier];

    NSDictionary *beaconPeripheralData = [region peripheralDataWithMeasuredPower:nil];
    NSLog(@"beaconPeripheralData : %@", beaconPeripheralData);

    [_peripheralManager startAdvertising:beaconPeripheralData];

7,要在AppDelegate.m中啟用beaconManager才會在背景移除情況下被觸發。

Estimote的廣播

02 01 06 //Flag[0~2]
1A       //Length
FF       //Type
4C 00    //Company ID
02 15    //Beacon Type
B9 40 7F 30 F5 F8 46 6E AF F9 25 55 6B 57 FE 6D //Proximity UUID
B1 98    //Major
B6 2E    //Minor
B6       //Measured Power
09 09 65 73 74 69 6D 6F 74 65 0E 16 0A 18 98 B1 2E B6 66 FC B6 98 B1 2E B6 00 00 00 00 00 00 00