Android 使用 ZXing 库实现二维码扫描与生成
在 Android 开发中,二维码功能(扫描与生成)是应用集成中的常见需求。ZXing (Zebra Crossing) 是一个开源的条码/二维码处理库。本文将详细介绍如何在 Android 项目中集成 zxing-lite 库,并实现扫描二维码和生成二维码的功能。
1. 引入第三方依赖
首先,需要在项目的 build.gradle (Module: app) 文件中添加 zxing-lite 的依赖。推荐使用 AndroidX 版本以确保兼容性。
// build.gradle (Module: app)
dependencies {
implementation 'com.king.zxing:zxing-lite:1.1.7-androidx'
}
添加完成后,点击 "Sync Now" 同步项目依赖。
2. 配置 AndroidManifest.xml
为了能够调用摄像头进行扫描,必须在清单文件中声明权限以及扫描 Activity。
2.1 声明权限
在 <manifest> 标签下添加以下权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.VIBRATE" />
<!-- 如果需要保存图片或读取相册 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2.2 注册 CaptureActivity
ZXing-lite 提供了现成的扫描界面 Activity,需要在 Manifest 中注册它,并设置合适的主题和屏幕方向。
<activity
android:name="com.king.zxing.CaptureActivity"
android:screenOrientation="fullSensor"
android:theme="@style/CaptureTheme" />
注意:在 Android 6.0 (API 23) 及以上版本,动态运行时权限是必须的。建议在代码中处理权限申请逻辑。
3. 布局文件设计 (activity_main.xml)
主界面需要包含输入框、按钮和图片展示区域。以下是推荐的布局结构:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<!-- 显示扫描结果 -->
<EditText
android:id="@+id/edt_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="扫描结果将显示在这里"
android:inputType="textMultiLine" />
<!-- 操作按钮组 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="16dp">
<Button
android:id="@+id/btn_scan"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="扫码" />
<Button
android:id="@+id/btn_create"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="生成" />
</LinearLayout>
<!-- 输入内容用于生成 -->
<EditText
android:id="@+id/edt_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="请输入要生成的文字内容" />
<!-- 二维码图片展示 -->
<ImageView
android:id="@+id/iv_qr"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_marginTop="16dp"
android:scaleType="fitCenter"
android:src="@android:drawable/ic_menu_gallery" />
</LinearLayout>
4. 核心代码实现 (MainActivity.java)
在主活动中,我们需要初始化视图,处理按钮点击事件,并接收扫描回调。
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.king.zxing.CaptureActivity;
import com.king.zxing.util.CodeUtils;
import static com.king.zxing.CaptureFragment.KEY_RESULT;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
protected EditText edtResult;
protected Button btnScan;
protected Button btnCreate;
protected EditText edtData;
protected ImageView ivQr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 修复:直接调用 setContentView,而非 super.setContentView
setContentView(R.layout.activity_main);
// 初始化权限工具类(需自行实现或使用 PermissionX 等库)
// PermissionUtils.applyPermission(this);
initView();
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.btn_scan) {
// 跳转到扫描界面
Intent intent = new Intent(this, CaptureActivity.class);
startActivityForResult(intent, 1);
} else if (view.getId() == R.id.btn_create) {
String data = edtData.getText().toString().trim();
if (TextUtils.isEmpty(data)) {
Toast.makeText(this, "请输入文字", Toast.LENGTH_SHORT).show();
} else {
// 生成二维码
Bitmap qrCode = CodeUtils.createQRCode(data, 600, null);
ivQr.setImageBitmap(qrCode);
}
}
}
/**
* 在该方法中拿到扫描的数据
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
String result = data.getStringExtra(KEY_RESULT);
Log.e("ZXing", "scan result-->" + result);
// 展示到页面上
if (edtResult != null) {
edtResult.setText(result);
}
}
} else if (resultCode == RESULT_CANCELED) {
// 用户取消扫描
Log.d("ZXing", "Scan canceled");
}
}
private void initView() {
edtResult = findViewById(R.id.edt_result);
btnScan = findViewById(R.id.btn_scan);
btnScan.setOnClickListener(this);
btnCreate = findViewById(R.id.btn_create);
btnCreate.setOnClickListener(this);
edtData = findViewById(R.id.edt_data);
ivQr = findViewById(R.id.iv_qr);
}
}
5. 常见问题与注意事项
5.1 运行时权限
在 Android 6.0 及以上版本,即使 Manifest 中声明了 CAMERA 权限,也需要在代码中动态请求用户授权。如果未获取权限,扫描界面可能会闪退或无法启动相机。
建议封装一个权限检查工具类,或者使用如 PermissionX 这样的库来简化流程。
5.2 内存溢出问题
生成高分辨率二维码时,Bitmap 会占用较多内存。如果频繁生成且未回收,可能导致 OOM。建议在生成后及时复用 Bitmap 对象,或在低内存设备上降低生成尺寸。
5.3 ProGuard 混淆
如果开启了代码混淆,请确保保留 ZXing 相关的类。在 proguard-rules.pro 中添加以下规则:
-keep class com.king.zxing.** { *; }
-dontwarn com.king.zxing.**
5.4 主题适配
CaptureTheme 默认样式可能在不同机型上表现不一致。如果发现扫描界面背景色异常,可以在 styles.xml 中自定义该主题颜色。
6. 总结
通过集成 zxing-lite 库,开发者可以快速在 Android 应用中实现二维码的扫描与生成功能。本文涵盖了从依赖引入、权限配置、UI 布局到核心逻辑实现的完整流程。在实际开发中,还需结合具体业务场景处理权限交互、错误提示及用户体验优化。

