守望者--AIR技术交流

标题: Adobe AIR移动App的互相调用实现方式 [打印本页]

作者: 破晓    时间: 2015-4-11 15:50
标题: Adobe AIR移动App的互相调用实现方式

在使用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,代码如下:

  1. package com.techmx.extensions;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.net.Uri;
  5. import com.adobe.fre.FREContext;
  6. import com.adobe.fre.FREFunction;
  7. import com.adobe.fre.FREObject;

  8. public class CallAppFunction implements FREFunction {

  9.     @Override
  10.     public FREObject call(FREContext arg0, FREObject[] arg1) {
  11.         FREObject result = null;
  12.         String appPackage;
  13.         String appID;
  14.         Intent myIntent = new Intent();
  15.         try {
  16.             Activity currentActivity = arg0.getActivity();
  17.             appPackage = arg1[0].getAsString();
  18.             appID = arg1[1].getAsString();
  19.             myIntent.addCategory(Intent.CATEGORY_LAUNCHER);
  20.             myIntent.setAction(Intent.ACTION_MAIN);
  21.             myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  22.             myIntent.setData(Uri.parse(arg1[2].getAsString()));
  23.             myIntent.setClassName(appPackage, appID);
  24.             currentActivity.startActivity(myIntent);
  25.         } catch (Exception e) {
  26.             // TODO: handle exception
  27.         }
  28.         return result;
  29.     }
  30. }
复制代码
然后打开Flash Builder,创建一个库项目,和Java部分的接口相对应:

  1. package com.techmx.extensions
  2. {
  3.     import flash.events.EventDispatcher;
  4.     import flash.events.IEventDispatcher;
  5.     import flash.external.ExtensionContext;

  6.     /**
  7.      * 通过一个传递的ID,启动另外一个应用
  8.      */
  9.     public class CallAppExtension extends EventDispatcher
  10.     {
  11.         public static const CALL_APP:String = "callApp";
  12.         public static const EXTENSION_ID:String = "com.techmx.extensions.CallAppExtension";
  13.         private var extContext:ExtensionContext;

  14.         public function CallAppExtension(target:IEventDispatcher=null)
  15.         {
  16.             extContext = ExtensionContext.createExtensionContext(EXTENSION_ID,"");
  17.         }

  18.         public function callApp(appPackage:String,appID:String,customURI:String):void
  19.         {
  20.             if(extContext)
  21.             {
  22.                 extContext.call(CALL_APP,appPackage,appID,customURI);
  23.             }
  24.         }
  25.     }
  26. }
复制代码
然后就可以拿出SWC,和Java项目导出的JAR一起,打包为ANE文件。整个项目工程(包括ANE文件)可以点击这里下载:ANEPack2然后我们就可以创建两个测试项目:MobileA和MobileB,类型都是ActionScript手机项目。在MobileA中,引入刚才创建的ANE文件,并调用扩展的方法来呼叫另一个应用,也就是MobileB。MobileA的主体代码:
  1. package
  2. {
  3.     import com.techmx.extensions.CallAppExtension;

  4.     import flash.display.Sprite;
  5.     import flash.events.MouseEvent;
  6.     import flash.net.*;

  7.     public class MobileA extends Sprite
  8.     {
  9.         public function MobileA()
  10.         {
  11.             super();
  12.             var btn:Sprite = new Sprite();
  13.             btn.graphics.beginFill(0x000000,1);
  14.             btn.graphics.drawCircle(50,50,50);
  15.             btn.graphics.endFill();
  16.             addChild(btn);
  17.             btn.addEventListener(MouseEvent.CLICK,clickHandler);
  18.         }

  19.         protected function clickHandler(event:MouseEvent):void
  20.         {
  21.             var extension:CallAppExtension = new CallAppExtension();
  22.             //注意ID的规则,AIR会自动补上"air."和".AppEntry"
  23.             extension.callApp("air.MobileB","air.MobileB.AppEntry","myarguments://me=neo&you=jack");
  24.         }
  25.     }
  26. }
复制代码
注意扩展方法的第三个参数,我们可以用自定义URI的方式传递参数,这里写的是myarguments,实际上你写成其它的值也没有关系,都可以传递过去。在MobileB中,则可以生成一个文本对象,来显示收到的参数:
  1. package
  2. {
  3.     import flash.desktop.NativeApplication;
  4.     import flash.display.Sprite;
  5.     import flash.events.InvokeEvent;
  6.     import flash.text.TextField;
  7.     import flash.text.TextFormat;

  8.     [SWF(width="320",height="480")]
  9.     public class MobileB extends Sprite
  10.     {
  11.         private var label:TextField;

  12.         public function MobileB()
  13.         {
  14.             super();
  15.             label = new TextField();
  16.             var format:TextFormat = new TextFormat(null,28);
  17.             label.width = 320;
  18.             label.height = 480;
  19.             label.defaultTextFormat = format;
  20.             addChild(label);
  21.             NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvoke);
  22.         }

  23.         private function onInvoke(event:InvokeEvent):void
  24.         {
  25.             label.text = "Reason: "+event.reason;
  26.             label.appendText("\n"+"Arguments: " + event.arguments);
  27.         }
  28.     }
  29. }
复制代码
将两个应用全部安装到手机上,然后打开MobileA,就可以点击黑色的圆圈呼叫MobileB。
[attach]1118[/attach]

第二种方式:使用自定义URI使用ANE的方式,可以最大程度的使用底层API的便利,但对于项目还是不太方便。如果只是呼叫另一个APP的话,所幸我们还有另一个选择,就是使用自定义的URI。这种方式就要求我们对那个需要被调用的应用(在这个例子中就是MobileB),在配置文件中注册一个自定义的URI,比如我们要注册一个“todoair”的URI,需要在配置文件中同时更改Android部分的定义和iOS部分的定义(如果您还要部署到iOS的话)。
  1. <android>
  2.         <manifestAdditions><![CDATA[
  3.             <manifest android:installLocation="auto">
  4.                 <application>
  5.                  <activity>
  6.                      <intent-filter>
  7.                            <action android:name="android.intent.action.MAIN"/>
  8.                            <category android:name="android.intent.category.LAUNCHER"/>
  9.                      </intent-filter>
  10.                      <intent-filter>
  11.                            <action android:name="android.intent.action.VIEW"/>
  12.                            <category android:name="android.intent.category.BROWSABLE"/>
  13.                            <category android:name="android.intent.category.DEFAULT"/>
  14.                            <data android:scheme="todoair"/>
  15.                      </intent-filter>
  16.                  </activity>
  17.               </application>
  18.               <uses-permission android:name="android.permission.INTERNET"/>
  19.             </manifest>

  20.         ]]></manifestAdditions>
  21. </android>
  22. <iPhone>
  23.         <InfoAdditions><![CDATA[
  24.             <key>UIDeviceFamily</key>
  25.             <array>
  26.                 <string>1</string>
  27.                 <string>2</string>
  28.             </array>
  29.             <key>CFBundleURLTypes</key>
  30.             <array>
  31.                 <dict>
  32.                     <key>CFBundleURLSchemes</key>
  33.                     <array>
  34.                         <string>todoair</string>
  35.                     </array>
  36.                     <key>CFBundleURLName</key>
  37.                     <string>MobileB</string>
  38.                 </dict>
  39.             </array>
  40.         ]]></InfoAdditions>
  41.         <requestedDisplayResolution>high</requestedDisplayResolution>
  42. </iPhone>
复制代码
然后先把MobileB打包安装到手机,接着来修改MobileA的代码,将调用方式修改为:
  1. protected function clickHandler(event:MouseEvent):void
  2. {
  3.     //URL方式
  4.     //navigateToURL(new URLRequest("todoair://me=neo&you=jack"));
  5. }
复制代码
这就可以了,打包MobileA到手机,运行效果和刚才基于ANE的方式是类似的:
[attach]1119[/attach]
这个方式不需要编写原生代码来配合,使用简单,但是一定要在配置文件中注册URI才会生效。另外您应该也注意到了,它使用navigateToURL来调用,说明这个方式用网页也是可行的。您可以在您的WEB网站上,用HTML中的A链接,结合注册的自定义URI,来启动您的应用。

本文来自:http://www.cnblogs.com/sevenyuan/archive/2013/03/25/2981056.html







欢迎光临 守望者--AIR技术交流 (http://www.airmyth.com/)