守望者--AIR技术交流
标题: 使用NativeExtension向AIR app 添加Activity和BroadCastReceiver [打印本页]
作者: 破晓 时间: 2015-1-10 21:56
标题: 使用NativeExtension向AIR app 添加Activity和BroadCastReceiver
前言AIR3的NativeExtension提供的让AIR调用本地代码的功能,从而将一些Actionscript无法做到的功能用系统的本地代码来实现。
目前大部分NativeExtension应用主要是将需要实现的功能封装为一个本地函数,然后通过AIR runtime调用这个本地函数实现AIR无法完成的功能,或者提升该功能的性能。如对振动器的调用。其实,NativeExtension不仅仅可以进行函数层级上的扩展,对GUI部分也可以进行扩展,本篇文章就以在Android平台为例,向AIR开发的app添加Activity和BroadCastReceiver。 这样,使用AIR开发的app不仅可以超出原有AIR的显示框架,而且可以接受系统广播事件,从而完成以前无法完成的很多功能,开发出更加丰富多彩的应用。最简单的例子就是可以直接调用Android系统的Camera了,这样可以实现自动对焦的一些功能。
这篇教程主要会演示如使用NativeExtension向AIR app中添加Activity和BroadCastReceiver。希望能给大家的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.
通过Intent将Activity的结果返回给AIR[attach]341[/attach]
其实这个流程在Android原生开发中非常常见,就是调用Activity的startActivityForResult方法,然后重写一下onActivityResult方法就能接收到返回的结果。但是这个流程在AIR的App中行不通,因为AIR的app中的主要的Activity是由AIR SDK生成的AppEntry,我们无法对其中的方法进行重写,只能通过FREContext的getActivity()来获取其引用。所以我们会创建一个BroadcastReceiver,使用Android系统的广播机制将我们所需要的值进行返回并做相应处理,然后NativeExtension会将返回值以事件抛回AIR app,从而完成整个流程。
其中主要涉及的重点包括:
FREContext的使用
如何从NativeExtension中向AIR抛出事件
AIR中app.xml的配置
本系列文章来自:http://sswilliam.blog.163.com/blog/static/18969638320119285102604/
作者: 破晓 时间: 2015-1-10 21:59
开发:Android项目新建一个针对NativeExtension的Android项目,实现相应的FREContext,FREExtension和FREFunction等方法,同时新建一个Activity和一个BroadCastReceiver。对于如何配置Android项目来开发NativeExtension,参考http://sswilliam.blog.163.com/blog/static/1896963832011910101142574/
Android项目目录和代码如下:
[attach]342[/attach]
CallBackExtension
CallBackExtension是NativeExtension的入口,实现了FREExtension接口,直接返回一个CallBackContext的对象实例,没啥好说的
- package net.sswilliam.ane.callback;
-
- import com.adobe.fre.FREContext;
- import com.adobe.fre.FREExtension;
-
- public class CallBackExtension implements FREExtension {
-
- @Override
- public FREContext createContext(String arg0) {
- // TODO Auto-generated method stub
- return new CallBackContext();
- }
-
- @Override
- public void dispose() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void initialize() {
- // TODO Auto-generated method stub
-
- }
-
- }
-
复制代码
CallBackContext
CallBackContext是整个扩展Java部分的上下文,扩展了FREContext。首先先定义一些常量:
常量名 | |
REGISTER_RECEIVER_FUNCTION | 注册BroadCastReceiver函数的Key |
| |
| |
在CallBackContext中主要需要实现getFunctions()方法,用来返回具体的java函数的映射:
- @Override
- public Map<String, FREFunction> getFunctions() {
- // TODO Auto-generated method stub
- if(functionMaps == null){
- functionMaps = new HashMap<String, FREFunction>();
- functionMaps.put(REGISTER_RECEIVER_FUNCTION, new RegisterReceiverFunction());
- functionMaps.put(START_ACTIVITY_FUNCTION, new StartActivityFunction());
- }
- return functionMaps;
- }
复制代码
RegisterReceiverFunction
RegisterReceiverFunction实现了FREFunction接口。其功能是向Android系统注册一个BroadCastReceiver。这里我们直接通过registerReceiver函数动态注册BroadCastReceiver而非是在AndroidManifest.xml中静态注册,主要原因是这个BroadCastReceiver的生命周期也就是这个app的生命周期,并且需要与App的FREContext进行交互,注册为静态的不是很合适。当然在AIR开发的Android程序中,也是支持在AndroidManifest.xml中静态注册BroadCastReceiver的。我们会在后面静态的注册一个Activity,静态注册BroadCastReceiver的方法和注册Activity的方法一样,因此这里就不赘述了。就像正常Android程序开发一样,Log也适用于AIR开发的Android app,可以在Logcat中查看。
- @Override
- public FREObject call(FREContext arg0, FREObject[] arg1) {
- // TODO Auto-generated method stub
- Log.d("YZ", "register receiver");
- MyReceiver receiver = new MyReceiver(arg0);
- arg0.getActivity().registerReceiver(receiver, new IntentFilter(MyReceiver.MYARECEIVER_ACTION));
- return null;
- }
复制代码
StartActivityFunction
StartActivityFunction实现了FREFunction接口。其功能是打开一个我们自定义的Activity。我们会定义一个自定义的ACTION。然后在AndroidManifest.xml将这个ACTION和这个Activity进行绑定。这样我们用startActivity方法发送一个Intent,就可以开启这个Activity
- @Override
- public FREObject call(FREContext arg0, FREObject[] arg1) {
- // TODO Auto-generated method stub
- Intent intent = new Intent(MyActivity.MYACTIVITY_ACTION);
- arg0.getActivity().startActivity(intent);
- return null;
- }
复制代码
MyActivity
MyActivity就是我们自定义的用来返回结果的Activity。首先会定义MyActivity的开启的ACTION:MYACTIVITY_ACTION = "net.sswilliam.ane.callback.myactivity".
然后重写onCreate函数构建界面,并添加事件侦听。这里我们适用java编码的方式构建界面,因为我们在新建项目时,就把gen这个目录已经剔除了。我的考虑可能是因为R中存储的都是资源的地址,在原生Android的应用中没有问题,但是AIR会重新编译和打包,所以在Android中的R里的地址可能在AIR中就变了,所以R也不能用。这只是一个猜的,具体还需要实验论证,等有时间了实验论证后再公布出来。
- package net.sswilliam.ane.callback;
-
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.LinearLayout;
-
- public class MyActivity extends Activity implements OnClickListener{
- //声明开启Activity的Action
- public static final String MYACTIVITY_ACTION = "net.sswilliam.ane.callback.myactivity";
-
- private LinearLayout layout;
- private EditText inputEdit;
- private Button submit;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- //构建界面
- super.onCreate(savedInstanceState);
- layout = new LinearLayout(this);
- inputEdit = new EditText(this);
- submit = new Button(this);
- submit.setText("return");
- layout.addView(inputEdit);
- layout.addView(submit);
- this.setContentView(layout);
- //添加事件侦听
- submit.setOnClickListener(this);
- }
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- //像预先注册过的BroadCastReceiver发送Intent以返回数据
- Intent intent = new Intent(MyReceiver.MYARECEIVER_ACTION);
-
- intent.putExtra("data",this.inputEdit.getText().toString());
- this.sendBroadcast(intent);
- this.finish();
-
-
- }
-
- }
-
复制代码
MyReceier
MyReceiver是我们自定义的BroadCastReceiver,会被动态的注册到系统中从而侦听相应的Intent,首先我们定义需要侦听的Intent的ACTION:MYARECEIVER_ACTION = "net.sswilliam.ane.callback.myreceiver"。同时我们会传入CallBackContext的引用。这样可以在处理Intent时向Actionscript端抛出事件。
注意FREContext中有一个dispatchStatusEventAsync方法可以从java代码向Actionscript端抛出ActionScript的事件。具体请查看NaiveExtension事件机制章节。
- package net.sswilliam.ane.callback;
-
- import com.adobe.fre.FREContext;
-
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
-
- public class MyReceiver extends BroadcastReceiver {
- private FREContext context;
- public static final String MYARECEIVER_ACTION = "net.sswilliam.ane.callback.myreceiver";
- public MyReceiver(FREContext context){
- this.context = context;
- }
-
- @Override
- public void onReceive(Context arg0, Intent arg1) {
- // TODO Auto-generated method stub
- String data = arg1.getExtras().getString("data");
- this.context.dispatchStatusEventAsync(CallBackContext.DATE_RECEIVE, data);
-
- }
-
- }
-
复制代码
作者: 破晓 时间: 2015-1-10 22:03
Flex Library项目Flex Library项目目录和代码如下:[attach]343[/attach]
CallBackExtension
CallBackExtension是我们这个NativeExtension的Actionscript的具体实现。同样我们会在其中先声明需要调用函数在Map中的Key,这两个Key和Java中的两个Key是完全相同的,申明成静态的常量可以减少编程时带来的拼写误差,也提高程序的可读性。
- public static const REGISTER_RECEIVER_FUNCTION:String = "register_receiver_function";
- public static const START_ACTIVITY_FUNCTION:String = "start_activity_function";
复制代码
对于Java端的两个函数,其中注册BroadCastReceiver的RegisterReceiverFunction函数会在CallBackExtension新建时就调用。从而将我们自定义的BroadCastReceiver动态的注册进系统。而StartActivityFunction函数提供给第三方程序进行调用。
- public function CallBackExtension(target:IEventDispatcher=null)
- {
- super(target);
- ext = ExtensionContext.createExtensionContext("net.sswilliam.ane.callback","");
- ext.addEventListener(StatusEvent.STATUS,onDataReceived);
- ext.call(REGISTER_RECEIVER_FUNCTION);
- }
- public function startActivity():void{
- ext.call(START_ACTIVITY_FUNCTION);
- }
复制代码
同时需要给ExtensionContext添加事件侦听函数。从而获得从Java端抛出的Actionscript事件。具体请查看NaiveExtension事件机制章节。
CallBackEvent
CallBackEvent是自定义的一个事件类,将从Java端接收到的事件和数据封装为Actionscript的一个事件对象,供具体使用该NativeExtension的app调用。
- package net.sswilliam.ane.callback
- {
- import flash.events.Event;
-
- public class CallBackEvent extends Event
- {
- public static const DATE_RECEIVE:String = "data_receive";
-
- public var callbackData:String = "";
- public function CallBackEvent(callBackData:String, bubbles:Boolean=false, cancelable:Boolean=false)
- {
- super(DATE_RECEIVE, bubbles, cancelable);
- this.callbackData = callBackData;
- }
- }
- }
复制代码
extension.xml
最后我们不能忘记在项目中添加相应的extension.xml文件对这个扩展做一个描述。大部分的tag都很清晰,就不过多解释了。注意的是namespace,虽然我们用3.0的sdk,但是在NativeExtension中还是2.5。
- <?xml version="1.0" encoding="UTF-8"?>
- <extension xmlns="http://ns.adobe.com/air/extension/2.5">
- <id>net.sswilliam.ane.callback</id>
- <versionNumber>1</versionNumber>
- <platforms>
- <platform name="Android-ARM">
- <applicationDeployment>
- <nativeLibrary>CallBack.jar</nativeLibrary>
- <initializer>net.sswilliam.ane.callback.CallBackExtension</initializer>
- <finalizer>net.sswilliam.ane.callback.CallBackExtension</finalizer>
- </applicationDeployment>
- </platform>
- </platforms>
- </extension>
复制代码
Flex Mobile 项目Flex Mobile项目目录结构和代码如下:
[attach]344[/attach]
在这个项目中,重点不在于App的开发,而在于app.xml的配置。
CallbackTest.mxml
只是一个很简单调用我们NativeExtension的程序。我们会在程序启动时直接实例化NativeExtension,然后添加事件。并且通过一个Button来开启Java原生的Activity。最后显示从Java返回的数据。代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
- xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="init(event)">
- <fx:Script>
- <![CDATA[
- import mx.events.FlexEvent;
-
- import net.sswilliam.ane.callback.CallBackEvent;
- import net.sswilliam.ane.callback.CallBackExtension;
-
- import spark.effects.CallAction;
-
- private var ext:CallBackExtension;
- protected function init(event:FlexEvent):void
- {
- // TODO Auto-generated method stub
- ext = new CallBackExtension();
- ext.addEventListener(CallBackEvent.DATE_RECEIVE,dataReceiverHandler);
-
- }
- private function dataReceiverHandler(e:CallBackEvent):void{
- this.console.appendText("data receiver:"+e.callbackData+"\n");
- }
-
- protected function startActivity(event:MouseEvent):void
- {
- // TODO Auto-generated method stub
- this.ext.startActivity();
- }
-
- ]]>
- </fx:Script>
- <fx:Declarations>
- <!-- 将非可视元素(例如服务、值对象)放在此处 -->
- </fx:Declarations>
- <s:Button x="10" y="10" label="call activity" click="startActivity(event)"/>
- <s:TextArea id="console" x="13" y="86" width="457" height="667"/>
- </s:Application>
-
复制代码
CallbackTest-app.xml
每一个AIR程序都需要一个app.xml文件对其进行描述。当AIR支持Android平台后,在app.xml中就多了一个的tag。里面会有一个manifestAdditions的子tag。在这里,就可以包含针对Android程序中的AndroidManifest.xml的一些信息的添加和修改。默认的,在这个tag里会包含如下信息:
- <android>
- <manifestAdditions><![CDATA[
- <manifest android:installLocation="auto">
-
- <!--See the Adobe AIR documentation for more information about setting Google Android permissions-->
- <!--删除 android.permission.INTERNET 权限将导致无法调试设备上的应用程序-->
- <uses-permission android:name="android.permission.INTERNET"/>
- <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>-->
- <!--<uses-permission android:name="android.permission.READ_PHONE_STATE"/>-->
- <!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>-->
- <!--应同时切换 DISABLE_KEYGUARD 和 WAKE_LOCK 权限,才能访问 AIR
- 的 SystemIdleMode API-->
- <!--<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>-->
- <!--<uses-permission android:name="android.permission.WAKE_LOCK"/>-->
- <!--<uses-permission android:name="android.permission.CAMERA"/>-->
- <!--<uses-permission android:name="android.permission.RECORD_AUDIO"/>-->
- <!--应同时切换 ACCESS_NETWORK_STATE 和 ACCESS_WIFI_STATE 权限,才能使用 AIR
- 的 NetworkInfo API-->
- <!--<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>-->
- <!--<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>-->
- </manifest>
-
- ]]></manifestAdditions>
- </android>
复制代码
从中可以看出,主要是对permission的一些设置。这些permission由AIR SDK自动添加到最终生成的AndroidManifest当中。
在原生的Android App中,当我们需要注册一个Activity时,可以直接修改AndroidManifest.xml文件。那么当我们向要在用AIR开发的Android app注册一个Activity要怎么做呢?其实也很简单,只要在AIR的app.xml的Android中添加相应的Tag即可。如下图红色标记,这里我们就向我们的AIR app添加了一个MyActivity的Activity。同时也定义了相应的IntentFilter。这里一定要注意两点
1. 包括在application tag里,在原生Android开发中,Activity也是注册在application tag里的。但是AIR的app.xml里没有这个tag,经过测试,发现直接在app.xml里添加application tag,最终application tag里的内容也会合并到最后生成的AndroidManifest.xml中。
2. android:name的值与Android项目中的Activity的包路径相同。
- <android>
- <manifestAdditions><![CDATA[
- <manifest android:installLocation="auto">
- <application>
- <activity android:name="net.sswilliam.ane.callback.MyActivity">
- <intent-filter>
- <action android:name="net.sswilliam.ane.callback.myactivity" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
- </application>
- <!--See the Adobe AIR documentation for more information about setting Google Android permissions-->
- <!--删除 android.permission.INTERNET 权限将导致无法调试设备上的应用程序-->
- <uses-permission android:name="android.permission.INTERNET"/>
- <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>-->
- <!--<uses-permission android:name="android.permission.READ_PHONE_STATE"/>-->
- <!--<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>-->
- <!--应同时切换 DISABLE_KEYGUARD 和 WAKE_LOCK 权限,才能访问 AIR
- 的 SystemIdleMode API-->
- <!--<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>-->
- <!--<uses-permission android:name="android.permission.WAKE_LOCK"/>-->
- <!--<uses-permission android:name="android.permission.CAMERA"/>-->
- <!--<uses-permission android:name="android.permission.RECORD_AUDIO"/>-->
- <!--应同时切换 ACCESS_NETWORK_STATE 和 ACCESS_WIFI_STATE 权限,才能使用 AIR
- 的 NetworkInfo API-->
- <!--<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>-->
- <!--<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>-->
- </manifest>
-
- ]]></manifestAdditions>
- </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中,就是调用FREContext的dispatchStatusEventAsync(arg0, arg1),它和Actionscript中的dispatchEvent(event)是不同的。在Actionscript中的dispatchEvent方法中主要传入的参数是一个Event对象,这个Event的一些具体参数需要自己进行封装。而dispatchStatusEventAsync(arg0, arg1)传入的是两个String,这个方法会在java端像actionscript端抛出StatusEvent对象,arg0被当做StatusEvent的code而arg1被当做StatusEvent的level。其中level可以被用作事件传递的数据,如果有复杂格式的数据,可以将数据封装成json或者xml,或者就简单的用分隔符分隔开。
Java端代码如下:
- this.context.dispatchStatusEventAsync("Status1", "data1;data2;data3");
复制代码
侦听事件:
接收事件主要在Actionscript进行,直接在ExtensionContext对象上添加StatusEvent.Status事件的侦听即可
- ext = ExtensionContext.createExtensionContext("net.sswilliam.ane.callback","");
- ext.addEventListener(StatusEvent.STATUS,onDataReceived);
复制代码
处理事件:
处理事件其实就是标准的用Switch Case处理StatusEvent事件的函数。官方文档里有很多范例。通过判断不同的code和level从而进行具体的逻辑处理。
- private function onDataReceived(e:StatusEvent):void{
- switch(e.code)
- {
- case "Status1":
- {
- var result:String = e.level;
- var datas:Array = result.split(";");
- trace(datas);
- break;
- }
-
- default:
- {
- break;
- }
- }
- }
复制代码
总结在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中的
- <android>
- <manifestAdditions><![CDATA[
-
- ]]></manifestAdditions>
- </android>
复制代码
里的内容自动的映射到最终的AndroidManifest.xml中。
如原本AIR APP的AndroidManifest是这样的:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest android:versionCode="0" android:versionName="@string/app_version" android:installLocation="auto" package="air.CallbackTest.debug"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <application android:label="@string/app_name" android:icon="@drawable/icon" android:hardwareAccelerated="true">
- <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">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- <meta-data android:name="autoOrients" android:value="false" />
- <meta-data android:name="fullScreen" android:value="false" />
- <meta-data android:name="uniqueappversionid" android:value="51f23dd3-5056-4831-ac9d-df2fcdca82a8" />
- <meta-data android:name="initialcontent" android:value="CallbackTest.swf" />
- </activity>
- </application>
- <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="11" />
- <uses-permission android:name="android.permission.INTERNET" />
- </manifest>
复制代码
如果我们在Android Tag中添加如下代码:
- <android>
- <manifestAdditions><![CDATA[
- <manifest android:installLocation="auto">
- <application>
- <activity android:name="net.sswilliam.ane.callback.MyActivity">
- <intent-filter>
- <action android:name="net.sswilliam.ane.callback.myactivity" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
- </application>
-
- </manifest>
-
- ]]></manifestAdditions>
- </android>
复制代码
那么打包后再查看AndroidManifest.xml, 就会变成这样:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest android:versionCode="0" android:versionName="@string/app_version" android:installLocation="auto" package="air.CallbackTest.debug"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <application android:label="@string/app_name" android:icon="@drawable/icon" android:hardwareAccelerated="true">
- <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">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- <meta-data android:name="autoOrients" android:value="false" />
- <meta-data android:name="fullScreen" android:value="false" />
- <meta-data android:name="uniqueappversionid" android:value="ab57dfb0-5b52-4e80-8a6d-f9dedda9a76e" />
- <meta-data android:name="initialcontent" android:value="CallbackTest.swf" />
- </activity>
- <activity android:name="net.sswilliam.ane.callback.MyActivity">
- <intent-filter>
- <action android:name="net.sswilliam.ane.callback.myactivity" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
- </application>
- <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="11" />
- <uses-permission android:name="android.permission.INTERNET" />
- </manifest>
复制代码
Apktool是个很好的工具,大家不妨各种不同方法打包出来的apk文件反编译一下,就可以发现各自的实现原理了。
| 欢迎光临 守望者--AIR技术交流 (http://www.airmyth.com/) |
|