在使用Adobe AIR進行移動應用開發的時候,我們或許會有這樣的需求:假如我們開發的是兩個應用(A和B),同時安裝到手機上,那么能否在A中呼叫B並傳遞參數呢(或者反過來B操作后,再把參數返回給A)。目前AIR還沒有直接呼叫某個APP的API,但我們可以使用手機特有的特性來實現。
第一種方式:使用ANE
假如我們的目標平台是Android,那么可以確定的是,Java是可以呼叫一個APP並傳遞參數的,所以我們可以借助Java實現的ANE來調用另一個APP(只要知道另一個APP的ID就可以了)。
首先打開Eclipse,創建一個Android項目,引入FlashRuntimeExtensions.jar,編寫Extension,Context和Function(具體過程不再細述了,可以參閱創建ANE的初級教程),也可以在稍后的鏈接中下載Java部分的代碼。主要是實現callApp這個Function,代碼如下:
package com.techmx.extensions; import android.app.Activity; import android.content.Intent; import android.net.Uri; import com.adobe.fre.FREContext; import com.adobe.fre.FREFunction; import com.adobe.fre.FREObject; public class CallAppFunction implements FREFunction { @Override public FREObject call(FREContext arg0, FREObject[] arg1) { FREObject result = null; String appPackage; String appID; Intent myIntent = new Intent(); try { Activity currentActivity = arg0.getActivity(); appPackage = arg1[0].getAsString(); appID = arg1[1].getAsString(); myIntent.addCategory(Intent.CATEGORY_LAUNCHER); myIntent.setAction(Intent.ACTION_MAIN); myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); myIntent.setData(Uri.parse(arg1[2].getAsString())); myIntent.setClassName(appPackage, appID); currentActivity.startActivity(myIntent); } catch (Exception e) { // TODO: handle exception } return result; } }
然后打開Flash Builder,創建一個庫項目,和Java部分的接口相對應:
package com.techmx.extensions { import flash.events.EventDispatcher; import flash.events.IEventDispatcher; import flash.external.ExtensionContext; /** * 通過一個傳遞的ID,啟動另外一個應用 */ public class CallAppExtension extends EventDispatcher { public static const CALL_APP:String = "callApp"; public static const EXTENSION_ID:String = "com.techmx.extensions.CallAppExtension"; private var extContext:ExtensionContext; public function CallAppExtension(target:IEventDispatcher=null) { extContext = ExtensionContext.createExtensionContext(EXTENSION_ID,""); } public function callApp(appPackage:String,appID:String,customURI:String):void { if(extContext) { extContext.call(CALL_APP,appPackage,appID,customURI); } } } }
然后就可以拿出SWC,和Java項目導出的JAR一起,打包為ANE文件。整個項目工程(包括ANE文件)可以點擊這里下載:ANEPack2
然后我們就可以創建兩個測試項目:MobileA和MobileB,類型都是ActionScript手機項目。在MobileA中,引入剛才創建的ANE文件,並調用擴展的方法來呼叫另一個應用,也就是MobileB。
MobileA的主體代碼:
package { import com.techmx.extensions.CallAppExtension; import flash.display.Sprite; import flash.events.MouseEvent; import flash.net.*; public class MobileA extends Sprite { public function MobileA() { super(); var btn:Sprite = new Sprite(); btn.graphics.beginFill(0x000000,1); btn.graphics.drawCircle(50,50,50); btn.graphics.endFill(); addChild(btn); btn.addEventListener(MouseEvent.CLICK,clickHandler); } protected function clickHandler(event:MouseEvent):void { var extension:CallAppExtension = new CallAppExtension(); //注意ID的規則,AIR會自動補上"air."和".AppEntry" extension.callApp("air.MobileB","air.MobileB.AppEntry","myarguments://me=neo&you=jack"); } } }
注意擴展方法的第三個參數,我們可以用自定義URI的方式傳遞參數,這里寫的是myarguments,實際上你寫成其它的值也沒有關系,都可以傳遞過去。
在MobileB中,則可以生成一個文本對象,來顯示收到的參數:
package { import flash.desktop.NativeApplication; import flash.display.Sprite; import flash.events.InvokeEvent; import flash.text.TextField; import flash.text.TextFormat; [SWF(width="320",height="480")] public class MobileB extends Sprite { private var label:TextField; public function MobileB() { super(); label = new TextField(); var format:TextFormat = new TextFormat(null,28); label.width = 320; label.height = 480; label.defaultTextFormat = format; addChild(label); NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvoke); } private function onInvoke(event:InvokeEvent):void { label.text = "Reason: "+event.reason; label.appendText("\n"+"Arguments: " + event.arguments); } } }
將兩個應用全部安裝到手機上,然后打開MobileA,就可以點擊黑色的圓圈呼叫MobileB。
第二種方式:使用自定義URI
使用ANE的方式,可以最大程度的使用底層API的便利,但對於項目還是不太方便。如果只是呼叫另一個APP的話,所幸我們還有另一個選擇,就是使用自定義的URI。
這種方式就要求我們對那個需要被調用的應用(在這個例子中就是MobileB),在配置文件中注冊一個自定義的URI,比如我們要注冊一個“todoair”的URI,需要在配置文件中同時更改Android部分的定義和iOS部分的定義(如果您還要部署到iOS的話)。
<android> <manifestAdditions><![CDATA[ <manifest android:installLocation="auto"> <application> <activity> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="todoair"/> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET"/> </manifest> ]]></manifestAdditions> </android> <iPhone> <InfoAdditions><![CDATA[ <key>UIDeviceFamily</key> <array> <string>1</string> <string>2</string> </array> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>todoair</string> </array> <key>CFBundleURLName</key> <string>MobileB</string> </dict> </array> ]]></InfoAdditions> <requestedDisplayResolution>high</requestedDisplayResolution> </iPhone>
然后先把MobileB打包安裝到手機,接着來修改MobileA的代碼,將調用方式修改為:
protected function clickHandler(event:MouseEvent):void { //URL方式 //navigateToURL(new URLRequest("todoair://me=neo&you=jack")); }
這就可以了,打包MobileA到手機,運行效果和剛才基於ANE的方式是類似的:
這個方式不需要編寫原生代碼來配合,使用簡單,但是一定要在配置文件中注冊URI才會生效。另外您應該也注意到了,它使用navigateToURL來調用,說明這個方式用網頁也是可行的。您可以在您的WEB網站上,用HTML中的A鏈接,結合注冊的自定義URI,來啟動您的應用。