天天看點

Android內建二維碼掃描功能

文章轉載自  https://github.com/yipianfengye/android-zxingLibrary

在具體介紹該掃描庫之前我們先看一下其具體的使用方式,看看是不是幾行代碼就可以內建二維碼掃描的功能。

  • 在module的build.gradle中執行compile操作
compile 'cn.yipianfengye.android:zxing-library:2.1'
           
  • 在demo Application中執行初始化操作
@Override
    public void onCreate() {
        super.onCreate();

        ZXingLibrary.initDisplayOpinion(this);
    }
           
  • 在代碼中執行打開掃描二維碼界面操作
/**
         * 打開預設二維碼掃描界面
         */
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, CaptureActivity.class);
                startActivityForResult(intent, REQUEST_CODE);
            }
        });
           

這裡的REQUEST_CODE是我們定義的int型常量。

  • 在Activity的onActivityResult方法中接收掃描結果
/**
         * 處理二維碼掃描結果
         */
        if (requestCode == REQUEST_CODE) {
            //處理掃描結果(在界面上顯示)
            if (null != data) {
                Bundle bundle = data.getExtras();
                if (bundle == null) {
                    return;
                }
                if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) {
                    String result = bundle.getString(CodeUtils.RESULT_STRING);
                    Toast.makeText(this, "解析結果:" + result, Toast.LENGTH_LONG).show();
                } else if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_FAILED) {
                    Toast.makeText(MainActivity.this, "解析二維碼失敗", Toast.LENGTH_LONG).show();
                }
            }
        }
           

怎麼樣是不是很簡單?下面我們可以來看一下具體的執行效果:

執行效果:

Android內建二維碼掃描功能

但是這樣的話是不是太簡單了,如果我想選擇圖檔解析呢?别急,對二維碼圖檔的解析也是支援的

  • 內建對二維碼圖檔的解析功能
  • 調用系統API打開圖庫
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_IMAGE);
           
  • 在Activity的onActivityResult方法中擷取使用者選中的圖檔并調用二維碼圖檔解析API
if (requestCode == REQUEST_IMAGE) {
            if (data != null) {
                Uri uri = data.getData();
                ContentResolver cr = getContentResolver();
                try {
                    Bitmap mBitmap = MediaStore.Images.Media.getBitmap(cr, uri);//顯得到bitmap圖檔

                    CodeUtils.analyzeBitmap(mBitmap, new CodeUtils.AnalyzeCallback() {
                        @Override
                        public void onAnalyzeSuccess(Bitmap mBitmap, String result) {
                            Toast.makeText(MainActivity.this, "解析結果:" + result, Toast.LENGTH_LONG).show();
                        }

                        @Override
                        public void onAnalyzeFailed() {
                            Toast.makeText(MainActivity.this, "解析二維碼失敗", Toast.LENGTH_LONG).show();
                        }
                    });

                    if (mBitmap != null) {
                        mBitmap.recycle();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
           

執行效果

Android內建二維碼掃描功能

有了預設的二維碼掃描界面,也有了對二維碼圖檔的解析,可能有的同學會說如果我想定制化顯示UI怎麼辦呢?沒關系也支援滴。

  • 定制化顯示掃描UI

由于我們的掃描元件是通過Fragment實作的,是以能夠很輕松的實作掃描UI的定制化。

  • 在新的Activity中定義Layout布局檔案
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_second"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/second_button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="取消"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="10dp"
        android:layout_gravity="bottom|center_horizontal"
        />

    <FrameLayout
        android:id="@+id/fl_my_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        ></FrameLayout>

</FrameLayout>
           

啟動id為fl_my_container的FrameLayout就是我們需要替換的掃描元件,也就是說我們會将我們定義的掃描Fragment替換到id為fl_my_container的FrameLayout的位置。而上面的button是我們添加的一個額外的控件,在這裡你可以添加任意的控件,各種UI效果等。具體可以看下面在Activity的初始化過程。

  • 在Activity中執行Fragment的初始化操作
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        /**
         * 執行掃面Fragment的初始化操作
         */
        CaptureFragment captureFragment = new CaptureFragment();
        // 為二維碼掃描界面設定定制化界面
        CodeUtils.setFragmentArgs(captureFragment, R.layout.my_camera);
        
        captureFragment.setAnalyzeCallback(analyzeCallback);
        /**
         * 替換我們的掃描控件
         */ getSupportFragmentManager().beginTransaction().replace(R.id.fl_my_container, captureFragment).commit();
    }

           

其中analyzeCallback是我們定義的掃描回調函數,其具體的定義:

/**
     * 二維碼解析回調函數
     */
    CodeUtils.AnalyzeCallback analyzeCallback = new CodeUtils.AnalyzeCallback() {
        @Override
        public void onAnalyzeSuccess(Bitmap mBitmap, String result) {
            Intent resultIntent = new Intent();
            Bundle bundle = new Bundle();
            bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_SUCCESS);
            bundle.putString(CodeUtils.RESULT_STRING, result);
            resultIntent.putExtras(bundle);
            SecondActivity.this.setResult(RESULT_OK, resultIntent);
            SecondActivity.this.finish();
        }

        @Override
        public void onAnalyzeFailed() {
            Intent resultIntent = new Intent();
            Bundle bundle = new Bundle();
            bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_FAILED);
            bundle.putString(CodeUtils.RESULT_STRING, "");
            resultIntent.putExtras(bundle);
            SecondActivity.this.setResult(RESULT_OK, resultIntent);
            SecondActivity.this.finish();
        }
    };
           

仔細看的話,你會發現我們調用了CondeUtils.setFragmentArgs方法,該方法主要用于修改掃描界面掃描框與透明框相對位置的,與若不調用的話,其會顯示預設的元件效果,而如果調用該方法的話,可以修改掃描框與透明框的相對位置等UI效果,我們可以看一下my_camera布局檔案的實作。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <SurfaceView
        android:id="@+id/preview_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <com.uuzuche.lib_zxing.view.ViewfinderView
        android:id="@+id/viewfinder_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:inner_width="200dp"
        app:inner_height="200dp"
        app:inner_margintop="150dp"
        app:inner_corner_color="@color/scan_corner_color"
        app:inner_corner_length="30dp"
        app:inner_corner_width="5dp"
        app:inner_scan_bitmap="@drawable/scan_image"
        app:inner_scan_speed="10"
        app:inner_scan_iscircle="false"
        />

</FrameLayout>
           

上面我們自定義的掃描控件的布局檔案,下面我們看一下預設的掃描控件的布局檔案:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <SurfaceView
        android:id="@+id/preview_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <com.uuzuche.lib_zxing.view.ViewfinderView
        android:id="@+id/viewfinder_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</FrameLayout>
           

可以發現其主要的差別就是在自定義的掃描控件中多了幾個自定義的掃描框屬性:

<declare-styleable name="innerrect">
        <attr name="inner_width" format="dimension"/><!-- 控制掃描框的寬度 -->
        <attr name="inner_height" format="dimension"/><!-- 控制掃描框的高度 -->
        <attr name="inner_margintop" format="dimension" /><!-- 控制掃描框距離頂部的距離 -->
        <attr name="inner_corner_color" format="color" /><!-- 控制掃描框四角的顔色 -->
        <attr name="inner_corner_length" format="dimension" /><!-- 控制掃描框四角的長度 -->
        <attr name="inner_corner_width" format="dimension" /><!-- 控制掃描框四角的寬度 -->
        <attr name="inner_scan_bitmap" format="reference" /><!-- 控制掃描圖 -->
        <attr name="inner_scan_speed" format="integer" /><!-- 控制掃描速度 -->
        <attr name="inner_scan_iscircle" format="boolean" /><!-- 控制小圓點是否展示 -->
    </declare-styleable>
           

通過以上幾個屬性我們就可以定制化的顯示我們的掃描UI了,比如定制化微信掃描UI:

執行效果

Android內建二維碼掃描功能

當然了如果以上的以上,你還是對定制化UI方面不太滿意,可以直接下載下傳我的項目,然後引入lib-zxing module作為你的module,直接修改其代碼。

  • 生成二維碼圖檔
  • 生成帶Logo的二維碼圖檔:
/**
         * 生成二維碼圖檔
         */
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String textContent = editText.getText().toString();
                if (TextUtils.isEmpty(textContent)) {
                    Toast.makeText(ThreeActivity.this, "您的輸入為空!", Toast.LENGTH_SHORT).show();
                    return;
                }
                editText.setText("");
                mBitmap = CodeUtils.createImage(textContent, 400, 400, BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
                imageView.setImageBitmap(mBitmap);
            }
        });
           
  • 生成不帶logo的二維碼圖檔
/**
         * 生成不帶logo的二維碼圖檔
         */
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String textContent = editText.getText().toString();
                if (TextUtils.isEmpty(textContent)) {
                    Toast.makeText(ThreeActivity.this, "您的輸入為空!", Toast.LENGTH_SHORT).show();
                    return;
                }
                editText.setText("");
                mBitmap = CodeUtils.createImage(textContent, 400, 400, null);
                imageView.setImageBitmap(mBitmap);
            }
        });
           
  • 執行效果
Android內建二維碼掃描功能
  • 支援控制閃光燈
/**
 * 打開閃光燈
 */
CodeUtils.isLightEnable(true);

/**
 * 關閉閃光燈
 */
 CodeUtils.isLightEnable(false);