Archive for the 'iOS' Category

2015/09/20 iPhoneから自宅/会社のMac上のAppleScriptを呼び出すEntangler

以前、Otto’s Antennaという名前で紹介したアプリケーションがバージョンアップして、「Entangler」という名前になっていました。

ちょうど、奥方様の実家のFAXの動作確認をする必要があったので、MacにFAXモデムをつないで、指定の電話番号にFAX出力するAppleScriptを書いて、iPhone上のEntanglerから呼び出してみました。

EntanglerというアプリケーションのMac版をMacにインストールし、iOS版をiPhoneにインストールして、iOS側からMac側の機能を呼び出すというのが、基本的な運用スタイルです(AppleWatch版もあるとは知りませんでした)。

前バージョンであるOtto’s Antennaよりもデザインがよくなって、iOSデバイスから操作してからの反応が速くなっていました。EntanglerはAppleScriptのほかにもAutomatorアクションやshell scriptなども実行できるそうです(AppleScriptしかテストしていないですけれども)。

Scriptを実行するMacはSleepせずに、ネットワーク(LAN/WiFi)に接続した状態にしておく必要があります。

print1.png
▲MacBook ProにUSRoboticsのUSB FAX Modem(OS X 10.10.5でも使える)をつなぎ、Sleepしないようにしてスタンバイ

print2.png
▲FAX送信元の電話番号に「ps-ax」と設定(最初に入っていた状態そのまま)

print3.png
▲Mac上のEntanglerにFAX送信するAppleScriptを登録

AppleScript名:print_a_fax
– Created 2015-09-20 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

property aPrinter : “USB Modem”
property targFaxNum : “03-XXXX-XXXX”

tell application “Safari”
  tell front document
    set aPrintSetting to {copies:1, starting page:1, ending page:9999, target printer:aPrinter, fax number:targFaxNum}
    
print with properties aPrintSetting without print dialog
  end tell
end tell

★Click Here to Open This Script 

print4.jpg
▲iPhone上のEntanglerを起動して、「print_a_fax」Scriptを実行

img_3127_resized.png
▲FAX受信中(「ps-ax」と通知が出ている)

63db476c-a6a1-4a82-8650-c79152570edd_resized.png
▲FAX受信中…

ptint0.png
▲Scriptの実行が終了すると、Macの通知センターに通知が表示される

bb1fb10f-5f86-43ed-bd72-fed8ec168e61_resized.png
▲確認のためにFAXで印刷したYahoo!のトップページ。印刷が途切れているのは、本来A4用紙が必要なところに無理やり別のサイズ(たぶんB5)の紙を突っ込んだため

2014/02/07 iPhoneからMacにAppleScriptを実行させるEventScripts+EventScripts Mobile

iOSデバイス+Mac上のAppleScript実行シリーズのしめくくりとして、Mousedown Softwareの「EventScripts」をご紹介します(現時点で、これとOtto’s Antennaの2つ以外には存在していません)。

es1.png

Mac用に「EventScripts」(原稿作成時のバージョンはv1.10 MacApp Storeで300円)というアプリがあって、マシンがシャットダウンするとかスリープするとか、Webブラウザが起動するとかいった(Mac上の)「イベント」を拾って、イベントごとに割り当てたAppleScriptを自動実行する機能を提供しています。

このEventScriptsに同じくMousedown SoftwareのiOS用(iPhone/iPad両用)リモートコントロールアプリ「EventScripts Mobile」(無料)を併用すると、iOSデバイスからWiFiネットワーク経由で、Mac上のAppleScriptをMacに実行させることができます。

es4.png

es2.png

ぱっと見、Bluetooth経由でiOSデバイス→MacにAppleScriptの実行要求をかけられそうに見えるのですが、それはできません。Bluetooth経由で3台までのデバイス(iOSでなくてもいいんでしょうね。マウスとかでも)を登録+監視することができ、Bluetoothデバイスの存在検出などのイベントをトリガーにしてAppleScriptの実行が行えるようになっています。

Otto’s Remoteと違うのは、WiFiネットワーク経由でiOSデバイス→MacへのAppleScript実行要求を出すことでしょうか。要求すると即座に実行されます。また、実行できたかどうかをiOSデバイス上で確認できます(緑で正常実行。赤だとエラー)。

img_2309.PNG

img_2310.PNG

ただし、実行結果をMacからiOSデバイスに返せないので、例によって別途さまざまなアプリケーションを経由して、実行結果を返してあげる必要がありそうです。

Otto’s RemoteがAutomator寄りだったのに対して、EventScriptsはAppleScript寄りです。というか、Automator Actionは実行できません。

EventScriptsに登録するAppleScriptは、

on run eventArgs
–なんか処理をする〜
end run

という書き方をします。このeventArgsの中にイベント発生情報が入っているようですが、どうなっているかドキュメントが存在していないので、実際に調べてみましょう。

Recordをまるごと文字化して、Console.appにsyslogとして出力することにします。

所要時間3分。あっという間にコピペで完成。

AppleScript名:イベントロガーだよ〜ん
on run eventArgs
  beep
  
–recordをstringsに変換
  
set aStr to recToString(eventArgs) of recToStrKit
  
  
logToSyslog(aStr) of me
  
end run

–Syslogにメッセージを出力する
on logToSyslog(theMes)
  do shell script “logger -s “ & quoted form of theMes
end logToSyslog

script recToStrKit
  
  
–エラートラップを使って、わざとエラーを発生させ、エラーメッセージからレコードをstringに変換する
  
on recToString(aRec)
    
    
–レコードを無理矢理stringにcastして、エラーメッセージを取得する
    
try
      set a to aRec as string –ここでエラー発生
    on error aMes
      set a to aMes
    end try
    
    
–エラーメッセージ文字列から、元のレコードの情報を組み立てる
    
set b to trimStrFromTo(a, “{”, “}”)
    
set b to “{” & b & “}”
    
    
return b
    
  end recToString
  
  
  
on trimStrFromTo(aStr, fromStr, toStr)
    –fromStrは前から探す
    
if fromStr is not equal to “” then
      set sPos to (offset of fromStr in aStr) + 1
    else
      set sPos to 1
    end if
    
    
–toStrは後ろから探す
    
if toStr is not equal to “” then
      set b to (reverse of characters of aStr) as string
      
set ePos to (offset of toStr in b)
      
set ePos to ((length of aStr) - ePos)
    else
      set ePos to length of aStr
    end if
    
set aRes to text sPos thru ePos of aStr
    
    
return aRes
    
  end trimStrFromTo
  
end script

★Click Here to Open This Script 

実際に、~/Library/Application Scripts/net.mousedown.EventScripts/フォルダに書いたAppleScriptを入れ、EventScriptsの画面上で「Add Script」で実行対象にします。その際に、応答するイベントを「EventScripts Mobile」にしておくとiOSデバイス上のEventScripts Mobileにスクリプト名が表示されます。

実行すると、ほぼ瞬間的に実行され、エラーが発生したかどうかがiOSデバイスの画面上で分ります。WiFiのネットワーク内にMacもiOSデバイスも共存できている環境であれば、Otto’s Antennaよりも使い勝手がよいと思われます。

iOS側からAppleScriptの実行をリクエストすると、Console.appの画面上に実行時のパラメータがそのまま文字で表示されます。

es5.png

Mobileからの実行イベントでは、scriptPathとtriggerの2つのパラメータが受け渡されるようです。scriptPathには実行したAppleScriptのPOSIX pathが、triggerには”EventScripts Mobile”が入っていました。

案外あっさりしている印象ですが、Mousedown SoftwareがWeb上で配布しているサンプルAppleScriptを見ると、イベントごとにAppleScriptに渡されるパラメータ(レコード)の内容が異なるようで、サンプル「Location Sample Script.scpt」では位置情報がAppleScript側に渡されることがうかがえます。

スクリプト名:Location Sample Script.scpt
on run eventArgs
  
  
– eventArgs is a record of with details of the action passed by the EventScripts application
  
– the properties passed depend on the action, however there will always be a trigger property
  
– which describes the event that triggered the script
  
  
set triggerAction to {trigger of eventArgs}
  
  
set latitude to {latitude of eventArgs} as string
  
set longitude to {longitude of eventArgs} as string
  
set previousLatitude to {previousLatitude of eventArgs}
  
set previousLongitude to {previousLongitude of eventArgs}
  
  
tell application “Finder”
    activate
    
display dialog “Your new location: “ & latitude & “, “ & longitude & return & ¬
      “Your old location: “ & previousLatitude & “, “ & previousLongitude with title triggerAction giving up after 2
  end tell
  
end run

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

どっちがいいの?

一長一短あり、EventScriptsとOtto’s Antennaのどちらをおすすめするかは、用途によると思われます。

es9.png

EventScriptは、自宅などWiFiネットワーク内にiOSデバイスもMacも共存できる場合がおすすめです。会社では、iOSデバイスのWiFiへのアクセスを禁止しているところが多いようなので、なかなか利用できないでしょう。

Otto’s Antennaは場所を選ばずに利用できるため、けっこう無茶な使い方ができそうです。ただ、リクエストしてから実行されるまでに時間がかかるのがデメリット。

こうした「iOSからAppleScript実行」系のソフトウェアが充実してくることで、さらに便利かつ強力なソリューションを構築できるようになると思われます。それぞれのソフトウェアの作者が開発を継続できるように、ぜひ購入して試してみてください。

2014/02/05 AppleScriptからiPhoneで電話をかける

AppleScriptから電話番号を指定してiPhoneで電話をかける実験です。

この手の処理では、Skype経由で電話をかけたりするのがポピュラーですが、今回はiPhone経由で電話をかけます。

あらかじめ、Macに「Dialogue」をインストール(MacApp Storeで700円、記事執筆時のバージョンはv1.2.1)しておく必要があります。

DialogueをインストールしてBluetooth経由でiPhoneとMacをペアリングすると……iPhoneにかかってきた電話をMacの画面上に通知して、Macの画面上で電話をとったり、Macのスピーカー/マイクやヘッドセットを使って通話できます。

dialogue2.png

dialogue3.png
▲Dialogueはメニューバーに常駐し、メニューバーから名前を指定して電話番号を検索して電話をかけられる(普通の使い方)

このDialogueに、隠し機能でURLスキーム経由で電話をかける機能が実装されており(作者から直接教えてもらいました)、AppleScriptで簡単な処理を書いて実行してみたところ……問題なく発信&通話できました。

dialogue1.png

▲AppleScriptから電話番号を指定して発信したあと、通話可能になったら「Macに向かって」話してください

スクリプト名:Dialogueを使ってMacからiPhone経由で電話をかける
–Dialogueを使ってMacからiPhone経由で電話をかける

set aNum to “117″ –時報
open location “x-dialogue://” & aNum

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

目下、Mavericks側のバグのせいで録音機能が使えない(Dialogueの作者Emiel Jansonいわく)ようですが、通話内容の録音もできると有用ですし……着信時と通話終了時にDialogueからAppleScriptが実行できると、手軽なCTIシステムとして利用できてよいと思います。

2014/02/02 iOSデバイスからMac上のScriptを実行するOtto’s Remote & Otto’s Antenna

Otto’s Remote & Antennaは、iOSデバイス上のOtto’s Remoteアプリケーション(100円)から、Mac上のOtto’s Antenna(記事執筆時点では200円→無料)に指令を送って、Mac上のAutomatorアクション、Shell Script、AppleScriptをMac上で実行させるソリューションです。

Otto’s RemoteはiPhoneでもiPadでも実行できるUniversalアプリですが、このアプリの性格を考えれば絶対にiPhoneで使うべきです。

AppleScript使いにとって本ソフトは、用途がありすぎてとても書き切れないほどの可能性があるので、かなりていねいにチェックしたいところです。

本Blogの性格上、Automatorとshell scriptは完全にスルーして、AppleScriptにのみフォーカスしてレビューします。

レビュー時のバージョン:
 Otto’s Antenna: ver 1.3
 Otto’s Remote: ver 1.3.2

 → Otto’s AntennaのWeb

インストールとセットアップ

最初に、iOSデバイス(iOS 6.1以降)にOtto’s Remoteを、Mac(OS X 10.8以降)にOtto’s Antennaをインストールする必要があります。また、iOSデバイスとMacの両方とも同一のApple IDを使っている必要があります。これは、Otto’s Remote/AntennaがiCloudの通知システムを利用しているためです。

同一のApple IDを使っていれば、複数のMac上のAppleScriptの実行をiPhone側から行うことも可能です。

Mac側のScriptフォルダ(~/Library/Application Scripts/com.amolloy.ottoantenna/)に入れておいたAppleScriptが、iOSデバイス側のOtto’s Remoteの画面上に表示されます。これを選択して実行することになります。

otto0.png

セットアップで悩んだり、ハマったりすることはとくにありませんでした。

さあ実行だ!

iOS上のOtto’s Remote上のScript名を(例:say Hello)タップすると、

「Are you sure you wish to perform say Hello?」

と聞かれます。選択肢は、

Yes, this time.
Yes, every time.
Yes, for all actions.
No, thank you

の4つ。

毎回実行するとか、他のアクション(script)実行時に必ず実行するとかいうのは、とっても危険な香りがする(解除方法が提供されていない)ので、正直なところ最初の「Yes, this time」と最後の「No, thank you」以外の選択肢は使わないはずです。

まずは、小手調べということで……英語のファイル名のAppleScriptをMac側のScriptフォルダに入れてiPhone側から実行。iPhoneがWiFi環境にいても、LTEのネットワーク側にいても、だいたい10秒前後でMacに指令が届いて実行されました。

実行対象のMacがスリープ状態(たとえば、MacBook Airをクローズした状態)だと、指定のAppleScriptは実行されません。「システム環境設定」のPower Napをオンにした状態でも、Scriptは実行されませんでした。これは、Otto’s Antenna側がPower Nap実行のためのサービスを実装していないことが考えられます。

【重要】Otto’s Antennaを運用させる際には、Macの電源は入れたままにしておく必要があります。

日本語にちゃんと対応しているかな?

次に、Mac側のScriptフォルダに「こんにちは」と日本語のファイル名を付けたAppleScriptを置き、iOSデバイス側でブラウズすると……「こんにちは」および「こんにちは〜」と存在しないファイルが見えてしまいます(やっぱり日本語ではテストしてないだろうな〜)。

otto1.png

img_2298.PNG

「こんにちは」Scriptは実行できましたが、「こんにちは~」Scriptはそもそも存在しないので、実行できません。

この問題は、どうやらMac側のOtto’s Antennaの問題らしく、Mac上でステータスバーのメニューから「こんにちは〜」を選択して「Delete」を実行すると、Mac側のメニューにも出なくなりますし、iOS側にも表示されなくなります。

日本語の「絵文字」(Japanese Mobile Emoji Characters)には対応しており、MacのFinder上で絵文字を入力してファイル名に絵文字を入れると、Mac上のOtto’s Antennaのメニュー上にも表示されますし、iOS上のOtto’s Remote上にも表示されます。

otto4.png

img_2299.PNG

日本語ファイル名にかぎらず、名称変更したり元のScriptが見つからなくなると、メニュー上では赤く表示されたままメニューに残ります(赤く表示するぐらいなら、メニュー上から削除したほうが)。

本気でためしてみよう!

階層構造実験

まずは、Mac側のScriptフォルダにフォルダを作成して、Otto’s Antennaがフォルダの階層構造を認識するかどうかという実験。

ためしてみると、きちんとOtto’s Antennaがフォルダ内に格納したScriptを検出しました。これについては合格点です。

AppleScriptファイル形式実験

次に、どのような形式のAppleScriptを認識・実行してくれるかどうかの実験です。目下、OS X 10.9環境の「AppleScriptエディタ」では、

 通常AppleScript:拡張子「.scpt」
 通常AppleScriptテキスト:拡張子「.applescript」
 通常AppleScriptスクリプトバンドル:拡張子「.scptd」
 AppleScriptアプレット:拡張子「.app」
 AppleScriptObjCアプレット:拡張子「.app」

を作成可能です。Otto’s Antennaが、これらのうちどこまでを「AppleScript」として扱うのかを確認しておく必要があります。

 通常AppleScript:拡張子「.scpt」→実行可
 通常AppleScriptテキスト:拡張子「.applescript」→実行可
 通常AppleScriptスクリプトバンドル:拡張子「.scptd」→実行可
 AppleScriptアプレット:拡張子「.app」→Otto’s Antennaに認識されず
 AppleScriptObjCアプレット:拡張子「.app」→Otto’s Antennaに認識されず

できることとできないことを、明確にしておくことは重要です。

位置情報をトリガーにしてAppleScript実行!

現行バージョンでは、iOSデバイス上で位置情報(Geo Location)を取得して、そこに到着するか出発するかを実行トリガとして使用できます。

バッテリーが少なくなってきたら実行とか、iOSデバイスの温度センサーが設定温度よりも低い/高い場合には実行とか、メールで呪いのメッセージが送られてきたら実行とかいう機能はありません。iOSデバイスを振ると実行とか、音声認識で実行とかはできてもいいような気もします。

実行トリガを設定できるのはよいのですが……実行時の結果をiOS上のOtto’s Remote側に返せないので、そのあたりが気になります。

また、Otto’s RemoteをiOS上でバックグラウンドに回した状態でこれを実行してくれるでしょうか?

そこで、これらを試すべく2本のAppleScriptを書き、Mac上のOtto’s Antennaに登録して実験してみました。

otto10.png

スクリプト名:メモに外出時刻を書く
–タイムスタンプからユニークなタイトルを作成
set aTitle to “てすと” & (do shell script “date +%Y%m%d%H%M%S”)
set aBody to “ぴよまるさんが、家を出ました。
Piyomaru left home.”

makeNewNoteOnNotes(aTitle, aBody, “iCloud”) of me

on makeNewNoteOnNotes(aTitle, aBody, anAccountName)
  set noteHTMLText to

"

& (aBody as Unicode text) & “”
  
  
tell application “Notes”
    –activate
    
tell account anAccountName
      make new note at folder “Notes” with properties {name:aTitle, body:noteHTMLText}
    end tell
  end tell
end makeNewNoteOnNotes

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:メモに帰宅時刻を書く
–タイムスタンプからユニークなタイトルを作成
set aTitle to “てすと” & (do shell script “date +%Y%m%d%H%M%S”)
set aBody to “ぴよまるさんが、家に帰りました。
Piyomaru return to home.”

makeNewNoteOnNotes(aTitle, aBody, “iCloud”) of me

on makeNewNoteOnNotes(aTitle, aBody, anAccountName)
  set noteHTMLText to

"

& (aBody as Unicode text) & “”
  
  
tell application “Notes”
    –activate
    
tell account anAccountName
      make new note at folder “Notes” with properties {name:aTitle, body:noteHTMLText}
    end tell
  end tell
end makeNewNoteOnNotes

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

登録したGPS位置情報から離れる(departing)/到着する(arriving)とAppleScriptの実行リクエストを行う「Geo Trigger」をそれぞれ登録。

img_2302.PNG

iPhoneの画面をオフにした状態でカバンに入れて自転車で移動。

5Kmほど離れた目的地に到着して、カバンからiPhoneを出して確認すると、通知センターに、

「Fired: メモに外出時刻を書く on MBPretina」

と表示がありました。成功です。画面表示時ではなく、はるかに前に実行されたことが確認できました。

img_2300.PNG

メモを見ると、「てすと20140202141308」のエントリが作成されており、

「ぴよまるさんが、家を出ました。
Piyomaru left home.」

と記入されていました。

帰宅時に実行されるScriptも無事動作していました。

ただ、出かける際にほぼフル充電だったバッテリーは4時間後の帰宅時には45%まで減っており、iPhone上でOtto’s Remoteを(GPS情報をトリガにするリクエストを登録して)実行させたまま1日運用するのはちょっと心もとないですね。真剣に位置情報をトリガにしたScriptを運用するのであれば、外部バッテリーの併用は欠かせないことでしょう。

Otto’s Antenna&Otto’s Remoteに必要不可欠な機能

まず、AppleScript(だけ)にパラメータを渡せないのはダメです。ダメを通り越してありえないです。早急に対応していただく必要があると思います。Otto’s Antennaが日本語の不必要なファイルをリストアップしてしまう問題も解消されるべきです。

あと、Automator Action/Shell Script/AppleScript全般に、実行結果を返せないのと、実行されたかどうかの確認ができないのもダメです。

ただし、緊急避難的にこれらの問題を解決する方法は存在しています。メモやリマインダー経由でiOSデバイスとMac間の情報のやりとりを行うというものです(もちろん、メールやメッセージ(iChat)で行ってもかまいません)。Otto’s Antenna&Remoteに多くを期待しないとそういう対応も行えます…………が、ここは少しOtto’s Antenna+Remoteでなんとかしていただきたいところです。

あとは、AppleScript側で受信できる追加パラメータとして、iOSデバイス側の実行タイムスタンプと位置情報(緯度、経度情報)が欲しいところです。

結論:こいつは使える!

本当に使えるのか半信半疑でしたが、たしかにこれは使えます。もっと注目されるべきアプリといえるでしょう。

iPhoneからMac上のAppleScriptの実行をキックできると、いろいろな処理が考えられます。

簡単なところでは、出力に時間のかかる(=出力枚数が多いので、給紙が必要+他の印刷物の状況を見る必要がある)書類の印刷を共用のカラーレーザープリンターで行う際に、プリンターの前まで行って、iPhoneから自分のデスクのMacのプリントアウトのAppleScriptを実行するとかいうのは、実際に実用性のある用途だと思います。

Mac側とiPhone側でCloudを介してデータを共用しているタイプのアプリケーションは、両者のI/O用に使えます。DropBoxなどでファイルをMacからiPhoneに渡すという処理も簡単ですし、Evernote経由でI/Oを行ってもよいと思います。

処理結果をMailやTwitter、WordPress経由で返すのも当然アリですが……データ転送量にしたがって課金されるタイプのサービスは避けたいところです。

2013/02/23 iOSアプリ「iBooks」に謎のsdefファイルが見つかった

Twitterで、

sdef1.png

という情報があったので、以前作っておいた「iOSアプリの内容をすべて展開する」AppleScriptでApple純正のiOSアプリのうちAppStoreからダウンロード可能なもの(iTunesにダウンロードしてこれるもの)をテストしてみました。

sdef10.png

sdef11.png

すると、iBooks.appにのみsdef(AppleScript命令定義)ファイルが存在していました。

sdef2.png

OS X 10.8上で、このsdefファイルをAppleScriptエディタにドラッグ&ドロップしてオープンしてみると……

sdef3.png

普通にひらけます。「ユーザーをからかうための、Appleエンジニアのジョーク」という線も考えられないではないですが、存在することは事実です。

iBooksはiBooks.appであり、MobileStore.appではありません。このMobileStore.appというのは……Googleで検索してみると、iOS上のiTunes Music Store.appのことであり、iTunes Music Store.appの中にMobileStore.sdefファイルが含まれているという情報が大量に見つかりました。

一体なぜ? いろいろ考えてしまうものですが、リリース前のテスト用だけに使っている可能性もあるので、「これで(リリース版の)iOSでAppleScriptが使えるようになるに違いない」といった証拠にはならないと思います。

以前に、某カリフォルニアの企業がiOSのテスティングエンジニアの求人条件に「AppleScriptが使えること」という採用条件を出していたので、リリース前OSやアプリの動作テスト用にAppleScriptを使っているのかもしれない、と思っていました。

先日AppleStore, Ginzaの店頭でiPadのデモンストレーションプログラムを眺めていたところ、通常のプリインストールされているアプリケーションを自動で動かしまくっていて、しかもそれがムービーに見えなかったので、案外デモ用にそうした自動操作機能が用意されているのかもしれない、などとも考えないではないです。

いずれにしても、2つのApple製アプリにsdefファイルが入っている以上の、確たる証拠はありません。

2012/08/07 iPhoneアプリをAppleScriptからコントロール

iPhoneアプリ(iOSアプリ)をAppleScriptからコントロールできるメドが立ちました。実際にAppleScriptからコントロールできています。

最初にお断りしておきますが……これは、「iPhoneアプリがiPhone実機で動いているところをAppleScript経由でコントロールする」という話ではありません。だいたい、AppleEventの仕組みが存在しないiOSに対してOS X側からネットワークごしにリモートAppleEventを投げ、応答があるわけがありません。

iphone11.jpg

Mac OS X上で稼働するiOSシミュレータ上で動くアプリをAppleScriptからコントロールした、ということです。確認はOS X 10.8+Xcode 4.4+iOSシミュレータ v5.1(272.21)で実施しました。

冷静になって考えれば、CocoaベースのアプリケーションであるiOSアプリが、特定のアプリ(iOSシミュレータ)の特定のウィンドウ上で稼働しているというのがiOSシミュレータの動作状態です(当然、例外はあると思います)。iOSアプリの作り方にもよりますし、普遍性がどの程度あるのかは保証のかぎりではありません。ただ、自分が関わっているiOSアプリケーションに対してコントロールを試みた、という話です。

この状態は、とくに変わったものではなく、一般的なCocoaアプリケーション内の1ウィンドウ内の各種GUI Elementに対してのアクセス……というとらえ方ができます。

とくに、技術的に困難な可能性はないと判断し、実際に試してみたら……当然のようにできました。

実際に、AppleScriptからiOSアプリケーションの画面上の情報を取得したり、特定のボタンをタップしたり……という操作を行えています(値の設定はかなり無理)。

自分としては、開発中の大規模なiOSアプリの画面スナップショット(画面数が多いので仕様書用の画像作成が大変)をひととおり自動作成するような自動処理を考えています。当然、書き出したあとは仕様書の中に貼り込んだ画面を最新のものにAppleScriptで自動で貼り替えることになります。このあたりは、日常茶飯事です。

よくも悪くも、「最高到達点」がその程度の処理内容にすぎないので、iOSアプリの開発資料の作成の手間を減らしたいとか、そういう「差し迫った必要性」がなければ、ほとんどのMac/iPhoneユーザーには関係のない話ではあります。

ただし、アプリ上のひととおりの画面のスナップショットを、仕様書上の画面番号を付けて指定フォルダに自動で保存できるとなれば、これは相当に便利です。

追記;予定していた仕様のものは、ひととおりできました。AppleScriptObjCでさらっと作って、便利に使えそうです。

2012/02/07 iTunesのMobileアプリをコピーしてすべて展開する

このAppleScriptは、iTunesに入っているiPhone/iPadのアプリを指定フォルダにコピーして、アーカイブを展開して、さらにアプリケーションバンドルを「ただのフォルダ」に変えるものです。

iTunesをコントロールして、iOSアプリの情報を取得しようとしても……iTunes上でアプリの情報を取得するための機能は(iTunesのAppleScript用語辞書には)一切用意されていません(selectionすら取得できないのには意図的なものを感じる)。でも、アプリの情報にアクセスするのに、iTunesの力は必要ありません。ファイル・アクセスだけで十分です。

iosap1.jpg

iOSのアプリは拡張子「.ipa」のファイルであり、このファイルはZipアーカイブの拡張子を変えただけのものなので、簡単に展開できます。

iosap2.jpg

展開すると「Payload」フォルダ内にiOSアプリケーションが展開されます。さらに、このiOSアプリの拡張子「.app」を外します。

iosap3.jpg

iOSアプリのアプリケーションバンドル中に入っている各種データをSpotlightでキーワード検索して探し出すことが可能になります。

iosap4.jpg

一度走らせれば一括処理できるので、2度目を実行する必要性はかなり低いのですが……。処理が簡単で、GUIアプリをコントロールしていないですし、処理を行ったMacBook Proでは4コアのCPUのほとんどが空いており……並列処理にはもってこいの内容です(が、使い捨ての処理なのでそこまでは……)。

とりあえず、EULAの文章などのサンプルを取り出すために、他の用件を片付けている間にAppleScriptを走らせて処理できました。予想外だったのは、すべてのアプリのアーカイブを展開したら容量が増えてHDDの空き容量が減って危ない目に……。

スクリプト名:iTunesのMobileアプリをコピーしてすべて展開する
–iTunesのデータフォルダを求める
set mFol to path to music folder
set mFolStr to mFol as string
set mFolStr to mFolStr & “iTunes:Mobile Applications:”

–home:Music:iTunes:Mobile Applicationsフォルダ内のipaファイルの一覧を取得する
try
  tell application “Finder”
    tell folder mFolStr
      set appList to (every file whose name ends with “.ipa”) as alias list
    end tell
  end tell
on error
  display dialog “Mobile Applicationsフォルダが存在しないか、Mobileアプリが存在しません。” buttons {“OK”} default button 1 with icon 1
  
return
end try

–ipaファイルを処理するループ
set appProcTmp to choose folder with prompt “iOSアプリケーションを展開する作業フォルダを指定”

set aCount to 1 –フォルダ名のカウンタ

repeat with i in appList
  –ipaからzipにリネーム
  
set j to contents of i
  
  
tell application “Finder”
    
    
–新規フォルダ作成
    
set newFolder to (make new folder at appProcTmp with properties {name:aCount as string})
    
set newFolder to newFolder as alias
    
    
–ipaファイルをコピー
    
set anAppFile to (duplicate j to newFolder)
    
set anAppFile to anAppFile as alias
    
    
–ipaファイルをzipにリネーム
    
set aName to name of anAppFile
    
set bName to retNameFromFilenameStr(aName) of me
    
set bName to bName & “.zip”
    
    
set name of anAppFile to bName –rename
    
  end tell
  
  
–unzipを実行してzipアーカイブを展開
  
set tmpFolPath to POSIX path of newFolder
  
set tmpPathPOSIXfull to POSIX path of anAppFile
  
try
    do shell script “cd “ & quoted form of tmpFolPath & ” && unzip “ & quoted form of tmpPathPOSIXfull
  on error erMes
    return {false, erMes}
  end try
  
–展開ここまで
  
  
  
–展開後のアプリケーションバンドルをただのフォルダに変える
  
tell application “Finder”
    tell folder (newFolder as string)
      tell folder “Payload”
        set appFileList to (every file whose name ends with “.app”)
        
set appFile to (contents of first item of appFileList) as alias
        
        
set tmpName to name of appFile
        
set newAppName to retNameFromFilenameStr(tmpName) of me
        
set name of appFile to newAppName
      end tell
    end tell
  end tell
  
  
  
set aCount to aCount + 1
  
end repeat

–ファイル名文字列から拡張子を外して返す
on retNameFromFilenameStr(fileNameStr)
  set fLen to length of fileNameStr
  
set revText to (reverse of (characters of fileNameStr)) as string –逆順テキストを作成
  
set anOffset to offset of “.” in revText
  
set fRes to text 1 thru (fLen - anOffset) of fileNameStr
  
return fRes
end retNameFromFilenameStr

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に