实例详细步骤:
1. 安装FMS 4.5,启动FMS 服务,安装目录applications下创建文件夹HelloFms
比如:D:\Program Files\Adobe\Flash Media Server 4.5\applications\HelloFms
2.HelloFms目录下创建main.asc,编写FMS服务器端脚本,保存成utf-8编码
main.asc脚本如下:
// 有客户连接 application.onConnect = function(client) { // 接受连接 application.acceptConnection(client); // 输出一个信息,这个信息可以在fms的admin工具里看到 trace("HelloFMS接受连接"); } //客户断开时 application.onDisconnect = function(client) { trace( "客户已断开"); } //客户发布流时 application.onPublish = function(client, myStream) { trace(myStream.name + "开始发布" + application.name); } //取消发布时 application.onUnpublish = function( client, myStream ) { trace(myStream.name + " 停止发布" ); } Client.prototype.serverHelloMsg = function(helloStr){ trace(helloStr); return "Hello, " + helloStr + "!"; }
3.启动FlashBuilder 4.6,创建Flex手机工程,工程名称HelloFms,目标平台Google Android,注意CAMERA和RECORD_AUDIO权限配置
HelloFms-app.xml如下:
<?xml version="1.0" encoding="utf-8" standalone="no"?> <application xmlns="http://ns.adobe.com/air/application/3.1"> <!-- Adobe AIR Application Descriptor File Template. Specifies parameters for identifying, installing, and launching AIR applications. xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/3.1 The last segment of the namespace specifies the version of the AIR runtime required for this application to run. minimumPatchLevel - The minimum patch level of the AIR runtime required to run the application. Optional. --> <!-- A universally unique application identifier. Must be unique across all AIR applications. Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. --> <id>HelloFms</id> <!-- Used as the filename for the application. Required. --> <filename>HelloFms</filename> <!-- The name that is displayed in the AIR application installer. May have multiple values for each language. See samples or xsd schema file. Optional. --> <name>HelloFms</name> <!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade. Values can also be 1-part or 2-part. It is not necessary to have a 3-part value. An updated version of application must have a versionNumber value higher than the previous version. Required for namespace >= 2.5 . --> <versionNumber>0.0.0</versionNumber> <!-- A string value (such as "v1", "2.5", or "Alpha 1") that represents the version of the application, as it should be shown to users. Optional. --> <!-- <versionLabel></versionLabel> --> <!-- Description, displayed in the AIR application installer. May have multiple values for each language. See samples or xsd schema file. Optional. --> <!-- <description></description> --> <!-- Copyright information. Optional --> <!-- <copyright></copyright> --> <!-- Publisher ID. Used if you're updating an application created prior to 1.5.3 --> <!-- <publisherID></publisherID> --> <!-- Settings for the application's initial window. Required. --> <initialWindow> <!-- The main SWF or HTML file of the application. Required. --> <!-- Note: In Flash Builder, the SWF reference is set automatically. --> <content>[此值将由 Flash Builder 在输出 app.xml 中覆盖]</content> <!-- The title of the main window. Optional. --> <!-- <title></title> --> <!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. --> <!-- <systemChrome></systemChrome> --> <!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. --> <!-- <transparent></transparent> --> <!-- Whether the window is initially visible. Optional. Default false. --> <!-- <visible></visible> --> <!-- Whether the user can minimize the window. Optional. Default true. --> <!-- <minimizable></minimizable> --> <!-- Whether the user can maximize the window. Optional. Default true. --> <!-- <maximizable></maximizable> --> <!-- Whether the user can resize the window. Optional. Default true. --> <!-- <resizable></resizable> --> <!-- The window's initial width in pixels. Optional. --> <!-- <width></width> --> <!-- The window's initial height in pixels. Optional. --> <!-- <height></height> --> <!-- The window's initial x position. Optional. --> <!-- <x></x> --> <!-- The window's initial y position. Optional. --> <!-- <y></y> --> <!-- The window's minimum size, specified as a width/height pair in pixels, such as "400 200". Optional. --> <!-- <minSize></minSize> --> <!-- The window's initial maximum size, specified as a width/height pair in pixels, such as "1600 1200". Optional. --> <!-- <maxSize></maxSize> --> <!-- The initial aspect ratio of the app when launched (either "portrait" or "landscape"). Optional. Mobile only. Default is the natural orientation of the device --> <!-- <aspectRatio></aspectRatio> --> <!-- Whether the app will begin auto-orienting on launch. Optional. Mobile only. Default false --> <!-- <autoOrients></autoOrients> --> <!-- Whether the app launches in full screen. Optional. Mobile only. Default false --> <!-- <fullScreen></fullScreen> --> <!-- The render mode for the app (either auto, cpu, gpu, or direct). Optional. Default auto --> <!-- <renderMode></renderMode> --> <!-- Whether or not to pan when a soft keyboard is raised or lowered (either "pan" or "none"). Optional. Defaults "pan." --> <!-- <softKeyboardBehavior></softKeyboardBehavior> --> <autoOrients>true</autoOrients> <fullScreen>false</fullScreen> <visible>true</visible> <softKeyboardBehavior>none</softKeyboardBehavior> </initialWindow> <!-- We recommend omitting the supportedProfiles element, --> <!-- which in turn permits your application to be deployed to all --> <!-- devices supported by AIR. If you wish to restrict deployment --> <!-- (i.e., to only mobile devices) then add this element and list --> <!-- only the profiles which your application does support. --> <!-- <supportedProfiles>desktop extendedDesktop mobileDevice extendedMobileDevice</supportedProfiles> --> <!-- The subpath of the standard default installation location to use. Optional. --> <!-- <installFolder></installFolder> --> <!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. --> <!-- <programMenuFolder></programMenuFolder> --> <!-- The icon the system uses for the application. For at least one resolution, specify the path to a PNG file included in the AIR package. Optional. --> <!-- <icon> <image16x16></image16x16> <image32x32></image32x32> <image36x36></image36x36> <image48x48></image48x48> <image57x57></image57x57> <image72x72></image72x72> <image114x114></image114x114> <image128x128></image128x128> </icon> --> <!-- Whether the application handles the update when a user double-clicks an update version of the AIR file (true), or the default AIR application installer handles the update (false). Optional. Default false. --> <!-- <customUpdateUI></customUpdateUI> --> <!-- Whether the application can be launched when the user clicks a link in a web browser. Optional. Default false. --> <!-- <allowBrowserInvocation></allowBrowserInvocation> --> <!-- Listing of file types for which the application can register. Optional. --> <!-- <fileTypes> --> <!-- Defines one file type. Optional. --> <!-- <fileType> --> <!-- The name that the system displays for the registered file type. Required. --> <!-- <name></name> --> <!-- The extension to register. Required. --> <!-- <extension></extension> --> <!-- The description of the file type. Optional. --> <!-- <description></description> --> <!-- The MIME content type. --> <!-- <contentType></contentType> --> <!-- The icon to display for the file type. Optional. --> <!-- <icon> <image16x16></image16x16> <image32x32></image32x32> <image48x48></image48x48> <image128x128></image128x128> </icon> --> <!-- </fileType> --> <!-- </fileTypes> --> <!-- iOS specific capabilities --> <!-- <iPhone> --> <!-- A list of plist key/value pairs to be added to the application Info.plist --> <!-- <InfoAdditions> <![CDATA[ <key>UIDeviceFamily</key> <array> <string>1</string> <string>2</string> </array> <key>UIStatusBarStyle</key> <string>UIStatusBarStyleBlackOpaque</string> <key>UIRequiresPersistentWiFi</key> <string>YES</string> ]]> </InfoAdditions> --> <!-- A list of plist key/value pairs to be added to the application Entitlements.plist --> <!-- <Entitlements> <![CDATA[ <key>keychain-access-groups</key> <array> <string></string> <string></string> </array> ]]> </Entitlements> --> <!-- Display Resolution for the app (either "standard" or "high"). Optional. Default "standard" --> <!-- <requestedDisplayResolution></requestedDisplayResolution> --> <!-- </iPhone> --> <!-- Specify Android specific tags that get passed to AndroidManifest.xml file. --> <!--<android> --> <!-- <manifestAdditions> <![CDATA[ <manifest android:installLocation="auto"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-feature android:required="true" android:name="android.hardware.touchscreen.multitouch"/> <application android:enabled="true"> <activity android:excludeFromRecents="false"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest> ]]> </manifestAdditions> --> <!-- Color depth for the app (either "32bit" or "16bit"). Optional. Default 16bit before namespace 3.0, 32bit after --> <!-- <colorDepth></colorDepth> --> <!-- </android> --> <!-- End of the schema for adding the android specific tags in AndroidManifest.xml file --> <android> <colorDepth>16bit</colorDepth> <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> <iPhone> <InfoAdditions><![CDATA[ <key>UIDeviceFamily</key> <array> <string>1</string> <string>2</string> </array> ]]></InfoAdditions> <requestedDisplayResolution>high</requestedDisplayResolution> </iPhone> </application>
4.HelloFmsView.mxml 源代码如下:
<?xml version="1.0" encoding="utf-8"?> <s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" actionBarVisible="false" creationComplete="creationCompleteHandler(event)"> <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <fx:Script> <![CDATA[ import mx.events.FlexEvent; private var cam:Camera = Camera.getCamera(); //获取视频源设备 private var mic:Microphone = Microphone.getMicrophone();//获取声源设备 private var video:Video=new Video(320,240); private var nc:NetConnection=new NetConnection(); private var nsOut:NetStream; //用于发布流 private var nsIn:NetStream; //用于接收流 private function initConn (e:NetStatusEvent):void { trace(e.info.code); switch (e.info.code) { case "NetConnection.Connect.Closed" : break; case "NetConnection.Connect.Failed" : break; case "NetConnection.Connect.Success" : var h264Settings:H264VideoStreamSettings = new H264VideoStreamSettings(); h264Settings.setProfileLevel(H264Profile.MAIN, H264Level.LEVEL_5_1); h264Settings.setMode(320, 240, 15); h264Settings.setQuality(0, 85); nsOut=new NetStream(nc); nsOut.attachAudio (mic); nsOut.attachCamera (cam); nsOut.videoStreamSettings = h264Settings; nsOut.publish("hello","live");//发布流。其中iLive为流的名称,监听者通过该名称来播放此流。live意为实时发布。 nsIn=new NetStream(nc); nsIn.play("hello");//播放节目名称 video.attachNetStream(nsIn);//视频组件加载输入流 this.stage.addChild(video);//将视频组件加载到舞台上显示。 var resp:Responder = new Responder(onSuccess,onFailed); nc.call("serverHelloMsg", resp, "Hello FMS!");//调用服务端的serverHelloMsg的方法 break; case "NetConnection.Connect.Rejected" : break; case "NetConnection.Connect.InvalidApp": break; case "NetConnection.Connect.AppShutDown": break; default : break; } } private function onSuccess(result:Object):void { trace("服务端返回内容:" + result.toString()); } private function onFailed(result:Object):void { trace(result.description); trace(result.code); } protected function creationCompleteHandler(event:FlexEvent):void { // TODO Auto-generated method stub nc.addEventListener (NetStatusEvent.NET_STATUS,initConn); nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onAsyncErrorHandler); nc.connect("rtmp://127.0.0.1/HelloFms"); nc.client = this; } private function onAsyncErrorHandler(evt:AsyncErrorEvent):void{} private function onBWDone(rs:Object):void {} ]]> </fx:Script> </s:View>
5.配置成模拟器运行,如果电脑正常连接摄像头,则Android手机模拟器上可以看到摄像头抓取的图像。本人测试通过。
控制台运行结果:
[SWF] HelloFms.swf - 解压缩后为 2,772,803 个字节 NetConnection.Connect.Success 服务端返回内容:Hello, Hello FMS!! [卸装 SWF] HelloFms.swf
6.注意不要将FMS的live例子中的main.far文件拷贝到HelloFms目录内,否则会报错:NetConnection.Call.Failed,描述信息是Method not found (serverHelloMsg).
如果还是仍然报错,试试重启FMS服务来解决这个问题。