@blog.justoneplanet.info

日々勉強

Xcode4とgitignore

なかなか良い設定が見つからない。現状のgitignoreは以下のようになっている。

# Xcode
build/*
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
*.xcworkspace
!default.xcworkspace
xcuserdata
profile
*.moved-aside
DerivedData

# osx noise
.DS_Store

途中で変更した場合は以下のコマンドでgit管理から外す。

git rm --cached filename

Fragmentを使ったtabの中のWebViewの戻るボタンを実装する

Fragmentを使ったタブの実装がドキュメントに書かれている。TabManagerの内部クラスTabInfoにgetterを実装する。

    static final class TabInfo {
        private final String tag;
        private final Class<?> clss;
        private final Bundle args;
        private Fragment fragment;

        TabInfo(String _tag, Class<?> _class, Bundle _args) {
            tag = _tag;
            clss = _class;
            args = _args;
        }

        public Fragment getFragment() {
            return fragment;
        }
    }

activityに以下のコードを記述する。

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            WebView webView = (WebView) mTabManager.mLastTab.getFragment().getView().findViewById(R.id.webview);
            if (webView != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                if (webView.canGoBack()) {
                    webView.goBack();
                    return true;
                }
                else {
                    finish();
                }
            }
        }
        return super.dispatchKeyEvent(event);
    }

HMAC-MD5を計算する

■PHP

hash_hmac('md5', $str, 'key');

■Python

import hmac
from hashlib import sha1
from hashlib import md5
hmac.new("key", "value", md5).hexdigest()
hmac.new("key", "value", sha1).hexdigest()

■Android

public class HmacMD5 {
private static final String ALGORISM = “HmacMD5”;
private static final String S = “key”;
public static String get(String str) {
SecretKeySpec secretKeySpec = new SecretKeySpec(S.getBytes(), ALGORISM);
try {
Mac mac = Mac.getInstance(ALGORISM);
mac.init(secretKeySpec);
byte[] result = mac.doFinal(str.getBytes());
return byteToString(result);
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (InvalidKeyException e) {
e.printStackTrace();
}
return “”;
}

private static String byteToString(byte [] b) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < b.length; i++) { int d = b[i]; d += (d < 0)? 256 : 0; if (d < 16) { buffer.append("0"); } buffer.append(Integer.toString(d, 16)); } return buffer.toString(); } } [/sourcecode]

■iOS

日本語入力に対応するためにstackoverflowから持ってきたコードに少々手を入れた。

+ (NSString *)HMACMD5WithKey:(NSString *)data
{
const char *cKey = [@”key” cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [data cStringUsingEncoding:NSUTF8StringEncoding];
const unsigned int blockSize = 64;
char ipad[blockSize];
char opad[blockSize];
char keypad[blockSize];

unsigned int keyLen = strlen(cKey);
CC_MD5_CTX ctxt;
if (keyLen > blockSize) {
CC_MD5_Init(&ctxt);
CC_MD5_Update(&ctxt, cKey, keyLen);
CC_MD5_Final((unsigned char *)keypad, &ctxt);
keyLen = CC_MD5_DIGEST_LENGTH;
}
else {
memcpy(keypad, cKey, keyLen);
}

memset(ipad, 0x36, blockSize);
memset(opad, 0x5c, blockSize);

int i;
for (i = 0; i < keyLen; i++) { ipad[i] ^= keypad[i]; opad[i] ^= keypad[i]; } CC_MD5_Init(&ctxt); CC_MD5_Update(&ctxt, ipad, blockSize); CC_MD5_Update(&ctxt, cData, strlen(cData)); unsigned char md5[CC_MD5_DIGEST_LENGTH]; CC_MD5_Final(md5, &ctxt); CC_MD5_Init(&ctxt); CC_MD5_Update(&ctxt, opad, blockSize); CC_MD5_Update(&ctxt, md5, CC_MD5_DIGEST_LENGTH); CC_MD5_Final(md5, &ctxt); const unsigned int hex_len = CC_MD5_DIGEST_LENGTH*2+2; char hex[hex_len]; for(i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { snprintf(&hex[i*2], hex_len-i*2, "%02x", md5[i]); } NSData *HMAC = [[NSData alloc] initWithBytes:hex length:strlen(hex)]; NSString *hash = [[[NSString alloc] initWithData:HMAC encoding:NSUTF8StringEncoding] autorelease]; [HMAC release]; return hash; } [/sourcecode]

ZXingをXcodeプロジェクトに組み込む

■組込

zxing-x.x/iphone/ZXingWidget/を自身のプロジェクトのプロジェクトナビゲーターにドロップする。

Targets > Build Phases

Target DependenciesでZXingWidgetを追加した後、Link Binary With Librariesで以下を追加する。

  • libZXingWidget.a
  • libiconv.dylib
  • CoreMedia.framework
  • CoreVideo.framework
  • AVFoundation.framework
  • AudioToolbox.framework
  • AddressBook.framework
  • AddressBookUI.framework
  • CoreGraphics.framework

Project > Build Settings

Header Search Pathsに以下の項目を追加する。

  • /User/[your name]/zxing-x.x/iphone/ZXingWidget/Classes
  • /User/[your name]/zxing-x.x/cpp/core/src

前者はrecursiveにチェックを入れて、後者はチェックを入れない。

参考

■実装

ScanViewController.h

#import <UIKit/UIKit.h>
#import "ZXingWidgetController.h"

@interface ScanViewController : UIViewController<ZXingDelegate>{
    UITextView *resultView;
    NSString *resultStr;
}
@property (nonatomic, retain) UITextView *resultView;
@property (nonatomic, copy) NSString *resultStr;
- (void)scanPressed:(id)sender;
@end

ScanViewController.mm

ファイルの拡張子を.mmとしないとコンパイルできない。

#import "ScanViewController.h"
#import "QRCodeReader.h"

@implementation ScanViewController
@synthesize resultView;
@synthesize resultStr;

- (void)scanPressed:(id)sender
{
    ZXingWidgetController *widController = [[ZXingWidgetController alloc] initWithDelegate:self showCancel:YES OneDMode:NO];
    QRCodeReader* qrcodeReader = [[QRCodeReader alloc] init];
    NSSet *readers = [[NSSet alloc ] initWithObjects:qrcodeReader,nil];
    [qrcodeReader release];
    widController.readers = readers;
    [readers release];

    [self presentModalViewController:widController animated:YES];
    [widController release];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}
- (void)dealloc {
    [resultView release];
}

#pragma mark - View lifecycle
- (void)loadView
{
    [super loadView];
    
    UIButton *btnStamp = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [btnStamp setFrame:CGRectMake(40, 220, 240, 50)];
    [btnStamp setTitle:@"QRコードを読み取る" forState:UIControlStateNormal];
    [btnStamp setTag:1];
    [btnStamp addTarget:self action:@selector(scanPressed:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btnStamp];
    
    resultView = [[UITextView alloc] initWithFrame:CGRectMake(40 , 280, 240, 50)];
    [self.view addSubview:resultView];
}
- (void)viewDidUnload
{
    [super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark -
#pragma mark ZXingDelegateMethods
- (void)zxingController:(ZXingWidgetController*)controller didScanResult:(NSString *)result {
    self.resultStr = result;
    if (self.isViewLoaded) {
        [resultView setText:resultStr];
        [resultView setNeedsDisplay];
    }
    [self dismissModalViewControllerAnimated:NO];
}
- (void)zxingControllerDidCancel:(ZXingWidgetController*)controller {
    [self dismissModalViewControllerAnimated:YES];
}
@end

こんな感じで。