• Android实例-实现扫描二维码并生成二维码(XE8+小米5)


    相关资料

    第三方资料太大没法写在博文上,请下载CSDN的程序包。

    程序包下载:

    http://download.csdn.net/detail/zhujianqiangqq/9657186

    注意事项:

    如果只加了Lib,然没有改AndroidManifest.xml,App在呼叫BarCode时会ANR没反应。
    开始可能没有官方的classes.dex,但如果发现编译出错后,请再检查一下。
    TMessageManager须加System.Messaging单元。

    使用DelphiXE7加入JavaLibrary后,呼叫Zxing相机
    1.新建一个DelphiXE工程,双击"Android-Android ADK 25.1.7.32bit"。

    2.依照Zxing会用到的Android权限,在 project->options->uses permission 加上权限。
    Access wifi state//访问WIFI状态
    Camera//相机
    Change wifi state//更改WIFI状态
    Flashlight//手电筒
    Internet//互联网
    Read contacts//读联系人
    Read history bookmarks//读历史书签
    Vibrate//颤动
    Write extrnal storage//写外置储存

    3.把解好的Jar档案放到项目目录下
    如:"CreateActivity.jar"放到"C:Userszhujq-aDesktopAndroid实例之实现扫描二维码并生成二维码"目录下。

    4.引入Jar包。
    在"Project1"->"Android-Android SDK 25.1.7.32bit"->Libraries->右击->"Add"->选中"C:Userszhujq-aDesktopAndroid实例之实现扫描二维码并生成二维码CreateActivity.jar"->打开。

    5.在"Project1"->"Compile"编译一次,产生 AndroidManifest.template.xml ,但不要Run手机的App。

    6.修改AndroidManifest.template.xml,加入CaptureActivity的区段。
    位置在"<activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"下面。
    代码如下:
    <activity android:name="com.google.zxing.client.android.CaptureActivity"
              android:screenOrientation="portrait"
              android:clearTaskOnLaunch="true"
              android:stateNotNeeded="true"
              android:configChanges="orientation|keyboardHidden"
              android:theme="@style/CaptureTheme"
              android:windowSoftInputMode="stateAlwaysHidden">
    </activity>

    7.这个时候编译会出现下面错误讯息,表示找不到Android的资源。
    [PAClient Error] Error: E2312 C:Userszhujq-aDesktopAndroid实例之实现扫描二维码并生成二维码AndroidDebugProject1AndroidManifest.xml:53: error: Error: No resource found that matches the given name (at 'theme' with value

    '@style/CaptureTheme').

    8.接下来要合并 Android 和 Embarcadero 的数据文件
    1>.把 Android 的资源复制到项目目录
    PS:这个地方说明一下:注意是编译后的CaptureActivity es文件夹(这里说的JAVA中的,但不是DLEPHI中的)
    把"CaptureActivity es"中的文件复制到"C:Userszhujq-aDesktopAndroid实例之实现扫描二维码并生成二维码"中。
    2>.打包这些资源文件
    Project->Deployment->把drawable, layout, menu, raw, values 和 xml 目录下的所有档案加入->修改"Remote Path"为"Local Path"(如:"resdrawable"的"Remote Path"为"."改为"resdrawable")。

    9.接下来因为Zxing和 Embarcadero 都有相同的档案 resvaluesstyles.xml,所以要取消其中一个,并手工把两个档案的内容合并。
    1>.取消官方的Styles.xml
    Project->Deployment->Styles.xml去掉对号。
    2>.取消官方的classes.dex(20161018亲测,去掉闪退,不去掉正好)
    Project->Deployment->classes.dex去掉对号。
    PS:这个地方说明一下:开始可能没有官方的classes.dex,但如果发现编译出错后,请再检查一下。
    3>.把 (项目目录)AndroidDebugstyles.xml 和 (项目目录) esvaluesstyles.xml 内容合并后如下
    打开notepad,打开文件"C:Userszhujq-aDesktopAndroid实例之实现扫描二维码并生成二维码AndroidDebugstyles.xml",复制如下内容:

    <style name="AppTheme" parent="@android:style/Theme.NoTitleBar">

    <item name="android:windowBackground">@drawable/splash_image_def</item>

    <item name="android:windowNoTitle">true</item>

    </style>
    打开notepad,打开文件"C:Userszhujq-aDesktopAndroid实例之实现扫描二维码并生成二维码 esvaluesstyles.xml",粘入复制的内容。位置是在 "<style>"的最后面。
    合并结束后,将"C:Userszhujq-aDesktopAndroid实例之实现扫描二维码并生成二维码 esvaluesstyles.xml"整个文件复制到"C:Userszhujq-aDesktopAndroid实例之实现扫描二维码并生成二维码AndroidDebug"中。

    10.增加工程代码(看博文)


    生成二维码功能
    1.将"xZXIngQRCode.pas"文件放入"C:Userszhujq-aDesktopAndroid实例之实现扫描二维码并生成二维码"工程代码目录下面。
    2.在文件管理器中,选中"project1"->Add->选中xZXIngQRCode.pas->打开。
    3.工程单元中引入"xZXIngQRCode"单元。
    4.窗体中写入生成二维码的代码(看博文)。


    关于横竖屏的问题
    但是android提供的SDK(android.hardware.Camera)里大概不能正常的使用竖屏(portrait layout)加载照相机,当用竖屏模式加载照相机时会产生以下情况:1. 照相机成像左倾90度(倾斜);2. 照相机成像长宽比例不对(失比)。
    基本上解决办法如下:
    1、在AndroidManifest.xml里面配置一下 ,使CaptureActivity属性为portrait:   android:screenOrientation="portrait"
    2、如果只是单纯的想改变照相机成像的方向,只需要在包com.google.zxing.client.android.camera下的   CameraConfigurationManager类中增加方法
       protected void setDisplayOrientation(Camera camera, int angle) {
            Method downPolymorphic;
            try {
             downPolymorphic = camera.getClass().getMethod(
               "setDisplayOrientation", new Class[] { int.class });
             if (downPolymorphic != null)
              downPolymorphic.invoke(camera, new Object[] { angle });
            } catch (Exception e1) {
            }
           }
       然后在方法void setDesiredCameraParameters(Camera camera){}中调用,
       setDisplayOrientation(camera, 90);
       具体位置在camera.setParameters(parameters);语句前面。

    2014-10-15
    楼主上面增加过程的方法在我的(ZXing2.3)CameraConfigurationManager中出错。
    实际只需setDisplayOrientation(camera, 90);修改成camera.setDisplayOrientation(90);

     3、改变完方向你会发现方向改变了可是分辨率会变得很低,接下来就是优化了
      (1)首先在类CameraManager.java中
       把 rect.left = rect.left * cameraResolution.x / screenResolution.x;
          rect.right = rect.right * cameraResolution.x / screenResolution.x;
          rect.top = rect.top * cameraResolution.y / screenResolution.y;
          rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
       替换成
          rect.left = rect.left * cameraResolution.y / screenResolution.x;
          rect.right = rect.right * cameraResolution.y / screenResolution.x;
          rect.top = rect.top * cameraResolution.x / screenResolution.y;
          rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
       (2)然后是在DecodeHandler类中的方法private void decode(byte[] data,int width,int height){}
       中添加byte[] rotatedData = new byte[data.length];
     for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++)
       rotatedData[x * height + height - y - 1] = data[x + y * width];
       *具体内容可见附件
      (3)再就是CameraConfigurationManager类中的方法void initFromCameraParameters(Camera camera){}中添加如下代码:

    Point screenResolutionForCamera = new Point();
        screenResolutionForCamera.x = screenResolution.x;
        screenResolutionForCamera.y = screenResolution.y;
        // preview size is always something like 480*320, other 320*480
     if (screenResolution.x < screenResolution.y) {
      screenResolutionForCamera.x = screenResolution.y;
      screenResolutionForCamera.y = screenResolution.x;
    注: 到这就完成了。如果还有问题,只需下载附件直接替换相应文件即可;    (直接替换很可能不行)
    还有一个最后存在的问题,在 下编译扫描窗口正常(竖屏),但打包后在DELPHI XE7下,扫描时提示是英文(标题是中文),不知为何?
    以上修改之处,是本人环境下完成。
    感谢[台北]Q面(2609815930)、[龟山]阿卍(1467948783) 、[北京]老猫(1765535979),还有许多不知名的作者。

    实例代码: 

      1 unit Unit1;
      2 
      3 interface
      4 
      5 uses
      6   System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      7   FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
      8   FMX.Edit, FMX.Controls.Presentation,
      9   System.Messaging,//需要引入
     10   System.Rtti,//需要引入
     11   System.Actions,//需要引入
     12   Androidapi.JNI.Net,//需要引入
     13   Androidapi.JNI.GraphicsContentViewText,//需要引入
     14   Androidapi.JNI.JavaTypes,//需要引入
     15   Androidapi.Helpers,//需要引入
     16   Androidapi.JNI.App,//需要引入
     17   FMX.Objects,//需要引入
     18   FMX.ActnList,//需要引入
     19   FMX.StdActns,//需要引入
     20   FMX.Platform.Android,//需要引入
     21   FMX.MediaLibrary.Actions,//需要引入
     22   xZXIngQRCode;//需要引入
     23 
     24 type
     25   TForm1 = class(TForm)
     26     Button1: TButton;
     27     Button2: TButton;
     28     Edit1: TEdit;
     29     Edit2: TEdit;
     30     Label1: TLabel;
     31     Label2: TLabel;
     32     Label3: TLabel;
     33     Image1: TImage;
     34     Panel1: TPanel;
     35     Label4: TLabel;
     36     Edit3: TEdit;
     37     Label5: TLabel;
     38     procedure Button1Click(Sender: TObject);
     39     procedure FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
     40       Shift: TShiftState);
     41     procedure Button2Click(Sender: TObject);
     42   private
     43     { Private declarations }
     44     //扫描请求代码
     45     const ScanRequestCode = 0;
     46     //
     47     var FMessageSubscriptionID: Integer;
     48     //活动结果事件
     49     function OnActivityResult(RequestCode, ResultCode: Integer; Data: JIntent): Boolean;
     50     //活动消息处理
     51     procedure HandleActivityMessage(const Sender: TObject; const M: TMessage);
     52   public
     53     { Public declarations }
     54      //扫描状态
     55      ScanState: Boolean;//TRUE代表扫描中,FALSE扫描结束
     56   end;
     57 
     58 var
     59   Form1: TForm1;
     60 
     61 implementation
     62 
     63 {$R *.fmx}
     64 {$R *.LgXhdpiPh.fmx ANDROID}
     65 
     66 //启用扫码
     67 procedure LaunchQRScanner(RequestCode: Integer);
     68 var
     69   Intent: JIntent;
     70 begin
     71   Intent := TJIntent.JavaClass.init;
     72   Intent.setClassName(SharedActivityContext, StringToJString('com.google.zxing.client.android.CaptureActivity'));
     73   //如果要预定扫描格式,UnComment 下面文字
     74   //Intent.putExtra(StringToJString('SCAN_MODE'), StringToJString('QR_CODE_MODE'));
     75   SharedActivity.startActivityForResult(Intent, RequestCode);
     76 end;
     77 
     78 //调用扫码方法
     79 procedure TForm1.Button1Click(Sender: TObject);
     80 var
     81   LIntent: JIntent;
     82 begin
     83   //LIntent := TJIntent.JavaClass.init;
     84   //LIntent.setClassName(SharedActivityContext, StringToJString('com.google.zxing.client.android.CaptureActivity'));
     85   //SharedActivity.startActivityForResult(LIntent, 0);
     86   //加载扫码
     87   FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage(TMessageResultNotification,
     88     HandleActivityMessage);
     89   //开始扫码
     90   LaunchQRScanner(ScanRequestCode);
     91   //状态定为扫码结束
     92   ScanState := False;
     93 end;
     94 
     95 procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
     96   Shift: TShiftState);
     97 begin
     98   //如果按下物理返回键,但是扫码未结束
     99   if (Key = vkHardwareBack) and (ScanState = True) then
    100   begin
    101     ScanState := False;
    102     Key := 0;
    103     Exit;
    104   end;
    105   //如果按下物理返回键,并且扫码结束
    106   if (Key = vkHardwareBack) and (ScanState = False) then
    107   begin
    108     {$IFDEF ANDROID}
    109     MessageDlg('确认退出吗?', System.UITypes.TMsgDlgType.mtInformation,
    110     [
    111       System.UITypes.TMsgDlgBtn.mbYes,
    112       //System.UITypes.TMsgDlgBtn.mbNo,
    113       System.UITypes.TMsgDlgBtn.mbCancel
    114     ], 0, System.UITypes.TMsgDlgBtn.mbCancel,
    115     procedure(const AResult: TModalResult)
    116     begin
    117       if AResult = mrYES then
    118          MainActivity.finish; { 退出程序 }   // use FMX.Platform.Android
    119       end);
    120     {$ENDIF ANDROID}
    121     //close;
    122     Key := 0;
    123     Exit;
    124   end;
    125 end;
    126 
    127 //活动消息处理
    128 procedure TForm1.HandleActivityMessage(const Sender: TObject;
    129   const M: TMessage);
    130 begin
    131   if M is TMessageResultNotification then
    132     OnActivityResult(TMessageResultNotification(M).RequestCode, TMessageResultNotification(M).ResultCode,
    133       TMessageResultNotification(M).Value);
    134 end;
    135 
    136 //活动结果事件
    137 function TForm1.OnActivityResult(RequestCode, ResultCode: Integer;
    138   Data: JIntent): Boolean;
    139 var
    140   ScanContent, ScanFormat: string;
    141 begin
    142   Result := False;
    143 
    144   TMessageManager.DefaultManager.Unsubscribe(TMessageResultNotification, FMessageSubscriptionID);
    145   FMessageSubscriptionID := 0;
    146   //判断请求代码
    147   if RequestCode = ScanRequestCode then
    148   begin
    149     //如果扫码结束
    150     if ResultCode = TJActivity.JavaClass.RESULT_OK then
    151     begin
    152       //有数据
    153       if Assigned(Data) then
    154       begin
    155         //解析出数据
    156         ScanContent := JStringToString(Data.getStringExtra(StringToJString('SCAN_RESULT')));
    157         ScanFormat := JStringToString(Data.getStringExtra(StringToJString('SCAN_RESULT_FORMAT')));
    158         Edit1.Text:= ScanContent;
    159         Edit2.Text:= ScanFormat;
    160         Label5.Text:= '扫描成功';
    161       end;
    162     end
    163     else if ResultCode = TJActivity.JavaClass.RESULT_CANCELED then
    164     begin
    165       Label5.Text:= '扫描取消';
    166     end;
    167     Result := True;
    168   end;
    169 end;
    170 
    171 //生成二维码
    172 procedure TForm1.Button2Click(Sender: TObject);
    173 var
    174   QRCode: TDelphiZXingQRCode;
    175 begin
    176   QRCode := TDelphiZXingQRCode.Create;
    177   try
    178     QRCode.Data := Edit3.Text;
    179     QRCode.Encoding := TQRCodeEncoding(0);
    180     QRCode.QuietZone := 4;
    181     QRCode.DrawQrcode(Image1,QRCode);
    182   finally
    183     QRCode.Free;
    184   end;
    185 end;
    186 
    187 end.
    View Code
  • 相关阅读:
    linux信号
    APM浅析
    Jackson高并发情况下,产生阻塞
    [转]slf4j 与log4j 日志管理
    2015-09-27 git学习
    MySQL学习笔记-锁相关话题
    MySQL学习笔记-MySQL数据库优化实践[转]
    MySQL学习笔记-事务相关话题
    几个关于网站架构和性能的问题(我在知乎上的问答)
    MySQL学习笔记-数据库文件
  • 原文地址:https://www.cnblogs.com/FKdelphi/p/5974198.html
Copyright © 2020-2023  润新知