守望者--AIR技术交流

标题: 使用NativeExtension向AIR app 添加Activity和BroadCastReceiver [打印本页]

作者: 破晓    时间: 2015-1-10 21:56
标题: 使用NativeExtension向AIR app 添加Activity和BroadCastReceiver
前言

AIR3NativeExtension提供的让AIR调用本地代码的功能,从而将一些Actionscript无法做到的功能用系统的本地代码来实现。

目前大部分NativeExtension应用主要是将需要实现的功能封装为一个本地函数,然后通过AIR runtime调用这个本地函数实现AIR无法完成的功能,或者提升该功能的性能。如对振动器的调用。其实,NativeExtension不仅仅可以进行函数层级上的扩展,对GUI部分也可以进行扩展,本篇文章就以在Android平台为例,向AIR开发的app添加ActivityBroadCastReceiver 这样,使用AIR开发的app不仅可以超出原有AIR的显示框架,而且可以接受系统广播事件,从而完成以前无法完成的很多功能,开发出更加丰富多彩的应用。最简单的例子就是可以直接调用Android系统的Camera了,这样可以实现自动对焦的一些功能。

这篇教程主要会演示如使用NativeExtensionAIR app中添加ActivityBroadCastReceiver。希望能给大家的NativeExtension开发提供更多的思路。

由于NativeExtension的开发目前来讲不论是开发还是部署打包都是一个比较复杂的工作,很容易做错步骤,因此希望大家先在看这篇之前,先参考:http://sswilliam.blog.163.com/blog/static/189696383201191094227313/这一系列教程,以了解NativeExtension开发的一些基本操作。

Demo简介

为了让大家更好的理解要做的事情,在这里将我们的demo做一个简单的介绍。Demo的示意图如下:

[attach]337[/attach]


其大体流程是AIR app会启动一个Android原生的Activity,然后在原生的Activity进行一些逻辑处理后,将结果返回给AIR



1.开启应用,点击call activity按钮

[attach]338[/attach]


2.系统弹出我们在NativeExtension中用Java写的原生的Activity

[attach]339[/attach]


3. 我们在输入框中输入一些字符后点击return



[attach]340[/attach]
4.
通过IntentActivity的结果返回给AIR
[attach]341[/attach]

其实这个流程在Android原生开发中非常常见,就是调用ActivitystartActivityForResult方法,然后重写一下onActivityResult方法就能接收到返回的结果。但是这个流程在AIRApp中行不通,因为AIRapp中的主要的Activity是由AIR SDK生成的AppEntry,我们无法对其中的方法进行重写,只能通过FREContextgetActivity()来获取其引用。所以我们会创建一个BroadcastReceiver,使用Android系统的广播机制将我们所需要的值进行返回并做相应处理,然后NativeExtension会将返回值以事件抛回AIR app,从而完成整个流程。

其中主要涉及的重点包括:

FREContext的使用

如何从NativeExtension中向AIR抛出事件

AIRapp.xml的配置



本系列文章来自:http://sswilliam.blog.163.com/blog/static/18969638320119285102604/

作者: 破晓    时间: 2015-1-10 21:59
开发:Android项目

新建一个针对NativeExtensionAndroid项目,实现相应的FREContextFREExtensionFREFunction等方法,同时新建一个Activity和一个BroadCastReceiver。对于如何配置Android项目来开发NativeExtension,参考http://sswilliam.blog.163.com/blog/static/1896963832011910101142574/

Android项目目录和代码如下:


[attach]342[/attach]

CallBackExtension

CallBackExtensionNativeExtension的入口,实现了FREExtension接口,直接返回一个CallBackContext的对象实例,没啥好说的

  1. package net.sswilliam.ane.callback;

  2. import com.adobe.fre.FREContext;
  3. import com.adobe.fre.FREExtension;

  4. public class CallBackExtension implements FREExtension {

  5.       @Override
  6.       public FREContext createContext(String arg0) {
  7.             // TODO Auto-generated method stub
  8.             return new CallBackContext();
  9.       }

  10.       @Override
  11.       public void dispose() {
  12.             // TODO Auto-generated method stub

  13.       }

  14.       @Override
  15.       public void initialize() {
  16.             // TODO Auto-generated method stub

  17.       }

  18. }
复制代码

CallBackContext

CallBackContext是整个扩展Java部分的上下文,扩展了FREContext。首先先定义一些常量:

常量名
说明
REGISTER_RECEIVER_FUNCTION
注册BroadCastReceiver函数的Key
START_ACTIVITY_FUNCTION
开启Activity函数的Key
DATA_RECEIVE
返回给AS端的事件

CallBackContext中主要需要实现getFunctions()方法,用来返回具体的java函数的映射:

  1.    @Override
  2.       public Map<String, FREFunction> getFunctions() {
  3.             // TODO Auto-generated method stub
  4.             if(functionMaps == null){
  5.                   functionMaps = new HashMap<String, FREFunction>();
  6.                   functionMaps.put(REGISTER_RECEIVER_FUNCTION, new RegisterReceiverFunction());
  7.                   functionMaps.put(START_ACTIVITY_FUNCTION, new StartActivityFunction());
  8.             }
  9.             return functionMaps;
  10.       }
复制代码

RegisterReceiverFunction

RegisterReceiverFunction实现了FREFunction接口。其功能是向Android系统注册一个BroadCastReceiver。这里我们直接通过registerReceiver函数动态注册BroadCastReceiver而非是在AndroidManifest.xml中静态注册,主要原因是这个BroadCastReceiver的生命周期也就是这个app的生命周期,并且需要与AppFREContext进行交互,注册为静态的不是很合适。当然在AIR开发的Android程序中,也是支持在AndroidManifest.xml中静态注册BroadCastReceiver的。我们会在后面静态的注册一个Activity,静态注册BroadCastReceiver的方法和注册Activity的方法一样,因此这里就不赘述了。就像正常Android程序开发一样,Log也适用于AIR开发的Android app,可以在Logcat中查看。

  1. @Override
  2.       public FREObject call(FREContext arg0, FREObject[] arg1) {
  3.             // TODO Auto-generated method stub
  4.             Log.d("YZ", "register receiver");
  5.             MyReceiver receiver = new MyReceiver(arg0);
  6.             arg0.getActivity().registerReceiver(receiver, new IntentFilter(MyReceiver.MYARECEIVER_ACTION));
  7.             return null;
  8.       }
复制代码

StartActivityFunction

StartActivityFunction实现了FREFunction接口。其功能是打开一个我们自定义的Activity。我们会定义一个自定义的ACTION。然后在AndroidManifest.xml将这个ACTION和这个Activity进行绑定。这样我们用startActivity方法发送一个Intent,就可以开启这个Activity

  1. @Override
  2.       public FREObject call(FREContext arg0, FREObject[] arg1) {
  3.             // TODO Auto-generated method stub
  4.             Intent intent = new Intent(MyActivity.MYACTIVITY_ACTION);
  5.             arg0.getActivity().startActivity(intent);
  6.             return null;
  7.       }
复制代码

MyActivity

MyActivity就是我们自定义的用来返回结果的Activity。首先会定义MyActivity的开启的ACTIONMYACTIVITY_ACTION = "net.sswilliam.ane.callback.myactivity".

然后重写onCreate函数构建界面,并添加事件侦听。这里我们适用java编码的方式构建界面,因为我们在新建项目时,就把gen这个目录已经剔除了。我的考虑可能是因为R中存储的都是资源的地址,在原生Android的应用中没有问题,但是AIR会重新编译和打包,所以在Android中的R里的地址可能在AIR中就变了,所以R也不能用。这只是一个猜的,具体还需要实验论证,等有时间了实验论证后再公布出来。

  1. package net.sswilliam.ane.callback;

  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.view.View.OnClickListener;
  7. import android.widget.Button;
  8. import android.widget.EditText;
  9. import android.widget.LinearLayout;

  10. public class MyActivity extends Activity implements OnClickListener{
  11.       //声明开启Activity的Action
  12.       public static final String MYACTIVITY_ACTION = "net.sswilliam.ane.callback.myactivity";
  13.      
  14.       private LinearLayout layout;
  15.       private EditText inputEdit;
  16.       private Button submit;
  17.       @Override
  18.       protected void onCreate(Bundle savedInstanceState) {
  19.             // TODO Auto-generated method stub
  20.             //构建界面
  21.             super.onCreate(savedInstanceState);
  22.             layout = new LinearLayout(this);
  23.             inputEdit = new EditText(this);
  24.             submit = new Button(this);
  25.             submit.setText("return");
  26.             layout.addView(inputEdit);
  27.             layout.addView(submit);
  28.             this.setContentView(layout);
  29.             //添加事件侦听
  30.             submit.setOnClickListener(this);
  31.       }
  32.       @Override
  33.       public void onClick(View v) {
  34.             // TODO Auto-generated method stub
  35.             //像预先注册过的BroadCastReceiver发送Intent以返回数据
  36.             Intent intent = new Intent(MyReceiver.MYARECEIVER_ACTION);
  37.            
  38.             intent.putExtra("data",this.inputEdit.getText().toString());
  39.             this.sendBroadcast(intent);
  40.             this.finish();
  41.            
  42.            
  43.       }

  44. }
复制代码

MyReceier

MyReceiver是我们自定义的BroadCastReceiver,会被动态的注册到系统中从而侦听相应的Intent,首先我们定义需要侦听的IntentACTIONMYARECEIVER_ACTION = "net.sswilliam.ane.callback.myreceiver"。同时我们会传入CallBackContext的引用。这样可以在处理Intent时向Actionscript端抛出事件。

注意FREContext中有一个dispatchStatusEventAsync方法可以从java代码向Actionscript端抛出ActionScript的事件。具体请查看NaiveExtension事件机制章节。

  1. package net.sswilliam.ane.callback;

  2. import com.adobe.fre.FREContext;

  3. import android.content.BroadcastReceiver;
  4. import android.content.Context;
  5. import android.content.Intent;

  6. public class MyReceiver extends BroadcastReceiver {
  7.       private FREContext context;
  8.       public static final String MYARECEIVER_ACTION = "net.sswilliam.ane.callback.myreceiver";
  9.       public MyReceiver(FREContext context){
  10.             this.context = context;
  11.       }

  12.       @Override
  13.       public void onReceive(Context arg0, Intent arg1) {
  14.             // TODO Auto-generated method stub
  15.             String data = arg1.getExtras().getString("data");
  16.             this.context.dispatchStatusEventAsync(CallBackContext.DATE_RECEIVE, data);

  17.       }

  18. }
复制代码



作者: 破晓    时间: 2015-1-10 22:03
Flex Library项目Flex Library项目目录和代码如下:

[attach]343[/attach]


CallBackExtension

CallBackExtension是我们这个NativeExtensionActionscript的具体实现。同样我们会在其中先声明需要调用函数在Map中的Key,这两个KeyJava中的两个Key是完全相同的,申明成静态的常量可以减少编程时带来的拼写误差,也提高程序的可读性。


  1. public static const REGISTER_RECEIVER_FUNCTION:String = "register_receiver_function";
  2. public static const START_ACTIVITY_FUNCTION:String = "start_activity_function";
复制代码

对于Java端的两个函数,其中注册BroadCastReceiverRegisterReceiverFunction函数会在CallBackExtension新建时就调用。从而将我们自定义的BroadCastReceiver动态的注册进系统。而StartActivityFunction函数提供给第三方程序进行调用。

  1. public function CallBackExtension(target:IEventDispatcher=null)
  2. {
  3.                 super(target);
  4.                 ext = ExtensionContext.createExtensionContext("net.sswilliam.ane.callback","");
  5.                 ext.addEventListener(StatusEvent.STATUS,onDataReceived);
  6.                 ext.call(REGISTER_RECEIVER_FUNCTION);
  7. }
  8. public function startActivity():void{
  9.                 ext.call(START_ACTIVITY_FUNCTION);
  10. }
复制代码

同时需要给ExtensionContext添加事件侦听函数。从而获得从Java端抛出的Actionscript事件。具体请查看NaiveExtension事件机制章节。

CallBackEvent

CallBackEvent是自定义的一个事件类,将从Java端接收到的事件和数据封装为Actionscript的一个事件对象,供具体使用该NativeExtensionapp调用。

  1. package net.sswilliam.ane.callback
  2. {
  3.                 import flash.events.Event;
  4.                
  5.                 public class CallBackEvent extends Event
  6.                 {            
  7.                                 public static const DATE_RECEIVE:String = "data_receive";
  8.                               
  9.                                 public var callbackData:String = "";
  10.                                 public function CallBackEvent(callBackData:String, bubbles:Boolean=false, cancelable:Boolean=false)
  11.                                 {
  12.                                                 super(DATE_RECEIVE, bubbles, cancelable);
  13.                                                 this.callbackData = callBackData;
  14.                                 }
  15.                 }
  16. }
复制代码

extension.xml

最后我们不能忘记在项目中添加相应的extension.xml文件对这个扩展做一个描述。大部分的tag都很清晰,就不过多解释了。注意的是namespace,虽然我们用3.0sdk,但是在NativeExtension中还是2.5

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <extension xmlns="http://ns.adobe.com/air/extension/2.5">
  3.   <id>net.sswilliam.ane.callback</id>
  4.   <versionNumber>1</versionNumber>
  5.   <platforms>
  6.     <platform name="Android-ARM">
  7.       <applicationDeployment>
  8.         <nativeLibrary>CallBack.jar</nativeLibrary>
  9.         <initializer>net.sswilliam.ane.callback.CallBackExtension</initializer>
  10.         <finalizer>net.sswilliam.ane.callback.CallBackExtension</finalizer>
  11.       </applicationDeployment>
  12.     </platform>
  13.   </platforms>
  14. </extension>
复制代码

Flex Mobile 项目

Flex Mobile项目目录结构和代码如下:

[attach]344[/attach]

在这个项目中,重点不在于App的开发,而在于app.xml的配置。

CallbackTest.mxml

只是一个很简单调用我们NativeExtension的程序。我们会在程序启动时直接实例化NativeExtension,然后添加事件。并且通过一个Button来开启Java原生的Activity。最后显示从Java返回的数据。代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
  3.                                                    xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="init(event)">
  4.                 <fx:Script>
  5.                                 <![CDATA[
  6.                                                 import mx.events.FlexEvent;
  7.                                                
  8.                                                 import net.sswilliam.ane.callback.CallBackEvent;
  9.                                                 import net.sswilliam.ane.callback.CallBackExtension;
  10.                                                
  11.                                                 import spark.effects.CallAction;
  12.                                                
  13.                                                 private var ext:CallBackExtension;
  14.                                                 protected function init(event:FlexEvent):void
  15.                                                 {
  16.                                                                 // TODO Auto-generated method stub
  17.                                                                 ext = new CallBackExtension();
  18.                                                                 ext.addEventListener(CallBackEvent.DATE_RECEIVE,dataReceiverHandler);
  19.                                                                
  20.                                                 }
  21.                                                 private function dataReceiverHandler(e:CallBackEvent):void{
  22.                                                                 this.console.appendText("data receiver:"+e.callbackData+"\n");
  23.                                                 }
  24.                                                
  25.                                                 protected function startActivity(event:MouseEvent):void
  26.                                                 {
  27.                                                                 // TODO Auto-generated method stub
  28.                                                                 this.ext.startActivity();
  29.                                                 }
  30.                                                
  31.                                 ]]>
  32.                 </fx:Script>
  33.                 <fx:Declarations>
  34.                                 <!-- 将非可视元素(例如服务、值对象)放在此处 -->
  35.                 </fx:Declarations>
  36.                 <s:Button x="10" y="10" label="call activity" click="startActivity(event)"/>
  37.                 <s:TextArea id="console" x="13" y="86" width="457" height="667"/>
  38. </s:Application>
复制代码

CallbackTest-app.xml

每一个AIR程序都需要一个app.xml文件对其进行描述。当AIR支持Android平台后,在app.xml中就多了一个的tag。里面会有一个manifestAdditions的子tag。在这里,就可以包含针对Android程序中的AndroidManifest.xml的一些信息的添加和修改。默认的,在这个tag里会包含如下信息:

  1. <android>
  2.         <manifestAdditions><![CDATA[
  3.                                                 <manifest android:installLocation="auto">
  4.                                                                
  5.                                                     <!--See the Adobe AIR documentation for more information about setting Google Android permissions-->
  6.                                                     <!--删除 android.permission.INTERNET 权限将导致无法调试设备上的应用程序-->
  7.                                                     <uses-permission android:name="android.permission.INTERNET"/>
  8.                                                     <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>-->
  9.                                                     <!--<uses-permission android:name="android.permission.READ_PHONE_STATE"/>-->
  10.                                                     <!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>-->
  11.                                                     <!--应同时切换 DISABLE_KEYGUARD 和 WAKE_LOCK 权限,才能访问 AIR
  12.                                 的 SystemIdleMode API-->
  13.                                                     <!--<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>-->
  14.                                                     <!--<uses-permission android:name="android.permission.WAKE_LOCK"/>-->
  15.                                                     <!--<uses-permission android:name="android.permission.CAMERA"/>-->
  16.                                                     <!--<uses-permission android:name="android.permission.RECORD_AUDIO"/>-->
  17.                                                     <!--应同时切换 ACCESS_NETWORK_STATE 和 ACCESS_WIFI_STATE 权限,才能使用 AIR
  18.                                 的 NetworkInfo API-->
  19.                                                     <!--<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>-->
  20.                                                     <!--<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>-->
  21.                                                 </manifest>
  22.                                                
  23.                                 ]]></manifestAdditions>
  24.     </android>
复制代码

从中可以看出,主要是对permission的一些设置。这些permissionAIR SDK自动添加到最终生成的AndroidManifest当中。

在原生的Android App中,当我们需要注册一个Activity时,可以直接修改AndroidManifest.xml文件。那么当我们向要在用AIR开发的Android app注册一个Activity要怎么做呢?其实也很简单,只要在AIRapp.xmlAndroid中添加相应的Tag即可。如下图红色标记,这里我们就向我们的AIR app添加了一个MyActivityActivity。同时也定义了相应的IntentFilter。这里一定要注意两点

1.       包括在application tag里,在原生Android开发中,Activity也是注册在application tag里的。但是AIRapp.xml里没有这个tag,经过测试,发现直接在app.xml里添加application tag,最终application tag里的内容也会合并到最后生成的AndroidManifest.xml中。

2.       android:name的值与Android项目中的Activity的包路径相同。

  1. <android>
  2.         <manifestAdditions><![CDATA[
  3.                                                 <manifest android:installLocation="auto">
  4.                                                                 <application>
  5.                                                                                 <activity android:name="net.sswilliam.ane.callback.MyActivity">
  6.                                                                                 <intent-filter>
  7.                                                                                                 <action android:name="net.sswilliam.ane.callback.myactivity" />
  8.                                                                                                 <category android:name="android.intent.category.DEFAULT" />
  9.                                                                                                 </intent-filter>
  10.                                                                                 </activity>
  11.                                                 </application>
  12.                                                     <!--See the Adobe AIR documentation for more information about setting Google Android permissions-->
  13.                                                     <!--删除 android.permission.INTERNET 权限将导致无法调试设备上的应用程序-->
  14.                                                     <uses-permission android:name="android.permission.INTERNET"/>
  15.                                                     <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>-->
  16.                                                     <!--<uses-permission android:name="android.permission.READ_PHONE_STATE"/>-->
  17.                                                     <!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>-->
  18.                                                     <!--应同时切换 DISABLE_KEYGUARD 和 WAKE_LOCK 权限,才能访问 AIR
  19.                                 的 SystemIdleMode API-->
  20.                                                     <!--<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>-->
  21.                                                     <!--<uses-permission android:name="android.permission.WAKE_LOCK"/>-->
  22.                                                     <!--<uses-permission android:name="android.permission.CAMERA"/>-->
  23.                                                     <!--<uses-permission android:name="android.permission.RECORD_AUDIO"/>-->
  24.                                                     <!--应同时切换 ACCESS_NETWORK_STATE 和 ACCESS_WIFI_STATE 权限,才能使用 AIR
  25.                                 的 NetworkInfo API-->
  26.                                                     <!--<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>-->
  27.                                                     <!--<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>-->
  28.                                                 </manifest>
  29.                                                
  30.                                 ]]></manifestAdditions>
  31.     </android>
复制代码

编译打包

编译打包跟其他的NativeExtension没有什么区别,具体参见:http://sswilliam.blog.163.com/blog/static/1896963832011910111931102/

http://sswilliam.blog.163.com/blog/static/1896963832011910111931102/


再次重申一下,NativeExtension目前的开发还是挺麻烦的,大家一定要耐心+细心。做成功一遍后就基本不会遇到什么困难了。



作者: 破晓    时间: 2015-1-10 22:06
NativeExtension的事件机制NativeExtension中通信方式主要由两种,一种是Actionscript直接通过call方法调用Native的代码,另外一种则是从Native代码像Actionscript抛出事件。这里主要讲解的是第二种方法。从Native代码向Actionscript抛出事件和Actionscript自身的事件机制非常相似。主要也是分为派发事件,侦听事件和处理事件三个部分。

派发事件:

派发事件主要是再Native code中执行,在Java中,就是调用FREContextdispatchStatusEventAsync(arg0, arg1),它和Actionscript中的dispatchEvent(event)是不同的。在Actionscript中的dispatchEvent方法中主要传入的参数是一个Event对象,这个Event的一些具体参数需要自己进行封装。而dispatchStatusEventAsync(arg0, arg1)传入的是两个String,这个方法会在java端像actionscript端抛出StatusEvent对象,arg0被当做StatusEventcodearg1被当做StatusEventlevel。其中level可以被用作事件传递的数据,如果有复杂格式的数据,可以将数据封装成json或者xml,或者就简单的用分隔符分隔开。

Java端代码如下:

  1. this.context.dispatchStatusEventAsync("Status1", "data1;data2;data3");
复制代码

侦听事件:

接收事件主要在Actionscript进行,直接在ExtensionContext对象上添加StatusEvent.Status事件的侦听即可

  1. ext = ExtensionContext.createExtensionContext("net.sswilliam.ane.callback","");
  2. ext.addEventListener(StatusEvent.STATUS,onDataReceived);
复制代码

处理事件:

处理事件其实就是标准的用Switch Case处理StatusEvent事件的函数。官方文档里有很多范例。通过判断不同的codelevel从而进行具体的逻辑处理。

  1. private function onDataReceived(e:StatusEvent):void{
  2.                 switch(e.code)
  3.                 {
  4.                                 case  "Status1":
  5.                                 {
  6.                                                 var result:String  = e.level;
  7.                                                 var datas:Array = result.split(";");
  8.                                                 trace(datas);
  9.                                                 break;
  10.                                 }
  11.                                                                               
  12.                                 default:
  13.                                 {
  14.                                                 break;
  15.                                 }
  16.                 }
  17. }
复制代码

总结

AIR开发的Android app中嵌入原生的Android的组件,其关键在于如何在app.xml中进行配置。因为AIR开发的Android app本质上还是一个Android app,必然需要一个AndroidManifest.xml。但是这个AndroidManifest.xml是由AIR自动生成的,我们只能在AIR app.xml中添加相应的参数变相的修改AndroidManifest.xml

从这次试验的结果来看,AIR SDK会把app.xml中的

  1. <android>
  2.         <manifestAdditions><![CDATA[
  3.                                                
  4.                                 ]]></manifestAdditions>
  5.     </android>
复制代码

里的内容自动的映射到最终的AndroidManifest.xml中。

如原本AIR APPAndroidManifest是这样的:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest android:versionCode="0" android:versionName="@string/app_version" android:installLocation="auto" package="air.CallbackTest.debug"
  3.   xmlns:android="http://schemas.android.com/apk/res/android">
  4.     <application android:label="@string/app_name" android:icon="@drawable/icon" android:hardwareAccelerated="true">
  5.         <activity android:theme="@style/Theme.NoShadow" android:label="@string/app_name" android:name=".AppEntry" android:launchMode="singleTask" android:screenOrientation="user" android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="stateHidden|adjustResize">
  6.             <intent-filter>
  7.                 <action android:name="android.intent.action.MAIN" />
  8.                 <category android:name="android.intent.category.LAUNCHER" />
  9.             </intent-filter>
  10.             <meta-data android:name="autoOrients" android:value="false" />
  11.             <meta-data android:name="fullScreen" android:value="false" />
  12.             <meta-data android:name="uniqueappversionid" android:value="51f23dd3-5056-4831-ac9d-df2fcdca82a8" />
  13.             <meta-data android:name="initialcontent" android:value="CallbackTest.swf" />
  14.         </activity>
  15.     </application>
  16.     <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="11" />
  17.     <uses-permission android:name="android.permission.INTERNET" />
  18. </manifest>
复制代码

如果我们在Android Tag中添加如下代码:

  1. <android>
  2.         <manifestAdditions><![CDATA[
  3.                                                 <manifest android:installLocation="auto">
  4.                                                                 <application>
  5.                                                                                 <activity android:name="net.sswilliam.ane.callback.MyActivity">
  6.                                                                                 <intent-filter>
  7.                                                                                                 <action android:name="net.sswilliam.ane.callback.myactivity" />
  8.                                                                                                 <category android:name="android.intent.category.DEFAULT" />
  9.                                                                                                 </intent-filter>
  10.                                                                                 </activity>
  11.                                                 </application>
  12.                                                
  13.                                                 </manifest>
  14.                                                
  15.                                 ]]></manifestAdditions>
  16.     </android>
复制代码

那么打包后再查看AndroidManifest.xml, 就会变成这样:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest android:versionCode="0" android:versionName="@string/app_version" android:installLocation="auto" package="air.CallbackTest.debug"
  3.   xmlns:android="http://schemas.android.com/apk/res/android">
  4.     <application android:label="@string/app_name" android:icon="@drawable/icon" android:hardwareAccelerated="true">
  5.         <activity android:theme="@style/Theme.NoShadow" android:label="@string/app_name" android:name=".AppEntry" android:launchMode="singleTask" android:screenOrientation="user"
  6. android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="stateHidden|adjustResize">
  7.             <intent-filter>
  8.                 <action android:name="android.intent.action.MAIN" />
  9.                 <category android:name="android.intent.category.LAUNCHER" />
  10.             </intent-filter>
  11.             <meta-data android:name="autoOrients" android:value="false" />
  12.             <meta-data android:name="fullScreen" android:value="false" />
  13.             <meta-data android:name="uniqueappversionid" android:value="ab57dfb0-5b52-4e80-8a6d-f9dedda9a76e" />
  14.             <meta-data android:name="initialcontent" android:value="CallbackTest.swf" />
  15.         </activity>
  16.         <activity android:name="net.sswilliam.ane.callback.MyActivity">
  17.             <intent-filter>
  18.                 <action android:name="net.sswilliam.ane.callback.myactivity" />
  19.                 <category android:name="android.intent.category.DEFAULT" />
  20.             </intent-filter>
  21.         </activity>
  22.     </application>
  23.     <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="11" />
  24.     <uses-permission android:name="android.permission.INTERNET" />
  25. </manifest>
复制代码

Apktool是个很好的工具,大家不妨各种不同方法打包出来的apk文件反编译一下,就可以发现各自的实现原理了。







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