Mobile Flex 调用摄像头
利用flash air技术可跨平台实现摄像头调用功能,并且实现了拍照并保存照片。(基于flex4.6开发)
Mxml文件代码如下:
<?xml version="1.0" encoding="GBK"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" applicationDPI="240" width="480" height="800" >
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.yapiodesign.components.android.alert.AlertDialog;
import flash.events.*;
import flash.media.CameraUI;
import flash.media.MediaType;
import mx.formatters.DateFormatter;
import mx.graphics.codec.JPEGEncoder;
private var imgBD:BitmapData = null;
private var alert:AlertDialog;
private function ini():void{
SavePic.enabled = false;
if(CameraUI.isSupported==false){
trace("您似乎没有安装摄像头!");
alert = new AlertDialog();
alert.title = "提示";
alert.message = "您似乎没有安装摄像头!!";
alert.open(this, true);
}else{
var cameraUI:CameraUI = new CameraUI();
cameraUI.launch(MediaType.IMAGE);
cameraUI.addEventListener(MediaEvent.COMPLETE,onComplete);
cameraUI.addEventListener(Event.CANCEL,onCancel);
cameraUI.addEventListener(ErrorEvent.ERROR,onError);
}
}
private var bitmapData:BitmapData;
private var fileSource:IEventDispatcher;
private var fileDataSource:IDataInput;
private var fileData:ByteArray;
private function onComplete(event:MediaEvent):void{
var promise:MediaPromise = event.data as MediaPromise;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
loader.loadFilePromise(promise);
//如果我不想显示,只是想得到该图片的二进制数据,就象打开一个File一样.用下面的方法.如果不用这个,请把下面的代码注释掉.不然会造成不能显示图片
//--------------Start
fileDataSource = promise.open();
if(promise.isAsync){
fileSource = fileDataSource as IEventDispatcher;
fileSource.addEventListener(Event.COMPLETE,dataCompleteHandler);
}else{
readFileData();
}
//---------------end
}
private function dataCompleteHandler(event:Event):void{
fileData = new ByteArray();
fileDataSource.readBytes(fileData);
}
//读取二进制数据
private function readFileData():void{
fileData = new ByteArray();
fileDataSource.readBytes(fileData);
//sendDataToServer(fileData);
}
private function onCancel(event:MediaEvent):void{
trace("您取消了本次拍照!");
alert = new AlertDialog();
alert.title = "提示";
alert.message = "您取消了本次拍照!";
alert.open(this, true);
}
/*
private function onImageLoaded(event:Event):void{
bitmapData = Bitmap(event.currentTarget.content).bitmapData;
var bitmap:Bitmap = new Bitmap(bitmapData);
// determine the image orientation
var isPortrait:Boolean = (bitmapData.height/bitmapData.width) > 1.0;
// choose smallest value between stage width and height
var forRatio:int = Math.min(stage.stageHeight, stage.stageWidth);
// calculate the scaling ratio to apply to the image
var ratio:Number;
if (isPortrait){
ratio = forRatio/bitmapData.width;
}else{
ratio = forRatio/bitmapData.height;
}
bitmap.width = bitmapData.width * ratio;
bitmap.height = bitmapData.height * ratio;
if (!isPortrait){
bitmap.y = bitmap.width;
bitmap.rotation = -90;
}
addChild(bitmap);
Img.source = bitmap;
SavePic.enabled = true;
}
*/
private function onImageLoaded(e:Event):void{
var mediaLoaderInfo:LoaderInfo = e.target as LoaderInfo;
mediaLoaderInfo.removeEventListener(Event.COMPLETE, onImageLoaded);
mediaLoaderInfo.loader.removeEventListener(IOErrorEvent.IO_ERROR, onError);
this.Img.source = mediaLoaderInfo.loader;
bitmapData = this.Img.bitmapData;
SavePic.enabled = true;
}
private function onError(event:Event):void{
trace("图像加载错误: " + event.toString(),"");
alert = new AlertDialog();
alert.title = "提示";
alert.message = "图像加载错误!";
alert.open(this, true);
}
private function save_pic():void{
//if(bitmapData){
//var jpg:JPEGEncoder = new JPEGEncoder();
//var byt:ByteArray = jpg.encode(bitmapData);
var dateFormatter:DateFormatter = new DateFormatter();
dateFormatter.formatString = "YYYYMMDDJJNNSS";
var now:String = dateFormatter.format(new Date());
var fl:File = new File(File.desktopDirectory.resolvePath(now+'.jpg').nativePath);
var fs:FileStream = new FileStream();
try{
//open file in write mode
fs.open(fl,FileMode.WRITE);
//write bytes from the byte array
//fs.writeBytes(byt);
fs.writeBytes(fileData);
//close the file
fs.close();
trace("成功保存图片到本地!" + File.desktopDirectory.resolvePath(now+'.jpg').nativePath);
alert = new AlertDialog();
alert.title = "提示";
alert.message = "成功保存图片到本地!\r\n" + File.desktopDirectory.resolvePath(now+'.jpg').nativePath;
alert.open(this, true);
} catch (e:Error){
trace(e.message);
}
//}
}
private function downloadComplete(event:Event):void{
trace("成功保存图片到本地!");
}
private function Close():void{
NativeApplication.nativeApplication.exit();
}
]]>
</fx:Script>
<s:Button x="43" y="585" label="照相" width="168" height="55" click="ini()" fontSize="24"/>
<s:Button x="256" y="585" id="SavePic" label="保存照片" width="160" height="55" click="save_pic()" fontSize="24" />
<s:Image id="Img" x="43" y="30" width="371" height="494" scaleMode="stretch" smooth="true"
smoothingQuality="high">
<s:source>
<s:MultiDPIBitmapSource source240dpi="@Embed('../bin-debug/dd.jpg')"/>
</s:source>
</s:Image>
<s:Button x="145" y="678" width="157" label="退出" click="Close()"/>
</s:Application>
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>Camera</id>
<!-- Used as the filename for the application. Required. -->
<filename>Camera</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>Camera</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>false</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>icons/114.png</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>