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

时间:2022-02-08 12:17:30

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:\Users\zhujq-a\Desktop\Android实例之实现扫描二维码并生成二维码\"目录下。

4.引入Jar包。
在"Project1"->"Android-Android SDK 25.1.7.32bit"->Libraries->右击->"Add"->选中"C:\Users\zhujq-a\Desktop\Android实例之实现扫描二维码并生成二维码\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:\Users\zhujq-a\Desktop\Android实例之实现扫描二维码并生成二维码\Android\Debug\Project1\AndroidManifest.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\res文件夹(这里说的JAVA中的,但不是DLEPHI中的)
把"CaptureActivity\res"中的文件复制到"C:\Users\zhujq-a\Desktop\Android实例之实现扫描二维码并生成二维码\"中。
2>.打包这些资源文件
Project->Deployment->把drawable, layout, menu, raw, values 和 xml 目录下的所有档案加入->修改"Remote Path"为"Local Path"(如:"res\drawable\"的"Remote Path"为".\"改为"res\drawable\")。

9.接下来因为Zxing和 Embarcadero 都有相同的档案 res\values\styles.xml,所以要取消其中一个,并手工把两个档案的内容合并。
1>.取消官方的Styles.xml
Project->Deployment->Styles.xml去掉对号。
2>.取消官方的classes.dex(20161018亲测,去掉闪退,不去掉正好)
Project->Deployment->classes.dex去掉对号。
PS:这个地方说明一下:开始可能没有官方的classes.dex,但如果发现编译出错后,请再检查一下。
3>.把 (项目目录)\Android\Debug\styles.xml 和 (项目目录)\res\values\styles.xml 内容合并后如下
打开notepad,打开文件"C:\Users\zhujq-a\Desktop\Android实例之实现扫描二维码并生成二维码\Android\Debug\styles.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:\Users\zhujq-a\Desktop\Android实例之实现扫描二维码并生成二维码\res\values\styles.xml",粘入复制的内容。位置是在 "<style>"的最后面。
合并结束后,将"C:\Users\zhujq-a\Desktop\Android实例之实现扫描二维码并生成二维码\res\values\styles.xml"整个文件复制到"C:\Users\zhujq-a\Desktop\Android实例之实现扫描二维码并生成二维码\Android\Debug\"中。

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

生成二维码功能
1.将"xZXIngQRCode.pas"文件放入"C:\Users\zhujq-a\Desktop\Android实例之实现扫描二维码并生成二维码\"工程代码目录下面。
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),还有许多不知名的作者。

实例代码:

 unit Unit1;

 interface

 uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Edit, FMX.Controls.Presentation,
System.Messaging,//需要引入
System.Rtti,//需要引入
System.Actions,//需要引入
Androidapi.JNI.Net,//需要引入
Androidapi.JNI.GraphicsContentViewText,//需要引入
Androidapi.JNI.JavaTypes,//需要引入
Androidapi.Helpers,//需要引入
Androidapi.JNI.App,//需要引入
FMX.Objects,//需要引入
FMX.ActnList,//需要引入
FMX.StdActns,//需要引入
FMX.Platform.Android,//需要引入
FMX.MediaLibrary.Actions,//需要引入
xZXIngQRCode;//需要引入 type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Image1: TImage;
Panel1: TPanel;
Label4: TLabel;
Edit3: TEdit;
Label5: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
Shift: TShiftState);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
//扫描请求代码
const ScanRequestCode = ;
//
var FMessageSubscriptionID: Integer;
//活动结果事件
function OnActivityResult(RequestCode, ResultCode: Integer; Data: JIntent): Boolean;
//活动消息处理
procedure HandleActivityMessage(const Sender: TObject; const M: TMessage);
public
{ Public declarations }
//扫描状态
ScanState: Boolean;//TRUE代表扫描中,FALSE扫描结束
end; var
Form1: TForm1; implementation {$R *.fmx}
{$R *.LgXhdpiPh.fmx ANDROID} //启用扫码
procedure LaunchQRScanner(RequestCode: Integer);
var
Intent: JIntent;
begin
Intent := TJIntent.JavaClass.init;
Intent.setClassName(SharedActivityContext, StringToJString('com.google.zxing.client.android.CaptureActivity'));
//如果要预定扫描格式,UnComment 下面文字
//Intent.putExtra(StringToJString('SCAN_MODE'), StringToJString('QR_CODE_MODE'));
SharedActivity.startActivityForResult(Intent, RequestCode);
end; //调用扫码方法
procedure TForm1.Button1Click(Sender: TObject);
var
LIntent: JIntent;
begin
//LIntent := TJIntent.JavaClass.init;
//LIntent.setClassName(SharedActivityContext, StringToJString('com.google.zxing.client.android.CaptureActivity'));
//SharedActivity.startActivityForResult(LIntent, 0);
//加载扫码
FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage(TMessageResultNotification,
HandleActivityMessage);
//开始扫码
LaunchQRScanner(ScanRequestCode);
//状态定为扫码结束
ScanState := False;
end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
Shift: TShiftState);
begin
//如果按下物理返回键,但是扫码未结束
if (Key = vkHardwareBack) and (ScanState = True) then
begin
ScanState := False;
Key := ;
Exit;
end;
//如果按下物理返回键,并且扫码结束
if (Key = vkHardwareBack) and (ScanState = False) then
begin
{$IFDEF ANDROID}
MessageDlg('确认退出吗?', System.UITypes.TMsgDlgType.mtInformation,
[
System.UITypes.TMsgD*n.mbYes,
//System.UITypes.TMsgD*n.mbNo,
System.UITypes.TMsgD*n.mbCancel
], , System.UITypes.TMsgD*n.mbCancel,
procedure(const AResult: TModalResult)
begin
if AResult = mrYES then
MainActivity.finish; { 退出程序 } // use FMX.Platform.Android
end);
{$ENDIF ANDROID}
//close;
Key := ;
Exit;
end;
end; //活动消息处理
procedure TForm1.HandleActivityMessage(const Sender: TObject;
const M: TMessage);
begin
if M is TMessageResultNotification then
OnActivityResult(TMessageResultNotification(M).RequestCode, TMessageResultNotification(M).ResultCode,
TMessageResultNotification(M).Value);
end; //活动结果事件
function TForm1.OnActivityResult(RequestCode, ResultCode: Integer;
Data: JIntent): Boolean;
var
ScanContent, ScanFormat: string;
begin
Result := False; TMessageManager.DefaultManager.Unsubscribe(TMessageResultNotification, FMessageSubscriptionID);
FMessageSubscriptionID := ;
//判断请求代码
if RequestCode = ScanRequestCode then
begin
//如果扫码结束
if ResultCode = TJActivity.JavaClass.RESULT_OK then
begin
//有数据
if Assigned(Data) then
begin
//解析出数据
ScanContent := JStringToString(Data.getStringExtra(StringToJString('SCAN_RESULT')));
ScanFormat := JStringToString(Data.getStringExtra(StringToJString('SCAN_RESULT_FORMAT')));
Edit1.Text:= ScanContent;
Edit2.Text:= ScanFormat;
Label5.Text:= '扫描成功';
end;
end
else if ResultCode = TJActivity.JavaClass.RESULT_CANCELED then
begin
Label5.Text:= '扫描取消';
end;
Result := True;
end;
end; //生成二维码
procedure TForm1.Button2Click(Sender: TObject);
var
QRCode: TDelphiZXingQRCode;
begin
QRCode := TDelphiZXingQRCode.Create;
try
QRCode.Data := Edit3.Text;
QRCode.Encoding := TQRCodeEncoding();
QRCode.QuietZone := ;
QRCode.DrawQrcode(Image1,QRCode);
finally
QRCode.Free;
end;
end; end.

Android实例-实现扫描二维码并生成二维码(XE8+小米5)的更多相关文章

  1. Android zxing 解析二维码,生成二维码极简demo

    zxing 官方的代码很多,看起来很费劲,此demo只抽取了有用的部分,实现了相机预览解码,解析本地二维码,生成二维码三个功能. 简化后的结构如下: 废话少说直接上代码: BaseDecodeHand ...

  2. Cordova各个插件使用介绍系列(二)—&dollar;cordovaBarcodeScanner扫描二维码与生成二维码

    详情链接地址:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/cordova-2-cordovabarcodescanner/ 这是 ...

  3. 【Java 二维码】生成二维码

    ZXingCodeEncodeUtils 生成及解析二维码项目 package utils; import java.awt.BasicStroke; import java.awt.Color; i ...

  4. 前端生成二维码 - Javascript生成二维码(QR)

    前段时间项目中需要动态的生成二维码,经过评估,前后端生成都可以.但后端生成会有两个问题: 没有找到正规发布出来的后端开源库. 二维码图片,会随着商品的增加而不断变多. 基于以上两个问题,决定在前端生成 ...

  5. 后端生成二维码 - C&num;生成二维码(QR)

    最近在github上找到一个相对比较好的C#二维码生成类库.在这里和大家分享一下. github地址:https://github.com/codebude/QRCoder 把解决方案下载下来,编译生 ...

  6. Laravel5中通过SimpleQrCode扩展包生成二维码实例

    Simple Qrcode是基于强大的Bacon/BaconQrCode库开发的针对Laravel框架的封装版本,用于在Laravel中为生成二维码提供接口. 安装SimpleQrCode扩展包 在项 ...

  7. Android利用zxing生成二维码

    感谢大佬:https://blog.csdn.net/mountain_hua/article/details/80646089 **gayhub上的zxing可用于生成二维码,识别二维码 gayhu ...

  8. iOS端使用二维码扫描(ZBarSDK)和生成(libqrencode)功能

    如今二维码随处可见,无论是实物商品还是各种礼券都少不了二维码的身影.手机中二维码使用也很广泛,如微信等.正好最近收集总结了下二维码的使用方法 下面介绍一下如何在iOS设备上使用二维码 首先在githu ...

  9. ecstore生成二维码

    利用phpqrcode库生成二维码: /* *二维码添加 */ ////////////////////////////////////// /*引入文件*/ @include(APP_DIR.'/i ...

随机推荐

  1. &lbrack;转&rsqb; Java内部类详解

    作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...

  2. js跟随鼠标移动的写法

    <script> window.onload=function(){ document.onmousemove=function (ev) { var oEvent=ev||event; ...

  3. ARC小知识

    ARC是iOS 5推出的新功能,全称叫 ARC(Automatic Reference Counting).简单地说,就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管 ...

  4. POJ 2155 Matrix &lpar;二维线段树入门,成段更新,单点查询 &sol; 二维树状数组,区间更新,单点查询&rpar;

    题意: 有一个n*n的矩阵,初始化全部为0.有2中操作: 1.给一个子矩阵,将这个子矩阵里面所有的0变成1,1变成0:2.询问某点的值 方法一:二维线段树 参考链接: http://blog.csdn ...

  5. JMeter 之Synchronizing Timer运行原理

    JMeter测试并发场景,是通过设置Synchronizing Timer(同步定时器),熟悉LoadRunner性能测试的话,就知道里面有个概念:集合点. Synchronizing Timer则可 ...

  6. SDP(7):Cassandra- Cassandra-Engine:Streaming

    akka在alpakka工具包里提供了对cassandra数据库的streaming功能.简单来讲就是用一个CQL-statement读取cassandra数据并产生akka-stream的Sourc ...

  7. Linux下查看80端口是否被占用

    方式一: ps -ef |grep 80 方式二: netstat -anp |grep :80 方式三: lsof -i:80 方式四: netstat -tunlp |grep :80 方式五: ...

  8. 神仙数据结构——FHQ&lowbar;Treap

    $FHQ\_Treap$是平衡树的一种,它不仅支持几乎所有的平衡树的操作,而且实现特别简单,总共只有两个操作.这里来简单介绍一下. 基本操作 $FHQ\_Treap$和$Treap$一样是需要用随机值 ...

  9. Loader的初步学习笔记

    Loader是一个异步加载数据的类,它和AsyncTask有类似也有不同,今天我们就先来学习下它.由于是对比学习,所以我们先来复习下AsyncTask的使用和特点. 一.AsyncTask 参考自:h ...

  10. UIViewController的初始化

    UIViewController的初始化一般有两个: -(instancetype)init; -(instancetype)initWithNibName:(NSString *)nibNameOr ...