守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 4481|回复: 8
打印 上一主题 下一主题

[平台接入] [AIR接入Android 平台]打造登录付费ANE全教程

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52903
    钢镚
    1422

    开源英雄守望者

    跳转到指定楼层
    楼主
    发表于 2014-12-30 22:33:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

    本文来自:http://bbs.9ria.com/thread-197503-1-1.html


    目前为止我为项目共接入了大概7-8家或大或小的平台。深知AIR移动项目接入运营平台在打造ANE过程中会有各种各样的问题。在这里我打算把我遇到的问题 和解决方式记录下来,也许你用得着 也许你已经遇到过 也许你已经解决掉。接下来我会从我的air项目和各种android应用运营平台方的SDK接入过程 中 遇到的问题进行探讨。其中有些问题已经解决 有些问题解决得很差强人意,有些问题尚未解决。也请已经解决了这些问题的朋友  能和我交流。当然我对原生android开发刚刚入门 有一些看法或多或少存在错误。也请看到的朋友能Email我指出。(rectvv[at]gmail[dot]com)


    再次声明下,这里仅仅写下我遇到的问题 和我个人的解决方式 关于ANE还有很多很多我没遇到的问题。同样如果同一个问题 您有更好的解决方式 希望能指导下我。小弟不胜感激。


    首先关于最近大家都在群里讨论 AIR是生是死的问题,ASER是否转行的问题,我觉得应该把当下的事情做好,就像CODE COMPLETE里面说的一样。程序员应该是超越语言的。当然我目前还没到这水平。接下来进入正题。

    在这之前 我之前写了一些关于ANE更早的一些文章:

    http://www.shadowkong.com/archives/tag/ane

    ————————————————–

    我的项目信息

    使用的跨平台技术:Adobe Air

    使用的GPU加速框架(引擎?):Starling

    使用的AIR SDK版本:3.5(AIR3.5打包STARLING项目出来的的APK对于HTC的机器会有一个BUG,更新到AIR3.7之后 HTC的BUG解决了 但是对三星的一款机器又出一个新BUG 目前我还在寻找完美的解决方式  当前我的解决方式并不完美 详细的BUG描述会在后面统计的时候给出)

    在接入的那么多平台中 在这里选择一个平台SDK看起来最繁琐 在打包ANE的时候 需要做的处理最多的 平台 做为例子。当然由于这个平台的SDK里面明确表示不允许 向他人 传播。所以我在后面的源码 与 附件中 会把 该平台的相关JAR 文档 等等去掉。但是如果你也接这个平台 那你可以完全拿过来套用。


    接入的平台信息

    针对设备:android

    需要打包入AIR APK的资源有:res  assets两种资源处理方式都有。(在之前我就写过一篇关于ANE如何处理资源的问题的文章)平台方接入的第三方(对于游戏是第四方):微博授权登录   QQ授权登录

    平台方需要加入的activity情况:这个平台需要加入的activity声明是最多的 在这个平台的 -app.xml也是最臃肿的,这会涉及到一个SDK activity 与 游戏activity 如何通信切换的问题。在之前就遇到过一个问题 把游戏主activity传给SDK的时候 执行完SDK操作  返回不了游戏activity 详细的解决方式 请看我前面的一篇文章。

    平台方需要加入的JAR数量:6个(平台方的JAR最后全部都需要打包成一个JAR 才能生成ANE 这个问题的解决方式后面会给出)

    ——————————————————-


    第一步 准备工作

    1.在这之前需要先安装 JDK  JRE  并且添加环境变量如图:

    (路径自己按照各自环境配置)这两个工具 请自行下载

    配置JAR 配置JDK:例如我的路径:C:\Program Files\Java\jdk1.7.0_17\bin  加入 环境变量 系统变量




    2.安装FB6 eclipse androidSDK  按照正常教程配置android开发环境 推荐下载androidSDK :2.2,2.3,4.0  

    我的项目全部统一使用android SDK2.3.3

    这些编辑器 SDK IDE等全部自行下载。。>.<


    3.一般平台SDK都会需要在assets加APK或者资源,这就需要命令行 编译 打包。所以建议在环境变量中加入 amxmlc例如我的是在其中加入:D:\FB\Adobe Flash Builder 4.6\sdks\AIR3.5\bin  命名为amxmlc  这样就可以在CMD中直接使用命令行编译了,若想命令行打包 则也一样的 直接加入 ADT所在路径即可。(这并不是必须的  仅仅为了更好的使用命令行)


    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
    收藏收藏 分享分享 支持支持 反对反对 微信
    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52903
    钢镚
    1422

    开源英雄守望者

    沙发
     楼主| 发表于 2014-12-30 22:40:50 | 只看该作者
    [AIR接入Android 平台]第二步 编写 JAVA端接口 与 AS端接口项目

    博文地址:http://www.shadowkong.com/archives/1106

    这和编写其他所有ANE类似。网上可以找到一堆的教程。但是我觉得都针对性不太强。如果你已经对编写ANE有足够的把握 那这篇文章完全可以不看。

    一点声明:我的水平有限 这里仅仅只能写出我认为可行的方案 和 代码

    而且针对接入平台运营商的情况。这种ANE基本都具有四个功能:

    初始化SDK  -> 登录 -> 付费 -> 退出

    所以我决定针对接入android平台而写一个基本的ANE教程。我接入的所有平台的ANE 都是基于教程中给出的源码而做的改进。

    ANE作为AIR调用本地代码的机制 他的组成分为两部分:

    在开始之前 先限定一些共同的ID:

    接口 ID:com.rect.ane

    初始化SDK标识:rect_function_init

    登录标识:rect_function_login

    付费标识:rect_function_pay

    退出SDK标识:rect_function_exit

    1.JAVA端项目新建库项目 如图



    注意包名最好和我们在之前限定的接口 ID一致。然后记得勾选为library



    然后一直确定 生成项目  Rectane。在eclipse中右键项目属性 – java构建路径 – 源代码 – Rectane/gen – 包括选择[包括]点击编辑  在[包括模式]中 点击 添加 输入 nothing 按确定。完成后如图



    接下来加入AIR SDK中的 FlashRuntimeExtensions.jar 文件到项目下的lib文件夹 然后导入到项目中 如图



    接下来就是贴代码的时间了:RectContext.java

    1. package com.rect.ane;

    2. import java.util.HashMap;
    3. import java.util.Map;

    4. import com.adobe.fre.FREContext;
    5. import com.adobe.fre.FREFunction;

    6. /**
    7. * @author Rect
    8. * @version  Time:2013-5-8
    9. */
    10. public class RectContext extends FREContext {
    11. /**
    12. * INIT sdk
    13. */
    14. public static final String RECT_FUNCTION_INIT = "rect_function_init";
    15. /**
    16. * 登录Key
    17. */
    18. public static final String RECT_FUNCTION_LOGIN = "rect_function_login";
    19. /**
    20. * 付费Key
    21. */
    22. public static final String RECT_FUNCTION_PAY = "rect_function_pay";
    23. /**
    24. * 退出Key
    25. */
    26. public static final String RECT_FUNCTION_EXIT = "rect_function_exit";
    27. @Override
    28. public void dispose() {
    29. // TODO Auto-generated method stub

    30. }

    31. @Override
    32. public Map getFunctions() {
    33. // TODO Auto-generated method stub
    34. Map map = new HashMap();
    35. //         //映射
    36. map.put(RECT_FUNCTION_INIT, new RectInit());
    37. map.put(RECT_FUNCTION_LOGIN, new RectLogin());
    38. map.put(RECT_FUNCTION_PAY, new RectPay());
    39. map.put(RECT_FUNCTION_EXIT, new RectExit());
    40. return map;
    41. }

    42. }
    复制代码

    RectExtension.java

    1. package com.rect.ane;

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

    4. /**
    5. * @author Rect
    6. * @version  Time:2013-5-8
    7. */
    8. public class RectExtension implements FREExtension {

    9. @Override
    10. public FREContext createContext(String arg0) {
    11. // TODO Auto-generated method stub
    12. return new RectContext();
    13. }

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

    17. }

    18. @Override
    19. public void initialize() {
    20. // TODO Auto-generated method stub

    21. }

    22. }
    复制代码

    更多的详细代码 请看附件中的 Rectane_java 项目
    在源码中会有更详细的表述2.AS 端项目
    AS项目是作为和JAVA对应的。负责侦听返回 和调用JAVA函数
    这里使用 FB 建立一个 手机库项目 然后在里面加两个类:
    RectEvents.as

    1. package com.rect.ane
    2. {
    3. /**
    4. *
    5. * @author Rect  2013-5-6
    6. *
    7. */
    8. public class RectEvents
    9. {
    10. public function RectEvents()
    11. {
    12. }
    13. /**************************平台通知************************************/
    14. /**
    15. *init
    16. */
    17. public static const DEMO_SDK_STATUS:String = "DemoInit";
    18. /**
    19. * 用户登录
    20. */
    21. public static const DEMO_LOGIN_STATUS : String = "DemoLogin";

    22. /**
    23. * 用户注销
    24. */
    25. public static const DEMO_LOGOUT_STATUS : String = "DemoExit";

    26. /**
    27. * 充值
    28. */
    29. public static const DEMO_PAY_STATUS : String = "DemoPay";
    30. }
    31. }
    复制代码

    RectExtension.as


    1. package com.rect.ane
    2. {
    3. import flash.events.EventDispatcher;
    4. import flash.events.IEventDispatcher;
    5. import flash.events.StatusEvent;
    6. import flash.external.ExtensionContext;

    7. /**
    8. *
    9. * @author Rect  2013-5-6
    10. *
    11. */
    12. public class RectExtension extends EventDispatcher
    13. {
    14. public static const RECT_FUNCTION_INIT:String = "rect_function_init";//与java端中Map里的key一致
    15. public static const RECT_FUNCTION_LOGIN:String = "rect_function_login";//与java端中Map里的key一致
    16. public static const RECT_FUNCTION_PAY:String = "rect_function_pay";//与java端中Map里的key一致
    17. public static const RECT_FUNCTION_EXIT:String = "rect_function_exit";//与java端中Map里的key一致

    18. public static const EXTENSION_ID:String = "com.rect.ane";//与extension.xml中的id标签一致
    19. private var extContext:ExtensionContext;

    20. /**单例的实例*/
    21. private static var _instance:RectExtension;
    22. public function RectExtension(target:IEventDispatcher=null)
    23. {
    24. super(target);
    25. if(extContext == null) {
    26. extContext = ExtensionContext.createExtensionContext(EXTENSION_ID, "");
    27. extContext.addEventListener(StatusEvent.STATUS, statusHandler);
    28. }

    29. }

    30. //第二个为参数,会传入java代码中的FREExtension的createContext方法
    31. /**
    32. * 获取实例
    33. * @return DLExtension 单例
    34. */
    35. public static function getInstance():RectExtension
    36. {
    37. if(_instance == null)
    38. _instance = new RectExtension();
    39. return _instance;
    40. }

    41. /**
    42. * 转抛事件
    43. * @param event 事件
    44. */
    45. private function statusHandler(event:StatusEvent):void
    46. {
    47. dispatchEvent(event);
    48. }

    49. /**
    50. *init发送函数
    51. * @param key 暂时传什么都可以  留着可能要用
    52. * @return
    53. *
    54. */
    55. public function FeiliuInit(key:int):String{
    56. if(extContext ){
    57. return extContext.call(RECT_FUNCTION_INIT,key) as String;
    58. }
    59. return "call login failed";
    60. }

    61. /**
    62. *登录发送函数
    63. * @param key 暂时传什么都可以  留着可能要用
    64. * @return
    65. *
    66. */
    67. public function FeiliuLogIn(key:int):String{
    68. if(extContext ){
    69. return extContext.call(RECT_FUNCTION_LOGIN,key) as String;
    70. }
    71. return "call login failed";
    72. }
    73. /**
    74. *付费发送函数
    75. * @param key 暂时传什么都可以 留着以后可能要用
    76. * @return
    77. *
    78. */
    79. public function FeiliuPay(data:Vector.,len:int = 5):String{
    80. if(extContext && data.length == len){
    81. return extContext.call(RECT_FUNCTION_PAY,data)as String;
    82. }
    83. return "call pay failed";
    84. }

    85. /**
    86. *退出SDK时候调用   这个函数只在退出游戏的时候调用
    87. * @param key
    88. * @return
    89. *
    90. */
    91. public function ExitSDKHandle(key:int):String{
    92. if(extContext){
    93. return extContext.call(RECT_FUNCTION_EXIT,key) as String;
    94. }
    95. return "call exit failed";
    96. }
    97. }
    98. }
    复制代码

    仔细看这两个类就可以发现 在前面说的 接口ID 和 各个函数调用的 ID 都必须保持一致
    3.extension.xml 文件-



    XML文件中要注意的是 必须保存一致4.打包ANE  在 1 2 3进行完了之后 我们去取到一下文件
    A>.JAVA项目下的 :Rect\Rectane_java\bin\rectane.jar
    B>AS库项目下的:Rect\RectANE_as\bin\RectANE.swc
    C>XML文件:extension.xml
    D>新建一个KEY文件:rect.p12(可用FB新建)
    F>解压RectANE 获得:catalog.xml library.swf
    总共 6个文件然后新建文件夹  Rect_make_ane
    在 Rect_make_ane文件夹下 新建 android-ARM文件夹
    然后上述6个文件分别放在下面:
    rectane.jar – > Rect_make_ane/android-ARM/rectane.jar
    catalog.xml – > Rect_make_ane/android-ARM/catalog.xml
    library.swf – > Rect_make_ane/android-ARM/library.swf
    RectANE.swc -> Rect_make_ane/RectANE.swc
    extension.xml – > Rect_make_ane/extension.xm
    lrect.p12 -> Rect_make_ane/rect.p12

    具体的看源码中的文件夹在打包ANE之前 接入平台的时候 还有一步 就是 合成 把 平台jar和 rectane.jar 一起合成一个jar 后续文章会详细介绍然后使用命令行打包 我在这里写成了一个批处理:(注意路径自己配
    )“[你的AIR SDK路径]\bin\adt” -package -storetype PKCS12 -keystore rect.p12 -storepass 1234 -target ane com.rect.ane extension.xml -swc *.swc -platform Android-ARM -C Android-ARM .
    保存为 ane_pacler.bat 在 Rect_make_ane文件夹下
    然后运行这里bat 就可以生成 ane了至此  ane 成功编写出来。
    注意:真正接入平台 的ANE  还需要 在JAVA项目中导入平台jar 然后在各个函数中编写各种操作。在把平台jar 和 rectane.jar一起打包成一个jar  再打包ANE我在这里把 平台jar 合成最终的 jar 略去 在后面的文章中会具体详细的说明过程。






    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52903
    钢镚
    1422

    开源英雄守望者

    板凳
     楼主| 发表于 2014-12-30 22:42:49 | 只看该作者
    [AIR接入Android 平台]第三步 打包处理多个JAR变成一个JAR提供给

    一点声明:我的水平有限 这里仅仅只能写出我认为可行的方案 和 代码

    接入android 运营平台 一般平台方都会提供一个或者更多的jar包。但是我们的ane只能打包一个jar包。这就需要我们把这些jar全部集合到一个去。

    我的方法是基于一个兄台的教程的改进:http://bbs.9ria.com/thread-160445-1-1.html

    拿我接过的最繁琐的一个SDK来说,它要求我必须连入6个jar。如图



    需要把 其余的jar 都合并到 flane.jar中。

    我们改进上面那个兄台的bat如下:


    1. @echo off
    2. ::转到当前盘符
    3. %~d0
    4. ::打开当前目录
    5. cd %~dp0
    6. ::你做的主JAR包的路径
    7. set MainJar=flane.jar
    8. ::第三方JAR包的路径
    9. set jar1=androidsdklibrary.jar
    10. set jar2=gamehelper.jar
    11. set jar3=oauth20.jar
    12. set jar4=oauth20-api.jar
    13. set jar5=sinaweibosso.jar
    14. set jar6=tencent_openapi.jar
    15. ::第三方JAR包顶级包名称
    16. set packageName1=com
    17. set packageName2=org
    18. set packageName3=android
    19. echo =========== start combin ==============
    20. ::解压第三方包
    21. jar -xf %jar1%
    22. jar -xf %jar2%
    23. jar -xf %jar3%
    24. jar -xf %jar4%
    25. jar -xf %jar5%
    26. jar -xf %jar6%
    27. ::合并主JAR包
    28. jar -uf %MainJar% %packageName1%
    29. ::如果还有别的顶级包可以接着合并,例如:
    30. jar -uf %MainJar% %packageName2%
    31. jar -uf %MainJar% %packageName3%
    32. echo =========== over ==============
    33. echo 再点一下就结束了--小Q
    34. pause
    复制代码

    就可以了。这个方法适用于合并N个jar。
    声明下 这并不是我的原创。感谢上面那位兄台的分享。



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52903
    钢镚
    1422

    开源英雄守望者

    地板
     楼主| 发表于 2014-12-30 22:45:47 | 只看该作者
    [AIR接入Android 平台]处理res资源之文字国际化

    一点声明:我的水平有限 这里仅仅只能写出我认为可行的方案 和 代码

    文字国际化 其实是android编码的规范之一。但是不同的运营商提供的SDK 这块处理的都不一样。

    就目前我接触过的平台来说。当乐 UC 91 360 算做得很好。

    但是其他小平台  特别是有一个运营商 他们客户端技术才一个人。

    都很不注重android文字国际化的问题。打包进ane的资源 布局文件XML必须是规范的国际化处理的。

    否则就会在打包APK的时候报错。

    例如下面:



    一般这个错误在打包ANE的时候是不会报的。而在打包APK的时候就会报出来。如图所示 这个错误主要是由于  ANE中的资源文件夹RES下的layout文件夹下的布局XML中的text 被SDK客户端程序员直接用代码写的。所以会直接写在layout的布局XML里面。而一般android官方开发标准推荐更标准化的写法。把layout中的text的内容写入 value文件夹下的string.xml中。而我们的ADT打包就是遵从这种标准。例如layout某XML的一段:<TextView
    android:layout_width=”wrap_content”
    android:layout_height=”wrap_content”
    android:text=”账号 : “
    android:textColor=”#A67D3D”
    android:textSize=”17sp” />

    红色部分的写法是错误的 正确的写法是 把红色部分变为:

    <TextView
    android:layout_width=”wrap_content”
    android:layout_height=”wrap_content”
    android:text=”@string/text001 “
    android:textColor=”#A67D3D”
    android:textSize=”17sp” />

    在res下的value文件夹下的string.xml中加入:
    <string name=”text001“>账号 :</string>

    这样才是规范的res文件。

    为了批量出来这种事情 我写了一个工具类


    1. package
    2. {
    3.         import flash.desktop.Clipboard;
    4.         import flash.desktop.ClipboardFormats;
    5.         import flash.desktop.NativeDragManager;
    6.         import flash.display.InteractiveObject;
    7.         import flash.display.Loader;
    8.         import flash.display.Sprite;
    9.         import flash.events.Event;
    10.         import flash.events.MouseEvent;
    11.         import flash.events.NativeDragEvent;
    12.         import flash.filesystem.File;
    13.         import flash.filesystem.FileMode;
    14.         import flash.filesystem.FileStream;
    15.         import flash.net.FileFilter;
    16.         import flash.net.FileReference;
    17.         import flash.net.URLLoader;
    18.         import flash.net.URLRequest;
    19.         import flash.text.TextField;
    20.         import flash.text.TextFormat;
    21.         
    22.         import flashButton.backButton;
    23.         
    24.         /**
    25.          *
    26.          * @author Rect  2013-4-16
    27.          *
    28.          */
    29.         [SWF(width="800" , height="600")]
    30.         public class FileXMLHandle extends Sprite
    31.         {
    32.                 private var sp:Sprite;
    33.                 private var mapAry:Array = [];
    34.                 private var test:TextField;
    35.                 private var beginBtn:backButton;
    36.                 private var SelectBtn:backButton;
    37.                 private var outBtn:backButton;
    38.                 private var textSize:TextField;
    39.                 private var textQuality:TextField;
    40.                 private var fileObj:FileReference = new FileReference();
    41.                 private var selectedSaveFile:File;
    42.                 private var fileArr:Array = [];
    43.                 private var key:String;
    44.                 public function FileXMLHandle()
    45.                 {
    46.                         super();
    47.                         init();
    48.                 }
    49.                 private function init():void{
    50.                         sp = new Sprite();
    51.                         test = new TextField();
    52.                         test.defaultTextFormat = (new TextFormat("",18,0xFFFFF));
    53.                         test.text = "拖入此处";
    54.                         test.width = 400;
    55.                         test.height = 400;
    56.                         test.wordWrap = true;
    57.                         test.multiline = true;
    58.                         
    59.                         sp.addChild(test);
    60.                         sp.graphics.beginFill(0x3CB371);
    61.                         sp.graphics.drawRect(0,0,800,600);
    62.                         sp.graphics.endFill();
    63.                         this.addChild(sp);
    64.                         sp.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, onDragInHandler);
    65.                         sp.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, onDropHandler);
    66.                         
    67.                         selectedSaveFile = new File();
    68.                         selectedSaveFile.addEventListener(flash.events.Event.SELECT, onSelectedSaveFile);
    69.                         var fileFilt:FileFilter = new FileFilter("输出文件(*.xml)", "*.xml");
    70.                         fileArr.push(fileFilt);
    71.                         
    72.                         beginBtn = new backButton("开始");
    73.                         beginBtn.x = 600,beginBtn.y = 110;
    74.                         beginBtn.mouseEnabled = false;
    75.                         beginBtn.addEventListener(MouseEvent.CLICK,onChick);
    76.                         this.addChild(beginBtn);
    77.                         
    78.                         SelectBtn = new backButton("选择string.xml");
    79.                         SelectBtn.x = 600,SelectBtn.y = 10;
    80.                         SelectBtn.addEventListener(MouseEvent.CLICK,onSelectFile);
    81.                         this.addChild(SelectBtn);
    82.                         
    83.                         outBtn = new backButton("选择输出文件夹");
    84.                         outBtn.x = 600,outBtn.y = 60;
    85.                         outBtn.addEventListener(MouseEvent.CLICK,onSelectPath);
    86.                         this.addChild(outBtn);
    87.                         
    88.                         
    89.                 }
    90.                
    91.                 private function onSelectedSaveFile(e:flash.events.Event):void
    92.                 {
    93.                         var str:String = selectedSaveFile.nativePath;
    94.                         var __reg:RegExp = new RegExp('\\\\', '');
    95.                         
    96.                         switch(key)
    97.                         {
    98.                                 case "file":
    99.                                         motherFileArys = str.replace(/\\/g,"/");
    100.                                         break;
    101.                                 
    102.                                 case "path":
    103.                                         outPath = str.replace(/\\/g,"/");
    104.                                         trace(outPath)
    105.                                         break;
    106.                         }
    107.                         
    108.                         if(motherFileArys && outPath)HandleMaps();
    109.                 }
    110.                 private var motherFileArys:String = null;
    111.                 private var outPath:String = null;
    112.                 private var _loaderImages:URLLoader  = new URLLoader();
    113.                 private var stringXML:XML;
    114.                 private var miscXML:XML;
    115.                 private function HandleMaps():void{
    116.                                 _loaderImages.addEventListener(Event.COMPLETE,loaderInitListeners);
    117.                                 _loaderImages.load(new URLRequest(motherFileArys));
    118.                 }
    119.                
    120.                 private function loaderInitListeners(evt:Event):void {
    121.                         _loaderImages.removeEventListener(Event.COMPLETE,loaderInitListeners);
    122.                         stringXML = XML(_loaderImages.data);
    123.                         _loaderImages.close();
    124.                         
    125.                 }
    126.                
    127.                 /**********************************/
    128.                 private function onChick(ev:MouseEvent):void{
    129.                         
    130.                         HandleMap();
    131.                 }
    132.                
    133.                 private function onSelectFile(ev:MouseEvent):void{
    134.                         key = "file";
    135.                         selectedSaveFile.browse(fileArr);
    136.                 }
    137.                
    138.                 private function onSelectPath(ev:MouseEvent):void{
    139.                         key = "path";
    140.                         selectedSaveFile.browseForDirectory("请选择目录");
    141.                 }
    142.                
    143.                 private function textDown(ev:MouseEvent):void{
    144.                         var text:TextField = ev.currentTarget as TextField;
    145.                         text.text = "";
    146.                 }
    147.                 protected function onDragInHandler(event : NativeDragEvent) : void
    148.                 {
    149.                         var transferable :Clipboard = event.clipboard;
    150.                         if(transferable.hasFormat(ClipboardFormats.FILE_LIST_FORMAT))
    151.                         {
    152.                                 var files : Array = transferable.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
    153.                                 if(files)
    154.                                 {
    155.                                         var file : File = File(files[0]);
    156.                                        
    157.                                         if(file && file.name.indexOf(".xml") >= 0 || file && file.name.indexOf(".XML") >= 0)
    158.                                         {
    159.                                                 NativeDragManager.acceptDragDrop(event.currentTarget as InteractiveObject);
    160.                                         }
    161.                                 }
    162.                                 
    163.                         }
    164.                 }
    165.                
    166.                 private var motherFileAry:Array = [];
    167.                 private var sonFileAry:Array = [];
    168.                 private var xmlHead:String = '<?xml version="1.0" encoding="utf-8" ?>';
    169.                 protected function onDropHandler(event : NativeDragEvent) : void
    170.                 {
    171.                         motherFileAry = [];
    172.                         sonFileAry = [];
    173.                         var transferable :Clipboard = event.clipboard;
    174.                         var files : Array = transferable.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
    175.                         if(files)
    176.                         {
    177.                                 var file :File;
    178.                                 for(var t:int = 0;t<files.length;t++){
    179.                                         file  = File(files[t]);
    180.                                         test.appendText("\n"+file.url);
    181.                                         motherFileAry.push(file.url);
    182.                                        
    183.                                         sonFileAry.push(outPath+"/"+ file.name);
    184.                                 }
    185.                                 if(sonFileAry.length != 0 ){
    186.                                         if(motherFileArys && outPath)this.beginBtn.mouseEnabled = true;
    187.                                 }else{
    188.                                 }
    189.                                 
    190.                                 trace(motherFileAry,outPath);//(file.name.length - 4))));
    191.                         }
    192.                 }
    193.                
    194.                 private var _loaderImage:URLLoader  = new URLLoader();
    195.                 private function HandleMap():void{
    196.                         if(motherFileAry.length){
    197.                                 _loaderImage.addEventListener(Event.COMPLETE,loaderInitListener);
    198.                                 _loaderImage.load(new URLRequest(motherFileAry.splice(0,1)));
    199.                         }else
    200.                         {
    201.                                 this.beginBtn.mouseEnabled = false;
    202.                                 test.text = ("完成!");
    203.                                 makeValue();
    204.                         }
    205.                 }
    206.                
    207.                 private function makeValue():void
    208.                 {
    209.                         
    210.                         for(var t:int = 0;t<stringArr.length;t++)
    211.                         {
    212.                                 stringXML.appendChild(<string name = {stringName[t]}>{stringArr[t]}</string>);
    213.                         }
    214.                         
    215.                         var filePath:String = motherFileArys ;
    216.                         var f:FileStream = new FileStream();
    217.                         var fl:File = new File(filePath);
    218.                         
    219.                         f.open(fl,FileMode.WRITE);
    220.                         var xmlStr1:String = stringXML.toString();
    221.                         var pattern1:RegExp = /\n/g;
    222.                         xmlStr1=xmlStr1.replace(pattern1, "\r\n");
    223.                         f.writeUTFBytes(String(xmlHead+"\r\n"+ xmlStr1));
    224.                         f.close();
    225.                         
    226.                         
    227.                 }
    228.                
    229.                 private function loaderInitListener(evt:Event):void {
    230.                         
    231.                         _loaderImage.removeEventListener(Event.COMPLETE,loaderInitListener);
    232.                         
    233.                         var xml:XML = XML(_loaderImage.data);
    234.                         
    235.                         walk(xml);
    236.                         
    237.                         makeFile(xml);
    238.                         
    239.                         HandleMap();
    240.                 }
    241.                
    242.                
    243.                 private function makeFile(str:XML):void{
    244.                         
    245.                         var filePath:String = (sonFileAry.splice(0,1)) ;
    246.                         var f:FileStream = new FileStream();
    247.                         var fl:File = new File(filePath);
    248.                         
    249.                         f.open(fl,FileMode.WRITE);
    250.                         
    251.                         var xmlStr:String = str.toString();
    252.                         var pattern:RegExp = /\n/g;
    253.                         xmlStr=xmlStr.replace(pattern, "\r\n");
    254.                         f.writeUTFBytes(String(xmlHead+"\r\n"+ xmlStr));
    255.                         
    256.                         f.close();
    257.                         
    258.                 }
    259.                
    260.                 private var stringArr:Array = [];
    261.                 private var stringName:Array = [];
    262.                 private var stringLen:int = 0;
    263.                
    264.                
    265.                 private function walk( node:XML ):void {
    266.                         
    267.                         var androidNS:Namespace = new Namespace("android","http://schemas.android.com/apk/res/android");
    268.                         node.addNamespace(androidNS);
    269.                         
    270.                         
    271.                         // Loop over all of the child elements of the node
    272.                         for each ( var element:XML in node.elements( ) ) {
    273.                                 // Output the label attribute
    274.                                 var attributes:XMLList = element.attributes( );
    275.                                 
    276.                                 for(var t:int = 0;t<100;t++)
    277.                                 {
    278.                                         if(!attributes[t])
    279.                                                 break;
    280.                                        
    281.                                         var str:String = attributes[t] ;
    282.                                         var pattern4:RegExp=/[\u4e00-\u9fa5]/;
    283.                                         if(pattern4.test(str))
    284.                                         {
    285.                                                 stringArr.push(str);
    286.                                                 stringName.push("DW_string_" + stringLen);
    287.                                                 
    288.                                                 attributes[t] = "@string/DW_string_" + stringLen.toString();
    289.                                                 
    290.                                                 stringLen++;
    291.                                         }
    292.                                 
    293.                                 
    294.                         }
    295.                                 walk( element );
    296.                         }
    297.                 }
    298.         }
    299. }
    300.                         
    301.                
    复制代码

    Button

    1. package flashButton
    2. {
    3.         import flash.display.Sprite;
    4.         import flash.events.MouseEvent;
    5.         import flash.text.TextField;
    6.         import flash.text.TextFieldAutoSize;
    7.         import flash.text.TextFormat;

    8.         public class backButton extends Sprite
    9.         {
    10.                 private var _buttonName:String;
    11.                 private var _szWide:Number;
    12.                 private var _szHeight:Number;
    13.                 private var _Color:int;
    14.                 public function backButton(
    15.                         buttonName:String,
    16.                         szWide:Number = 180,
    17.                         szHeight:Number = 40,
    18.                         Color:int = 0xFFFFFF)
    19.                 {
    20.                         _buttonName = buttonName;
    21.                         _szWide = szWide;
    22.                         _szHeight = szHeight;
    23.                         _Color = Color;
    24.                         init();
    25.                 }
    26.                 private var _text:TextField;
    27.                 private var _textFormat:TextFormat;
    28.                 private function init():void{
    29.                         _text = new TextField();
    30.                         _text.mouseEnabled = false;
    31.                         _text.text = _buttonName;
    32.                         _text.x = 2;
    33.                         _text.y = 2;
    34.                         _text.width = _szWide-5;
    35.                         _text.height = _szHeight-5;
    36.                         _text.autoSize = TextFieldAutoSize.CENTER;
    37.                         _textFormat = new TextFormat();
    38.                         _textFormat.size = 25;
    39.                         _textFormat.color = 0;//0x228b22;
    40.                         _text.setTextFormat(_textFormat);
    41.                         addChild(_text);
    42.                         this.graphics.beginFill(_Color,.9);
    43.                         this.graphics.drawRoundRect(0,0,_szWide,_szHeight,5,5);
    44.                         this.graphics.endFill();
    45.                         this.addEventListener(MouseEvent.ROLL_OVER,onMouseOver);
    46.                         this.addEventListener(MouseEvent.ROLL_OUT,onMouseOut);
    47.                 }
    48.                 private function onMouseOut(ev:MouseEvent):void{
    49.                         this.graphics.clear();
    50.                         this.graphics.beginFill(_Color,.9);
    51.                         this.graphics.drawRoundRect(0,0,_szWide,_szHeight,5,5);
    52.                         this.graphics.endFill();
    53.                 }
    54.                 private function onMouseOver(ev:MouseEvent):void{
    55.                         this.graphics.clear();
    56.                         this.graphics.beginFill(0xeedd82,.9);
    57.                         this.graphics.drawRoundRect(1,1,_szWide-1,_szHeight-1,5,5);
    58.                         this.graphics.endFill();
    59.                 }
    60.         }
    61. }
    复制代码

    使用方式:
    A.新建任意项目 运行上述类
    B.拖动ANE的res下的layout下的XML到这个类中
    C.点击按钮
    D.正则中只转换中文,一般text中英文比较少 但是也有,一般都不多的。
    遇到报错出来的是英文 就手动改就好了 或者你完善一下我的类。反正上面这个类 对于我已经够用了 很多平台的资源布局文件都是只改几个。



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52903
    钢镚
    1422

    开源英雄守望者

    5#
     楼主| 发表于 2014-12-30 22:50:28 | 只看该作者
    [AIR接入Android 平台]处理res资源之找不到资源ID

    一点声明:我的水平有限 这里仅仅只能写出我认为可行的方案 和 代码

    打包ANE会经常遇到找不到资源R.XXX ID的问题,或者是找到的资源ID不对

    然后报NULL POINT错 直接程序崩溃。

    AIR与android原生取资源方式的区别
    ADOBE给出的取资源的方式是:

    1. _context.getResourceId("id.AlipayTitleItemName");
    复制代码

    但是原生JAVA取资源的方式是:

    1. findViewById(R.id.AlipayTitleItemName);
    复制代码

    ADOBE的取资源方式 是我们在ANE中使用到资源的时候的取法,
    但是一般运营商提供的SDK都是混淆的jar 取资源的方式都是清一色的findViewById。
    而我们不可能去修改SDK 的jar。除非你的逆向能力到一定水平。

    其实修改SDK的jar也不是不可能的。对于android逆向有兴趣的同学 可以去试试。

    其实android逆向也是一门非常好玩的技术。如果你有兴趣 我们可以一起探讨。


    ANE打包资源后生成的R.java特点

    前面的文章说了 ANE打包资源是通过把资源文件夹res放到 Android-ARM下。然后打包的时候就可以在ANE内部生成R.java了。我们反编译一个APK看看AIR生成的R.java有什么特点:



    默认是生成R.java处在 包名为APK的ID下。也就是air+(你程序的-app.xml的ID)。例如(air.xxx.xxx.R)
    而我们的SDK取ID都是 R.id.AlipayTitleItemName 也就是说取的是SDK的同级包下的R.java。

    这就会导致取不到资源ID:



    也就是说 导致取不到ID的原因之一 有可能是(之所以说有可能 是因为取不到资源ID还有其他各种的原因,起码我遇遇到过的是如此):

    真正的资源ID 所在的类[air.xxx.xxx.xx.R.java]  与SDK资源ID的包名[wxd.view.R.java]地址不同

    现在知道问题所在了。那解决这个问题仔细一想就能知道如下几种方法:

    A. 最简单的方式。说服运营商 把SDK的取资源的包改为我们AIR生成资源的包,但是这也是最异想天开的方法。永远别梦想着运营商会针对你一家修改它的SDK。虽然想法美好 但是却是痴心妄想。


    B.在ANE源码中新建一个包例如上面举例的情况是 在src下新建 包 [wxd.view] 在这个包下新建类R.java。然后把运营商提供的JAVADEMO的gen文件夹下的R.java复制过去  如图:



    C.也是目前我发现最完美的解决方式:灵活使用context.getResourceId 取AIR生成的R.java下的ID 取填补 SDK下的R.java的资源ID。

    如图:



    例如上图的例子中。加一个resHandle.java类。

    1. package com.xxx.ane;

    2. import android.util.Log;

    3. import com.adobe.fre.FREContext;

    4. /**
    5. * R.java ID处理
    6. * @author Rect
    7. * @version  Time:2013-5-14
    8. */
    9. public class ResHandle {
    10.     public static void setResourctID(FREContext _context,String TAG)
    11.     {
    12.         if(wxd.view.R.array.address == _context.getResourceId("array.address") &&
    13.                 wxd.view.R.anim.elseway == _context.getResourceId("anim.elseway"))
    14.             return;
    15.         
    16.         Log.d(TAG, "---------anim-------"+_context.getResourceId("anim.elseway"));
    17.         wxd.view.R.anim.elseway = _context.getResourceId("anim.elseway");
    18.         wxd.view.R.anim.elseway_in = _context.getResourceId("anim.elseway_in");
    19.         wxd.view.R.anim.landscape_anim = _context.getResourceId("anim.landscape_anim");
    20.         wxd.view.R.anim.portrait_anim = _context.getResourceId("anim.portrait_anim");
    21.         wxd.view.R.anim.zoom_enter = _context.getResourceId("anim.zoom_enter");
    22.         wxd.view.R.anim.zoom_exit = _context.getResourceId("anim.zoom_exit");
    23.         wxd.view.R.anim.zoomin = _context.getResourceId("anim.zoomin");
    24.         wxd.view.R.anim.zoomout = _context.getResourceId("anim.zoomout");
    25.          }
    复制代码

    当然 在SDK包下的R.java要做一些处理 使得能访问全部静态变量 例如我的
    wxd.view.R.java 如下:


    1. package wxd.view;


    2. public  class R
    3. {
    4.   public static class anim
    5.   {
    6.     public static  int elseway = 2130968576;
    7.     public static  int elseway_in = 2130968577;
    8.     public static  int landscape_anim = 2130968578;
    9.     public static  int portrait_anim = 2130968579;
    10.     public static  int zoom_enter = 2130968580;
    11.     public static  int zoom_exit = 2130968581;
    12.     public static  int zoomin = 2130968582;
    13.     public static  int zoomout = 2130968583;
    14.   }
    复制代码

    这样外部就能访问 各个变量了。
    然后在 调用SDK打开SDK界面之前 调用这句对R.java进行处理:

    1. Log.d(TAG, "---------R.java处理-------");
    2.         ResHandle.setResourctID(_context, TAG);
    3.         Log.d(TAG, "---------Login开始-------");
    复制代码

    至此 由于取不到资源ID的问题 就得到了解决。当然再强调一次 取不到资源ID 也有可能是由于其他问题导致的。这仅仅是导致这个问题的原因之一。



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52903
    钢镚
    1422

    开源英雄守望者

    6#
     楼主| 发表于 2014-12-30 22:51:25 | 只看该作者
    命令行打包ANE
    一点说明:打包ANE有很多方式。我的方式比较普遍  把步骤分得太细。最初的时候也是为了了解全过程。其实zrong打包ANE的方式才是王道。举个例子 我打包飞流ANE的命令:

    "D:\FB\Adobe Flash Builder 4.6\sdks\AIR3.5\bin\adt" -package -storetype PKCS12 -keystore qlwx.p12 -storepass 1234 -target ane com.feiliu.ane extension.xml -swc *.swc -platform Android-ARM -C Android-ARM .


    说明:
    "D:\FB\Adobe Flash Builder 4.6\sdks\AIR3.5\bin\adt"   本机ADT路径
    qlwx.p12   证书文件
    1234   证书密码
    com.feiliu.ane 生成的ANE文件名字
    extension.xml  对接XML


    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52903
    钢镚
    1422

    开源英雄守望者

    7#
     楼主| 发表于 2014-12-30 22:51:46 | 只看该作者
    打包APK命令解释

    一点说明:同样我打包的方式步骤分得太细。打包APK用命令行 因为很多平台都会要求打APK进入我们的AIR APK中
    举个例子小米平台的打包APK命令:
    "D:\FB\Adobe Flash Builder 4.6\sdks\AIR3.5\bin\adt"  -package -target apk-captive-runtime -storetype pkcs12 -keystore a.p12 -storepass 1234 xiaomi.apk logInTest-app.xml logInTest.swf  MiGameCenterSDKService.apk assets -extdir .


    说明:

    "D:\FB\Adobe Flash Builder 4.6\sdks\AIR3.5\bin\adt"  你的本机ADT命令
    “a.p12”   证书文件
    “1234” 证书密码
    “xiaomi.apk” 要生成的最终APK名字
    “logInTest-app.xml ” AIR项目XML
    “logInTest.swf ”AIR项目SWF
    “MiGameCenterSDKService.apk” 打进APK去的APK
    “assets” 打进APK去的资源文件

    有朋友问这里的SWF XML怎么来的。
    下面说一种最简单的方式:
    右键属性 - 导出 -发行版 - 下一步 - 下一步 (这里步骤不一定准确,但是记住 在FB打包APK前停止操作)
    然后停止操作。去项目文件下找bin-release-temp文件夹,此文件夹下会有编译的SWF文件 和 xml文件。


    还有更好的方式:

    A.ADT打包,上手比较快。把项目的编译 打包分开。由于FB大项目编译打包老是卡死 我已经对FB打包深恶痛绝了。目前完全抛弃了用FB来打包 全部用命令行。


    B.ANT打包,上手比较慢一点,但是ANT打包非常强大啊。强大到可以做你想做的任何东西,例如排除jar中的.class文件 例如导入各种lib文件 例如生成jar 例如编译swf 例如 。。。
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52903
    钢镚
    1422

    开源英雄守望者

    8#
     楼主| 发表于 2014-12-30 22:53:54 | 只看该作者
    这篇教程是我在ANE中自己新建一个activity来调用SDK的。你看看能不能帮到你。或者你可以把你的情况描述得更清晰点
    http://www.shadowkong.com/archives/1062

    https://github.com/platformanes/android360   必须的有。不过涉及官方SDK的文档 源码库 等我已经去掉了 只保留ANE源码  保留打包命令  但是ANE可以直接拿来用。
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52903
    钢镚
    1422

    开源英雄守望者

    9#
     楼主| 发表于 2014-12-30 22:54:03 | 只看该作者
    您好,想请教一个问题:我最近做MM android接入的时候,发现MM的接入jar包中有一部分资源在jar下(不在res ...






    先打包APK 然后解压 再把资源放入  这种方式很不稳定的。你失败了是因为签名问题吧;对于资源的处理有两种方式:
    1.res文件下的布局文件 图片 等打包进去ANE
    2.assets 文件夹下的 图片等  复制到 AIR项目的src文件夹下 打进APK

    更详细的请看:http://www.shadowkong.com/archives/1042
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2026-1-25 03:12 , Processed in 0.064163 second(s), 33 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表