Android基于google Zxing实现二维码的生成
最近项目用到了二维码的生成与识别,之前没有接触这块,然后就上网搜了搜,发现有好多这方面的资源,特别是google Zxing对二维码的封装,实现的已经不错了,可以直接拿过来引用,下载了他们的源码后,只做了少少的改动,就是在Demo中增加了长按识别的功能,网上虽然也有长按识别的Demo,但好多下载下来却无法运行,然后总结了一下,加在了下面的Demo中。
下面来介绍这个Demo的主类
public class BarCodeTestActivity extends Activity { private TextView resultTextView; private EditText qrStrEditText; private ImageView qrImgImageView; private String time; private File file = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); resultTextView = (TextView) this.findViewById(R.id.tv_scan_result); qrStrEditText = (EditText) this.findViewById(R.id.et_qr_string); qrImgImageView = (ImageView) this.findViewById(R.id.iv_qr_image); Button scanBarCodeButton = (Button) this.findViewById(R.id.btn_scan_barcode); scanBarCodeButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //打开扫描界面扫描条形码或二维码 Intent openCameraIntent = new Intent(BarCodeTestActivity.this,CaptureActivity.class); startActivityForResult(openCameraIntent, 0); } }); qrImgImageView.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { // 长按识别二维码 saveCurrentImage(); return true; } }); Button generateQRCodeButton = (Button) this.findViewById(R.id.btn_add_qrcode); generateQRCodeButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { String contentString = qrStrEditText.getText().toString(); if (!contentString.equals("")) { //根据字符串生成二维码图片并显示在界面上,第二个参数为图片的大小(350*350) Bitmap qrCodeBitmap = EncodingHandler.createQRCode(contentString, 350); qrImgImageView.setImageBitmap(qrCodeBitmap); }else { //提示文本不能是空的 Toast.makeText(BarCodeTestActivity.this, "Text can not be empty", Toast.LENGTH_SHORT).show(); } } catch (WriterException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } //这种方法状态栏是空白,显示不了状态栏的信息 private void saveCurrentImage() { //获取当前屏幕的大小 int width = getWindow().getDecorView().getRootView().getWidth(); int height = getWindow().getDecorView().getRootView().getHeight(); //生成相同大小的图片 Bitmap temBitmap = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888 ); //找到当前页面的根布局 View view = getWindow().getDecorView().getRootView(); //设置缓存 view.setDrawingCacheEnabled(true); view.buildDrawingCache(); //从缓存中获取当前屏幕的图片,创建一个DrawingCache的拷贝,因为DrawingCache得到的位图在禁用后会被回收 temBitmap = view.getDrawingCache(); SimpleDateFormat df = new SimpleDateFormat("yyyymmddhhmmss"); time = df.format(new Date()); if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){ file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/screen",time + ".png"); if(!file.exists()){ file.getParentFile().mkdirs(); try { file.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } FileOutputStream fos = null; try { fos = new FileOutputStream(file); temBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } new Thread(new Runnable() { @Override public void run() { String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/screen/" + time + ".png"; final Result result = parseQRcodeBitmap(path); runOnUiThread(new Runnable() { public void run() { if(null!=result){ resultTextView.setText(result.toString()); }else{ Toast.makeText(BarCodeTestActivity.this, "无法识别", Toast.LENGTH_LONG).show(); } } }); } }).start(); //禁用DrawingCahce否则会影响性能 ,而且不禁止会导致每次截图到保存的是缓存的位图 view.setDrawingCacheEnabled(false); } } //解析二维码图片,返回结果封装在Result对象中 private com.google.zxing.Result parseQRcodeBitmap(String bitmapPath){ //解析转换类型UTF-8 Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>(); hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); //获取到待解析的图片 BitmapFactory.Options options = new BitmapFactory.Options(); //如果我们把inJustDecodeBounds设为true,那么BitmapFactory.decodeFile(String path, Options opt) //并不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回来给你 options.inJustDecodeBounds = true; //此时的bitmap是null,这段代码之后,options.outWidth 和 options.outHeight就是我们想要的宽和高了 Bitmap bitmap = BitmapFactory.decodeFile(bitmapPath,options); //我们现在想取出来的图片的边长(二维码图片是正方形的)设置为400像素 /** options.outHeight = 400; options.outWidth = 400; options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeFile(bitmapPath, options); */ //以上这种做法,虽然把bitmap限定到了我们要的大小,但是并没有节约内存,如果要节约内存,我们还需要使用inSimpleSize这个属性 options.inSampleSize = options.outHeight / 400; if(options.inSampleSize <= 0){ options.inSampleSize = 1; //防止其值小于或等于0 } /** * 辅助节约内存设置 * * options.inPreferredConfig = Bitmap.Config.ARGB_4444; // 默认是Bitmap.Config.ARGB_8888 * options.inPurgeable = true; * options.inInputShareable = true; */ options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeFile(bitmapPath, options); //新建一个RGBLuminanceSource对象,将bitmap图片传给此对象 RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(bitmap); //将图片转换成二进制图片 BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(rgbLuminanceSource)); //初始化解析对象 QRCodeReader reader = new QRCodeReader(); //开始解析 Result result = null; try { result = reader.decode(binaryBitmap, hints); } catch (Exception e) { // TODO: handle exception } return result; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //处理扫描结果(在界面上显示) if (resultCode == RESULT_OK) { Bundle bundle = data.getExtras(); String scanResult = bundle.getString("result"); resultTextView.setText(scanResult); } } }
然后长按识别二维码调用了RGBLuminanceSource这个类
public class RGBLuminanceSource extends LuminanceSource { private byte bitmapPixels[]; protected RGBLuminanceSource(Bitmap bitmap) { super(bitmap.getWidth(), bitmap.getHeight()); // 首先,要取得该图片的像素数组内容 int[] data = new int[bitmap.getWidth() * bitmap.getHeight()]; this.bitmapPixels = new byte[bitmap.getWidth() * bitmap.getHeight()]; bitmap.getPixels(data, 0, getWidth(), 0, 0, getWidth(), getHeight()); // 将int数组转换为byte数组,也就是取像素值中蓝色值部分作为辨析内容 for (int i = 0; i < data.length; i++) { this.bitmapPixels[i] = (byte) data[i]; } } @Override public byte[] getMatrix() { // 返回我们生成好的像素数据 return bitmapPixels; } @Override public byte[] getRow(int y, byte[] row) { // 这里要得到指定行的像素数据 System.arraycopy(bitmapPixels, y * getWidth(), row, 0, getWidth()); return row; } }
相机识别二维码调用了CaptureActivity这个类
public class CaptureActivity extends Activity implements Callback { private CaptureActivityHandler handler; private ViewfinderView viewfinderView; private boolean hasSurface; private Vector<BarcodeFormat> decodeFormats; private String characterSet; private InactivityTimer inactivityTimer; private MediaPlayer mediaPlayer; private boolean playBeep; private static final float BEEP_VOLUME = 0.10f; private boolean vibrate; private Button cancelScanButton; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.camera); CameraManager.init(getApplication()); viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view); cancelScanButton = (Button) this.findViewById(R.id.btn_cancel_scan); hasSurface = false; inactivityTimer = new InactivityTimer(this); } @Override protected void onResume() { super.onResume(); SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view); SurfaceHolder surfaceHolder = surfaceView.getHolder(); if (hasSurface) { initCamera(surfaceHolder); } else { surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } decodeFormats = null; characterSet = null; playBeep = true; AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE); if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) { playBeep = false; } initBeepSound(); vibrate = true; //quit the scan view cancelScanButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { CaptureActivity.this.finish(); } }); } @Override protected void onPause() { super.onPause(); if (handler != null) { handler.quitSynchronously(); handler = null; } CameraManager.get().closeDriver(); } @Override protected void onDestroy() { inactivityTimer.shutdown(); super.onDestroy(); } /** * Handler scan result * @param result * @param barcode */ public void handleDecode(Result result, Bitmap barcode) { inactivityTimer.onActivity(); playBeepSoundAndVibrate(); String resultString = result.getText(); //FIXME if (resultString.equals("")) { //扫描失败 Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show(); }else { // System.out.println("Result:"+resultString); Intent resultIntent = new Intent(); Bundle bundle = new Bundle(); bundle.putString("result", resultString); resultIntent.putExtras(bundle); this.setResult(RESULT_OK, resultIntent); } CaptureActivity.this.finish(); } private void initCamera(SurfaceHolder surfaceHolder) { try { CameraManager.get().openDriver(surfaceHolder); } catch (IOException ioe) { return; } catch (RuntimeException e) { return; } if (handler == null) { handler = new CaptureActivityHandler(this, decodeFormats, characterSet); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { if (!hasSurface) { hasSurface = true; initCamera(holder); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { hasSurface = false; } public ViewfinderView getViewfinderView() { return viewfinderView; } public Handler getHandler() { return handler; } public void drawViewfinder() { viewfinderView.drawViewfinder(); } private void initBeepSound() { if (playBeep && mediaPlayer == null) { // The volume on STREAM_SYSTEM is not adjustable, and users found it // too loud, // so we now play on the music stream. setVolumeControlStream(AudioManager.STREAM_MUSIC); mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setOnCompletionListener(beepListener); AssetFileDescriptor file = getResources().openRawResourceFd( R.raw.beep); try { mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength()); file.close(); mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME); mediaPlayer.prepare(); } catch (IOException e) { mediaPlayer = null; } } } private static final long VIBRATE_DURATION = 200L; private void playBeepSoundAndVibrate() { if (playBeep && mediaPlayer != null) { mediaPlayer.start(); } if (vibrate) { Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); vibrator.vibrate(VIBRATE_DURATION); } } /** * When the beep has finished playing, rewind to queue up another one. */ private final OnCompletionListener beepListener = new OnCompletionListener() { public void onCompletion(MediaPlayer mediaPlayer) { mediaPlayer.seekTo(0); } }; }
下面是主布局mian文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/white" android:orientation="vertical" > <Button android:id="@+id/btn_scan_barcode" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:text="Open camera" /> <LinearLayout android:orientation="horizontal" android:layout_marginTop="10dp" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/black" android:textSize="18sp" android:text="Scan result:" /> <TextView android:id="@+id/tv_scan_result" android:layout_width="fill_parent" android:textSize="18sp" android:textColor="@android:color/black" android:layout_height="wrap_content" /> </LinearLayout> <EditText android:id="@+id/et_qr_string" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:hint="Input the text"/> <Button android:id="@+id/btn_add_qrcode" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Generate QRcode" /> <ImageView android:id="@+id/iv_qr_image" android:layout_width="250dp" android:layout_height="250dp" android:scaleType="fitXY" android:layout_marginTop="10dp" android:layout_gravity="center"/> </LinearLayout>
详细了解的请下载demo自己看,Demo中解决了在竖拍解码时二维码被拉伸的现象。
不过我遇到了一个问题是 二维码的扫描框调大后,扫描的灵敏度降低了,希望知道的朋友给指导下
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。
更多Android基于google Zxing实现二维码的生成相关文章请关注PHP中文网!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Kelas kelas Java melibatkan pemuatan, menghubungkan, dan memulakan kelas menggunakan sistem hierarki dengan bootstrap, lanjutan, dan pemuat kelas aplikasi. Model delegasi induk memastikan kelas teras dimuatkan dahulu, yang mempengaruhi LOA kelas tersuai

Artikel ini membincangkan pelaksanaan caching pelbagai peringkat di Java menggunakan kafein dan cache jambu untuk meningkatkan prestasi aplikasi. Ia meliputi persediaan, integrasi, dan faedah prestasi, bersama -sama dengan Pengurusan Dasar Konfigurasi dan Pengusiran PRA Terbaik

Artikel ini membincangkan menggunakan JPA untuk pemetaan objek-relasi dengan ciri-ciri canggih seperti caching dan pemuatan malas. Ia meliputi persediaan, pemetaan entiti, dan amalan terbaik untuk mengoptimumkan prestasi sambil menonjolkan potensi perangkap. [159 aksara]

Artikel ini membincangkan menggunakan Maven dan Gradle untuk Pengurusan Projek Java, membina automasi, dan resolusi pergantungan, membandingkan pendekatan dan strategi pengoptimuman mereka.

Artikel ini membincangkan membuat dan menggunakan perpustakaan Java tersuai (fail balang) dengan pengurusan versi dan pergantungan yang betul, menggunakan alat seperti Maven dan Gradle.
