40歳からのキャリアチェンジ

20代はエンジニア・PM、30代はWeb系エンジニア向けのキャリアアドバイザー。40代の今はフリーランスで開発含めて色々やってます。技術ネタとしてはRuby/RailsとJavaScript関連あたり

Titanium3.x で Titanium Cloud Services+Facebookアカウントの連携機能が思いのほか難しかったのでまとめてみた

はじめに

クラフトビールのアプリを作ってて、お店の情報が400件近くあると

「あ、今度このお店行きたいからブックマーク的な機能がほしい」 「ここで、xxが買えたからメモっておきたい」

という気持ちが出てきてお気に入り的な機能は最低限必須かなと思い以下のようなことを検討しました

  • ユーザ別のお気に入りのお店情報をTitanium Cloud Servicesにて管理する。具体的には登録して有るお店情報に対するReviewsオブジェクトを生成する。
  • ユーザ情報はTitanium Cloud Services+Facebookアカウントの連携機能をベースにする。(Facebookアカウントを持っていない人の場合を想定して、別途ユーザアカウント作成を作る予定)

やりたいことはシンプルなのでAppceleratorのドキュメントにあるサンプルコードをそのまま流用すればOK・・・と考えていたのですが、Titanium Mobile&Cloud に関するドキュメントの細かい所を読み落としていたせいで、思いのほか難しく感じた部分があったので情報まとめておくことにしました。

まずは結論から:コードを書くだでは済まずtiapp.xmlの修正などいくつか細かい作業が必要になる

  • Titanium Mobileの tiapp.xml の修正
  • Titanium MobileのInfo.plistFacebookのアプリの設定
  • Facebookのアプリの設定

なお文中のAppIDのinfo.h5y1m141.CBFanはサンプルアプリとして作ったものなので、ここは適宜読み替えてください

Titanium Mobileの tiapp.xml

以下の記述を追加する

<property name="ti.facebook.appid">info.h5y1m141.CBFan</property>

Info.plist

Info.plist の修正が必須かどうか正直わからないのですが、いくつか見る情報だとこの修正もしたほうが良いみたいです

<array>
  <dict>
    <key>CFBundleURLName</key>
    <!-- xxxの所は以下ご自身が作ってるアプリケーションのAppIDを入力 -->
    <string>xxxx</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>app</string>
      <!-- fb以降のxxxの所はFacebookのAppIDを入力。 -->
      <string>fbxxxx</string>
    </array>
  </dict>
</array>

Facebookのアプリの設定

  • facebook developersにアクセスする
  • 「設定を編集」ボタンをクリックして基本設定画面が表示されます。

f:id:h5y1m141:20130703073023p:plain

  • アプリをFacebookに結合する方法を選択の項目に「ネイティブiOS」という項目があり、「アプリバンドルID」という項目にAppIDの「info.h5y1m141.CBFan」を入力します。

f:id:h5y1m141:20130703073035p:plain

ソースコードサンプル

この準備が出来てれいば後は以下のようにすることでTitanium Cloud Services+Facebookアカウントの連携が出来ました。

app.coffee

FacebookTab = require("ui/facebookTab")
facebookTab = new FacebookTab()
tabGroup = Ti.UI.createTabGroup
  tabsBackgroundColor:"#f9f9f9"
  shadowImage:"ui/image/shadowimage.png"

tabGroup.addTab facebookTab
tabGroup.open()

config.json

{
  "facebook":{
    "appid": FacebookのAppIDを入力,
    "secret": "FacebookのsecretKeyを入力"
  }
}

facebookTab.coffee

class facebookTab
  constructor:() ->
    baseColor =
      barColor:"#f9f9f9"
      backgroundColor:"#dfdfdf"
      keyColor:"#EDAD0B"

    fb = require('facebook');
    fb.appid = @_getAppID()
    fb.permissions =  ['read_stream']
    fb.forceDialogAuth = false
    that = @
    fb.addEventListener('login', (e) ->
      
      token = fb.accessToken
      _Cloud = require('ti.cloud')
      
      if e.success
        if e.success

          _Cloud.SocialIntegrations.externalAccountLogin
            type: "facebook"
            token: token
          , (e) ->
            if e.success
              user = e.users[0]
              Ti.API.info "User  = " + JSON.stringify(user)
              Ti.App.Properties.setString "cbFan.currentUserId", user.id
              that._userSection(user)
            else
              alert "Error: " + ((e.error and e.message) or JSON.stringify(e))
        
      else if e.error
        alert e.error
      else alert "Canceled"  if e.cancelled
    )
    fb.addEventListener('logout',(e)->
      alert 'logout'
    )
    fb.authorize()  unless fb.loggedIn
    button = Ti.UI.createButton
      title: "Facebook auth"
      top:30
      left:30
    button.addEventListener "click", (e) ->
      fb.reauthorize ["read_stream"], "me", (e) ->
        if e.success
          Ti.API.info "If successful, proceed with a publish call"
        else
          if e.error
            alert e.error
          else
            alert "Unknown result"
    button.hide()      
    

    facebookWindowTitle = Ti.UI.createLabel
      textAlign: 'center'
      color:'#333'
      font:
        fontSize:'18sp'
        fontFamily : 'Rounded M+ 1p'
        fontWeight:'bold'
      text:"アカウント設定"

    fbLoginButton = fb.createLoginButton
      top:5
      left:5
      style : fb.BUTTON_STYLE_WIDE
      
    cbFan.facebookWindow = Ti.UI.createWindow
      title:"アカウント設定"
      barColor:baseColor.barColor
      backgroundColor: baseColor.backgroundColor
      tabBarHidden:false

    cbFan.facebookWindow.add button
    cbFan.facebookWindow.add fbLoginButton
    
    if Ti.Platform.osname is 'iphone'
      cbFan.facebookWindow.setTitleControl facebookWindowTitle

    facebookTab = Ti.UI.createTab
      window:cbFan.facebookWindow
      barColor:"#343434"
      icon:"ui/image/tab2ic.png"

    return facebookTab
    
  _getAppID:() ->
    # Facebook appidを取得
    config = Titanium.Filesystem.getFile(Titanium.Filesystem.resourcesDirectory, "config.json")
    file = config.read().toString()
    json = JSON.parse(file)
    appid = json.facebook.appid
    return appid
    
  _userSection:(user) ->
    baseColor =
      barColor:"#f9f9f9"
      backgroundColor:"#dfdfdf"
      keyColor:"#EDAD0B"

    rows = []
    table = Ti.UI.createTableView
      backgroundColor: baseColor.backgroundColor
      style: Titanium.UI.iPhone.TableViewStyle.GROUPED
      width:'auto'
      height:'100'
      top:50
      left:0
      
    menuHeaderView = Ti.UI.createView
      backgroundColor:baseColor.backgroundColor
      height:30
      
    menuHeaderTitle = Ti.UI.createLabel
      top:0
      left:5
      color:'#333'
      font:
        fontSize:18
        fontFamily :'Rounded M+ 1p'
      text:'アカウント情報'
      
    menuHeaderView.add menuHeaderTitle
    
    menuSection = Ti.UI.createTableViewSection
      headerView:menuHeaderView
      
    nameRow = Ti.UI.createTableViewRow
      backgroundColor:baseColor.backgroundColor
      height:40
      className:"facebook"
      
    nameLabel = Ti.UI.createLabel
      text: "#{user.first_name} #{user.last_name}"
      width:280
      color:"#333"
      left:5
      top:5
      font:
        fontSize:18
        fontFamily :'Rounded M+ 1p'
        fontWeight:'bold'
        
    nameRow.add nameLabel      
    menuSection.add nameRow

    rows.push menuSection
    
    table.setData rows
    cbFan.facebookWindow.add table
    return
module.exports =  facebookTab

forceDialogAuthとか、色々まだ理解が浅い所がある

ドキュメントにはforceDialogAuthはfalseにしろって書かれていたけど、そもそもこのプロパティが何なのかよくわからなかったのですが

true:これまでの慣れ親しんだ(?)Facebookのユーザアカウント、パスワード入力を促すダイアログが表示される false:ダイアログが非表示になりiOS 6のFacebook連携機能を利用する

という感じみたいですが、それ以外にも fb.reauthorize に関する部分などまだ色々理解が浅い所があるので、気が向いたらその辺りもう少しまとめようかと思ってます

参考になったページ

物凄くドツボにはまっていた時に、Titanium SDK 3.1.0 対応で色々大変だったというメモというページを見つけて、ここから突破口が開けたのでとても感謝しています!