2014/11/21

[Objective-C][iOS][Google]Google plus SDKで個人情報を取得

Google plus SDKを使って認証する方法を書きましたが、それをもとに、自分の情報を取得するには、どうすればいいのだろうか?

- (void)finishedWithAuth: (GTMOAuth2Authentication *)auth error: (NSError *) error {
    //errorがある場合、ない場合は、nilを返す
    if(error){
      return
    }

    GTLServicePlus* plusService = [[GTLServicePlus alloc] init];
    plusService.retryEnabled = YES;
    [plusService setAuthorizer:[GPPSignIn sharedInstance].authentication];

    GTLQueryPlus *query = [GTLQueryPlus queryForPeopleGetWithUserId:@"me"];
    [plusService executeQuery:query
        completionHandler:^(GTLServiceTicket *ticket,
                            GTLPlusPerson *person,
                            NSError *error) {
            if (error) {
                GTMLoggerError(@"Error: %@", error);
            } else {
                //person.displayName
                //person.identifer
             }
    }];
}

2014/11/20

[Objective-C][iOS][Google]Google plus SDKでサインインせずに共有

ログインないしサインインせずにGoogle plusに情報を共有できるGPPShareBuilderを読みながら写真(画像)も共有できるのかなーっと思って調べてみたんだけど、できないっぽい。

プログラム途中で書いたのになー。

2014/11/19

[iOS][Objective-C]Google plus SDKとFacebook SDKを共存させる

Google plus SDKもFacebook SDKもともにログインする時に下記のメソッドにお世話になります。

- (BOOL)application: (UIApplication *)application openURL: (NSURL *)url sourceApplication: (NSString *)sourceApplication annotation: (id)annotation
Googleの場合
- (BOOL)application: (UIApplication *)application
            openURL: (NSURL *)url
  sourceApplication: (NSString *)sourceApplication
         annotation: (id)annotation {
 return [GPPURLHandler handleURL:url
               sourceApplication:sourceApplication
                      annotation:annotation];
}
Facebookの場合
- (BOOL)application:(UIApplication *)application
            openURL: (NSURL *)url
  sourceApplication: (NSString *)sourceApplication
         annotation: (id)annotation {

        BOOL wasHandled = [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
        return wasHandled;
}
でもろどかぶりしているので、どうすればいいのかなーっと検索していたら、Handling openURL: with Facebook and Googleというエントリーを発見して、下記のようにすれば問題なく解決することができました。
- (BOOL)application:(UIApplication *)application
            openURL: (NSURL *)url
  sourceApplication: (NSString *)sourceApplication
         annotation: (id)annotation {
    if ([[url absoluteString] rangeOfString:@""].location == NSNotFound){
        BOOL wasHandled = [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
        return wasHandled;
    }else{
        return [GPPURLHandler handleURL:url sourceApplication:sourceApplication annotation:annotation];
    }
}

2014/11/18

[iOS][Objective-C]Google plus SDKを使ってログアウト

昨日のエントリーでGoogle plus SDKを使って認証(ログイン)する方法を書きました。

で今回は、ログアウトをする方法なのですが、これは簡単、以下、一文で終了します。

[[GPPSignIn sharedInstance] signOut];

2014/11/17

[iOS][Objective-C]Google plus SDKを使って認証

Google+ Platform for iOSを使ってログインをしてみる。

まずは、Start integrating Google+ into your iOS appからSDKをダウンロード

で、使うには、下記のネイティブライブラリをあらかじめインポートしておく必要がある。

AddressBook.framework
AssetsLibrary.framework
Foundation.framework
CoreLocation.framework
CoreMotion.framework
CoreGraphics.framework
CoreText.framework
MediaPlayer.framework
Security.framework
SystemConfiguration.framework
UIKit.framework
インポート完了後、さらに下のライブラリをインポートする必要がある。
GooglePlus.framework
GoogleOpenSource.framework
Google側が用意してくれているGoogle+ Sign-Inボタンを使いたい場合は、GooglePlus.bundleが必要だが、今回は、使わない。

Google Developers Consoleページのプロジェクトで左側にある「APIと認証」で「Google+ API」を有効にする。

有効になったら、今度は、「APIと認証」の直下にある「認証情報」画面で「新しいクライアントIDを作成」をクリックして「インストールされているアプリケーション」を選択してiOSにチェックを入れる。

Xcodeに記載されているバンドルIDとApp Store IDを入力後、ディープリンクを有効にして最後に「クライアントIDを作成」をクリックする。

Xcodeに戻ってターゲットのビルドセッティングのOther Linker Flagsに「-ObjC」を追加する。

Xcodeの「Info」タブの「URL type」の「identifier」と「URL schemes」にバンドルIDを設定する。

ログイン処理を行うプログラム(ここでは、UIViewControllerを継承しているプログラム)に下のようにGooglePlus.hのインポートとdelegateを設定する。
#import <GooglePlus/GooglePlus.h>
#import <GoogleOpenSource/GoogleOpenSource.h>
@interface ThisisSignInGooglePlusViewController : UIViewController <GPPSignInDelegate>
viewDidLoadメソッドで以下のように記述を行う
- (void)viewDidLoad {
  [super viewDidLoad];

  GPPSignIn *signIn = [GPPSignIn sharedInstance];
  signIn.shouldFetchGooglePlusUser = YES;
  signIn.shouldFetchGoogleUserID = YES;
  //kClientIdは、Google Developers Consoleページで作ったクライアントID
  signIn.clientID = kClientId;
  signIn.scopes = @[@"profile"];
  signIn.delegate = self;
}
Google+ Sign-In for iOSを読むと、
signIn.shouldFetchGoogleUserID = YES;
がないのだが、これがないとidが取得できなかった。

GPPSignInDelegateの処理として以下のメソッドを実行する。
- (void)finishedWithAuth: (GTMOAuth2Authentication *)auth
                   error: (NSError *) error {
    //errorがある場合、ない場合は、nilを返す
    if(error){
      return
    }
}
delegateファイルに
#import <GooglePlus/GooglePlus.h>
を設定して、下記のコードを記述する。
- (BOOL)application: (UIApplication *)application
            openURL: (NSURL *)url
  sourceApplication: (NSString *)sourceApplication
         annotation: (id)annotation {
 return [GPPURLHandler handleURL:url
               sourceApplication:sourceApplication
                      annotation:annotation];
}
でここから悩んだのだが、認証を行う場合は、以下のメソッドを実行すればいいようだ。
[signIn authenticate];
これがGPPSignIn Class Referenceの方にあったので、すごく悩んでしまった。

実際の上のような流れで試したところ、IDとかユーザー名を取得することができたので、問題ないかと思う。

2014/11/16

[Python]uuidの生成

uuidのモジュールを使えば生成できそうだ。

import uuid
hoge = uuid.uuid1()
hoge = str(hoge)

bar = uuid.uuid4()
bar = str(bar)

2014/11/15

[Python]Twitterのようにハッシュタグを検索する方法

今、新規アプリを作っているのですが、一機能の一つとして、コメントを投稿できる機能があり、Twitterのようにハッシュタグを許可しようと思うのだが、その際に、Pythonでハッシュタグを検知するにはどうすればいいのだろうか?

参考として
Twitterのつぶやきにある2つ以上の#(ハッシュタグ)にリンクをつけたいときの正規表現について
【正規表現,jQuery,PHP】twitterハッシュタグを抽出する
Pythonでの正規表現の使い方
を読んだところ、以下のような形で収束しました。

import re

p = re.compile(u"(?:^|[^ヲ-゚ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z0-9&_\/]+)#([ヲ-゚ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z0-9_]*[ヲ-゚ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z]+[ヲ-゚ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z0-9_]*)")

s = u"#foo かきくけこ #hoge #あいうえお #bar1#dfghjkl       #bar___"
s = s.replace(u' ', ' ')
m = p.findall(s)
for i in m:
  print i
実行した結果、欲しいものは得られたのですが、パターンのグループ化がまだ完全に理解できない。
import re

p = re.compile(u"(^|[^ヲ-゚ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z0-9&_\/]+)#([ヲ-゚ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z0-9_]*[ヲ-゚ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z]+[ヲ-゚ー゛゜々ヾヽぁ-ヶ一-龠a-zA-Z0-9a-zA-Z0-9_]*)")

s = u"#foo かきくけこ #hoge #あいうえお #bar1#dfghjkl       #bar___"
s = s.replace(u' ', ' ')
m = p.findall(s)
for i in m:
  print i
こうすると、余計なスペースが混入するのでそれを省くというのは、理解できるんだけど。

2014/11/14

[mac][Python]PILのインストール

どうやら、google app engineでローカルサーバーでimagesを使うには、PILを使う必要があるみたいなので、インストールしてみた。

まず、macのmavericksを使っている場合、コマンドラインツールをインストールする必要があるので、ターミナルで下記コマンドを打ってみた。

xcode-select --install
参考:Can't install PIL after Mac OS X 10.9

インストール完了後、PILの配布サイトから1.1.7 Source Kitをダウンロード。

で、READMEの指示通り、
python setup.py install
を打ってインストールしようとしたところ、permission deniedが発生してできない。

結果的に、
sudo python setup.py install
で解決したのだが、果たして、このやり方でいいのかわからない。

ただ、
from PIL import Image
をうったら正常終了したので、問題ないのかなーっと。

参考:ライブラリ:PIL

2014/11/13

[本]デザイニング・インターフェース ―パターンによる実践的インタラクションデザイン

読了

デザイニング・インターフェース ―パターンによる実践的インタラクションデザイン
Jenifer Tidwell
オライリー・ジャパン
売り上げランキング: 219,452

01 ユーザの行動
目標達成の手段
ユーザ調査の基礎
ユーザの学習意欲
パターンの解説
1 安全な探検(safe Exploration)
2 即座の喜び(instant gratification)
3 最小限での充足(satisficing)
4 途中での方針変更(changes in midstream)
5 回答の先送り(deferred choices)
6 少しずつの組み立て(incremental construction)
7 習慣化(habituation)
8 空間的な記憶(spatial memory)
9 展望的な記憶(prospective memory)
10 繰り返しの効率化(streamlined repetition)
11 キーボードのみ(keyboard only)
12 他者のアドバイス(other people's advice)

02 コンテンツを整理する
情報アーキテクチャとアプリケーション構造
情報アーキテクチャの基本:分類すること
物理的構造
パターンの解説
13 2パネルのセレクタ(two-panel selector)
14 カンバスとパレット(canvas and palette)
15 1ウィンドウでのドリルダウン(one-window drilldown)
16 代替表示(alternative views)
17 ウィザード(wizard)
18 オンデマンド追加項目(extras on demand)
19 魅力的な分岐(intriguing branches)
20 マルチレベルのヘルプ(multi-level help)

03 動き回る
ナビゲーション、標識、経路探索
いつでも居場所が分かるということ
ナビゲーションのコスト
パターンの解説
21 明快な入り口(clear entry points)
22 グローバルナビゲーション(global navigation)
23 ハブとスポーク(hub and spoke)
24 ピラミッド(pyramid)
25 モーダルなパネル(modal panel)
26 シーケンス表示(sequence map)
27 パンくず(breadcrumbs)
28 注釈つきスクロールバー(annotated scrollbar)
29 色分けしたセクション(color-coded sections)
30 アニメーションによる転換(animated transition)
31 避難口(escape hatch)

04 ページを構成する
ページ要素のレイアウト
ページレイアウトの基礎
パターンの解説
32 視覚的なフレームワーク(visual framework)
33 中央ステージ(center stage)
34 タイトルつきセクション(titled sections)
35 カードのスタック(card stack)
36 開閉可能パネル(closable panels)
37 移動可能パネル(movable panels)
38 右揃えと左揃え(right/left alignment)
39 対角線バランス(diagonal balance)
40 プロパティシート(property sheet)
41 反応的な追加表示(responsive disclosure)
42 反応的なイネーブル化(responsive enabling)
43 リキッドレイアウト(liquid layout)

05 事を行う
アクションとコマンド
限界を広げる
パターンの解説
44 ボタンのグループ(button groups)
45 アクションパネル(Action Panel)
46 目立つ「完了」ボタン(prominent "done" button)
47 動的なメニュー項目(smart menu items)
48 プレビュー(preview)
49 プログレス表示(progress indicator)
50 キャンセル機能(cancelability)
51 マルチレベルのアンドゥ(multi-level undo)
52 操作の履歴(command history)
53 マクロ(macros)

06 複合的なデータを表示する
ツリー、テーブル、その他、
インフォメーショングラフィックス
インフォメーショングラフィックスの基礎知識
パターンの解説
54 概観と詳細(overview plus detail)
55 データティップ(datatips)
56 動的なクエリ(dynamic queries)
57 データのブラッシング(data brushing)
58 部分的なズーム表示(local zooming)
59 行のストライプ配色(row striping)
60 ソート可能なテーブル(sortable table)
61 項目へのジャンプ(jump to item)
62 新規項目の入力行(new-item row)
63 カスケーディングリスト(cascading lists)
64 ツリー表示テーブル(tree table)
65 複数Y軸のグラフ(multi-y graph)
66 小さな複合データ群(small multiples)
67 ツリーマップ(treemap)

07 ユーザからの入力を受け取る
フォームとコントロール
フォームデザインの基礎知識
コントロールの選択
パターンの解説
68 寛容な入力形式(forgiving format)
69 構造化された入力形式(structured format)
70 穴埋め(fill-in-the-blanks)
71 入力ヒント(input hints)
72 入力プロンプト(input prompt)
73 オートコンプリート(autocompletion)
74 ドロップダウン式の選択(dropdown chooser)
75 画像による選択肢(illustrated choices)
76 リストビルダー(list builder)
77 よいデフォルト値(good defaults)
78 同一ページでのエラーメッセージ(same-page error messages)

08 制作ツールと編集ツール
編集ツールをデザインするための基礎
パターンの解説
79 その場での編集(edit-in-place)
80 スマート選択(smart selection)
81 合成要素の選択(composite selection)
82 1回限りのモード(one-off mode)
83 ばね式のモード(spring-loaded mode)
84 制約的リサイズ(constrained resize)
85 吸着(magnetism)
86 ガイド(guides)
87 ペーストのバリエーション(paste variations)

09 よい見た目にする
視覚的なスタイルと美学
同じ内容、違うスタイル
ビジュアルデザインの基礎
デスクトップアプリケーションにおけるビジュアルデザインの意義
パターンの解説
88 深みのある背景(deep background)
89 少色相・多明度(few hues, many values)
90 コーナー処理(corner treatments)
91 フォントを反映したボーダー(borders that echo fonts)
92 ヘアライン(hairlines)
93 フォントウェイトのコントラスト(contrasting font weights)
94 スキン(skins)

参考資料
索引
監訳者あとがき
訳者あとがき

via:目次
まぁー、出版された年月が年月なだけに、もろPC向けだよね。
携帯電話もガラケーだし。

スマホ版がほしいところ。

2014/11/12

[Google App Engine][Python]ndbを使ってimageデータを保存

今度、リリースするiOSアプリには、ndbを使うかなと思うのだが、その際に、imageの保存について確認する。

HTMLは、下のような感じで用意する。

<form action="" method="POST" enctype="multipart/form-data">
  <input type="file" name="image_file" value="ファイルを選択">
  <input type="submit" value="送信">
</form>
Python側のmodelを以下のように設定
class ImageDataStore(ndb.Model):
  image_data = ndb.BlobProperty()
送信されたときに処理を行うクラスをMainPageとすると下のようになる
class MainPage(webapp2.RequestHandler):
    def post(self):
        image_file = self.request.get('image_file')
        imagedatastore = ImageDataStore()
        imagedatastore.image_data = image_file
        imagedatastore.put()
dbの場合だと、db.Blob(image_data)という形にして保存する必要があったのですが、その必要がなさそうです。

取り出す時は、
imagedatastore = ImageDataStore()
self.response.write(imagedatastore.image_data)
という形で、無事に画像を表示することができた。
これもdbの場合、
from google.appengine.api import images
imagedatastore = ImageDataStore()
img = images.Image(imagedatastore.image_data)
self.response.write(img)
としなくちゃいけなかったんだけど。

今回は、htmlから送信した場合にうまくいったけど、果たして、iOSからだとうまくいくのだろうか?
検証は続く。