show code block

2017年4月20日 星期四

third-party元件(barcodescanner) ─ 簡易掃描QRCode

前言:

如果在Google Play商店搜尋打QRCode,你會發現如沐春雨般的此類App。

這是使用第三方是非常簡單就能實作出來的東西,看來大家都想賺廣告錢啊XD

這次東西有牽涉到
Android元件 ─ 要求權限 Permission 封裝(二)
Android元件(WebView) ─ 內崁網路瀏覽器



QRCODE第三方:https://github.com/dm77/barcodescanner





重要程式碼:

只要記得 implements ZXingScannerView.ResultHandler

和複寫
public void handleResult(final Result rawResult) {
 //do something after scanner
  }

這個方法就好了。
剩下就是簡單的設定問題了。



實作:

今日要實做到的部分。


STEP 1 :先在 build.gradle(Module:app)加入今日的第三方

compile 'me.dm7.barcodescanner:zxing:1.9'


STEP 2 :在AndroidManifest.xml內加入要使用到的權限

   <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.INTERNET" />

由上至下的權限分別為:
自動對焦
獲取使用相機
網路使用權

其中只有獲取使用相機是危險權限,所以只有這裡需要額外寫Code和使用者要權限。

STEP 3 ;創建新的Activity和畫xml



在「APP上按右鍵 > NEW > Activit y> Empty Activity
先創建一個新Activity,我命名為ScannerActivity.javaactivity_scanner.xml

先著手開始畫xml
activity_main.xml

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.spinner.a015865.qrcode.MainActivity">

    <TextView
        android:layout_margin="20dp"
        android:onClick="scanCode"
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="I am Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
<WebView
    android:id="@+id/wv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
</LinearLayout>
設置一個Button,在Button下面畫一個WebView,當QRCode掃入一個網址後,可以回掉開啟。



activity_scanner.xml
activity_scanner.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    android:id="@+id/main_activity"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.spinner.a015865.qrcode.ScannerActivity">
</FrameLayout>


基本上就是空的,唯一需要設置的就是這xml的id。我們之後會用到。

STEP 4 :寫入程式JAVA

MainActivity.java
public class MainActivity extends AppCompatActivity {
    //設置畫面元件
    private TextView mTextView;
    private WebView mWebView;

    //轉畫面的Activity參數
    private Class<?> mClss;

    //
    private static final int ZXING_CAMERA_PERMISSION = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始畫面
        initView();
        //初始畫面設置
        initSet();


    }


    //起始畫面
    private void initView() {
        mTextView = (TextView) findViewById(R.id.tv);
        mWebView = (WebView) findViewById(R.id.wv);
    }

    //起始畫面設置
    private void initSet() {

        /**
         * 以下都是WebView的設定
         * */
        WebSettings websettings = mWebView.getSettings();
        websettings.setSupportZoom(true); //啟用內置的縮放功能
        websettings.setBuiltInZoomControls(true);//啟用內置的縮放功能
        websettings.setDisplayZoomControls(false);//讓縮放功能的Button消失
        websettings.setJavaScriptEnabled(true);//使用JavaScript
        websettings.setAppCacheEnabled(true);//設置啟動緩存
        websettings.setSaveFormData(true);//設置儲存
        websettings.setAllowFileAccess(true);//啟用webview訪問文件數據
        websettings.setDomStorageEnabled(true);//啟用儲存數據
        mWebView.setWebViewClient(new WebViewClient());
    }

    //Button的設置
    public void scanCode(View view) {
//        startActivityForResult(new Intent(this, ScannerActivity.class), 1);
        launchActivity(ScannerActivity.class);
    }

    //轉畫面的封包,兼具權限和Intent跳轉化面
    public void launchActivity(Class<?> clss) {
        //假如還「未獲取」權限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            mClss = clss;
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA}, ZXING_CAMERA_PERMISSION);
        } else {
            Intent intent = new Intent(this, clss);
//            startActivity(intent);
            startActivityForResult(intent, ZXING_CAMERA_PERMISSION);
        }
    }

    //當ScannerActivity結束後的回調資訊
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            Log.d("checkpoint", "CheckPoint");
            mTextView.setText(data.getStringExtra("text"));

            mWebView.loadUrl(data.getStringExtra("text"));
        }
    }
}

MainActivity內我使用到了WebViewPermission的封包方法。詳情點連結。

ScannerActivity.java
public class ScannerActivity extends Activity implements ZXingScannerView.ResultHandler {
    private ZXingScannerView mScannerView;

    @Override
    public void onCreate(Bundle state) {
        super.onCreate(state);
        setContentView(R.layout.activity_scanner);
        //設置畫面
        ViewGroup contentFrame = (ViewGroup) findViewById(R.id.main_activity);
        //設定Scanner
        mScannerView = new ZXingScannerView(this);
        //把Scanner加入
        contentFrame.addView(mScannerView);
//        setContentView(mScannerView);
    }

    @Override
    public void onResume() {
        super.onResume();
        //設置Scanner的回調
        mScannerView.setResultHandler(this);
        //開啟相機
        mScannerView.startCamera();
    }

    @Override
    public void onPause() {
        super.onPause();
        //停止相機
        mScannerView.stopCamera();
    }

    //設定回調,當你掃完QR你將要做的事情
    @Override
    public void handleResult(final Result rawResult) {
        Toast.makeText(this, "Contents = " + rawResult.getText() +
                ", Format = " + rawResult.getBarcodeFormat().toString(), Toast.LENGTH_SHORT).show();

        /**
         * 這邊等兩秒才回調資料
         * 比較舊的設備有時候會產生無法預期的錯誤
         * 這邊作者使用延遲兩秒去debug
         * */
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //把掃描到的資料回調到MainActivity
                Intent data = new Intent();
                data.putExtra("text", rawResult.getText());
                setResult(RESULT_OK, data);
                finish();
                mScannerView.resumeCameraPreview(ScannerActivity.this);
            }
        }, 2000);
    }
}


完成囉!





Demo:
https://drive.google.com/open?id=0Byk75IYx-dKXT0dERGdqRVNYSEk




沒有留言:

張貼留言

協程(coroutine) - 協程為什麼要學它?

 Coroutine 協程 再強調一次 協程就是由kotlin官方所提供的線程api //Thread Thread { }.start() //Executor val execu...