show code block

顯示具有 qrcode卡頓 標籤的文章。 顯示所有文章
顯示具有 qrcode卡頓 標籤的文章。 顯示所有文章

2017年11月26日 星期日

Android元件(AsyncTask)— 非同步任務、異步任務

前言

現在下載東西大多都使用第三方套件,異步任務都已經幫你處理得妥妥的。
但如果你要生成一張很大的圖片或是很好資源的任何東西,你就會需要它

這邊貼個介紹
http://aiur3908.blogspot.tw/2015/06/android-asynctask.html
超好懂的AsyncTask

以下簡略轉貼
求詳細請點上面網址

今日實作


重點程式碼

AsyncTask<Params, Progress, Result>



你開的class 會需要繼承 AsyncTask

而後面的三個參數

Params  代表著你要放入的參數,像是String 或是 int 

Progress 如果你要下載東西,這邊專門給你用進度條的參數

Result 就是你希望這條你新分出去的執行緒要回到主執行緒的時候要返回什麼東西。
如果你是拿來下載圖片,就可以返回Bitma。如果你是跑一個陣列,也可以返回ArrayList<>之類的....


而繼承AsyncTask會產生四個方法

onPreExecute  執行前,一些基本設定可以在這邊做。

doInBackground  執行中,在背景做任務。這邊就是重點中的重點,你希望下載或做事情的方法寫在這邊

onProgressUpdate  執行中,專門給Porgress條做監聽的方法

onPostExecute  執行後,最後的結果會在這邊。如果你Result的部分設定返回圖片,這裡就會噴Bitmap給你

方法會長以下這樣 

private class GetImage extends AsyncTask<String , Integer , Bitmap>{

        @Override
        protected void onPreExecute() {
            //執行前 設定可以在這邊設定
            super.onPreExecute();
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            //執行中 在背景做事情
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            //執行中 可以在這邊告知使用者進度
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            //執行後 完成背景任務
            super.onPostExecute(bitmap);
        }
}
 

String... 和 int... 的部分可以參考我寫的一篇猛虎出閘
http://nikeru8.blogspot.tw/2017/08/java.html

如果是複數的Params,使用方式就是Params[0]、Params[1]依此類推...

Params[0] 就會是helloOne
Params[1] 就是 helloTwo

使用範例

private class GetImage extends AsyncTask<String , Integer , Bitmap>{

        private ProgressDialog progressBar;
        //進度條元件

        @Override
        protected void onPreExecute() {
            //執行前 設定可以在這邊設定
            super.onPreExecute();

            progressBar = new ProgressDialog(MainActivity.this);
            progressBar.setMessage("Loading...");
            progressBar.setCancelable(false);
            progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressBar.show();
            //初始化進度條並設定樣式及顯示的資訊。
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            //執行中 在背景做事情
            int progress = 0;
            for (String urlStr : params) {
                try {
                    URL url = new URL(urlStr);
                    Bitmap bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
                } catch (Exception  e) {
                    e.printStackTrace();
                }
                publishProgress(progress+=33);
                //有三張圖 每張圖33%
            }
            publishProgress(100);
            //最後達到100%
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            //執行中 可以在這邊告知使用者進度
            super.onProgressUpdate(values);
            progressBar.setProgress(values[0]);
            //取得更新的進度
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            //執行後 完成背景任務
            super.onPostExecute(bitmap);

            progressBar.dismiss();
            //當完成的時候,把進度條消失
            imageView.setImageBitmap(bitmap);
        }
    }
 


完整程式碼

main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:clickable="true"
        android:gravity="center"
        android:onClick="onbuttonclick"
        android:text="產生QRCode" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="45dp" />
</RelativeLayout>
 

MainActivity.java
public class MainActivity extends AppCompatActivity {


    private Activity activity;

    private ProgressDialog loadingDialog;

    //要生成的QRCode內容
    String QRCodeContent = "http://nikeru8.blogspot.tw/2017/04/third-partyxzingcore-qrcodejar.html";
    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        activity = this;
        //參數
        imageView = (ImageView) findViewById(R.id.imageView);

        //設定loading Dialog
        loadingDialog = new ProgressDialog(activity);
        loadingDialog.setCanceledOnTouchOutside(false);
        loadingDialog.setCancelable(true);
        loadingDialog.setMessage("loading please wait...");
    }

    public void onbuttonclick(View view) {
        new GetImage().execute(QRCodeContent);
    }


    private class GetImage extends AsyncTask<String, Integer, Bitmap> {

        @Override
        protected void onPreExecute() {
            //執行前 設定可以在這邊設定

            loadingDialog.show();
            super.onPreExecute();
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            //執行中 在背景做事情
            int QRCodeWidth = 600;
            int QRCodeHeight = 600;
            //QRCode內容編碼
            Map hints = new EnumMap(EncodeHintType.class);
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

            MultiFormatWriter writer = new MultiFormatWriter();
            try {
                //ErrorCorrectionLevel容錯率分四級:L(7%) M(15%) Q(25%) H(30%)
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);

                //建立QRCode的資料矩陣
                BitMatrix result = writer.encode(params[0], BarcodeFormat.QR_CODE, QRCodeWidth, QRCodeHeight, hints);

                //建立矩陣圖
                Bitmap bitmap = Bitmap.createBitmap(QRCodeWidth, QRCodeHeight, Bitmap.Config.ARGB_4444);
                for (int y = 0; y < QRCodeHeight; y++) {
                    for (int x = 0; x < QRCodeWidth; x++) {
                        bitmap.setPixel(x, y, result.get(x, y) ? Color.BLACK : Color.WHITE);
                    }
                }

                return bitmap;

            } catch (WriterException e) {
                e.printStackTrace();
                return null;
            }

        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            //執行中 可以在這邊告知使用者進度
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            //執行後 完成背景任務
            super.onPostExecute(bitmap);
            imageView.setImageBitmap(bitmap);
            loadingDialog.dismiss();
        }
    }
}

 


Demo


我拿QRCode寫個範例

因為QRCode如果跑太大張,通常都會造成畫面卡頓

使用AsyncTask就可以完美解決這問題

https://github.com/nikeru8/QRCodeDemo

2017年4月20日 星期四

third-party元件(XZing.core) ─ 生成QRCode、導入第三方(jar)

前言:

有別於掃描的用法。

這次是在App內生成QRCode。

情境可以是給她一個網址參數,或任何字串,然後產生QRcode提供掃描。

像是購物網站,當你買了物品,你想追蹤商品情況時,購物網站可以在訂單查詢內提供QRCode供你掃描查看商品跑去哪了。
可以看看這第三方 https://github.com/zxing/zxing







實作:

等等要操作到的地方



STEP 1 :先匯入專案


兩種匯入方式 兩種選擇其中一種就好,別傻傻的兩個都匯入
第一種
第一種是直接compile
compile 'com.google.zxing:core:3.2.1'
 

 第二種
先把core-3.2.1.jar下載下來。

然後就開始匯入專案了。

匯入專案的地方可以參考這一篇:
http://nikeru8.blogspot.tw/2017/03/androidyoutube-api-youtube-api.html

我在這邊使用另外一種方式,不過大同小異。

下載下來後,把core-3.2.1.jar放到你自己專案的資料夾libs內。(如果沒有此資料夾請自己創)

如果圖片太小可點擊放大
core-3.2.1.jar放入後讓我們回到Android Studio,匯入專案囉

點選左上角選擇「Project」>>  找到「libs」>> 找到「core-3.2.1.jar」 >> 點擊右鍵 >> 選擇「Add As Library...



跳出視窗選擇「app」 >> ok


專案匯入完成囉!


STEP 2:來畫我們的xml

activity_main.xml
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:clickable="true"
        android:gravity="center"
        android:onClick="onbuttonclick"
        android:text="產生QRCode" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="45dp" />
</RelativeLayout>


設置一個Button,等點擊之後生成QRCode


STEP 3:寫Code in JAVA

MainActivity.java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onbuttonclick(View view) {
        String QRCodeContent = "http://nikeru8.blogspot.tw/2017/04/third-partyxzingcore-qrcodejar.html";
        int QRCodeWidth = 200;
        int QRCodeHeight = 200;

        //QRCode內容編碼
        Map hints = new EnumMap(EncodeHintType.class);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

        MultiFormatWriter writer = new MultiFormatWriter();
        try {
            //ErrorCorrectionLevel容錯率分四級:L(7%) M(15%) Q(25%) H(30%)
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);

            //建立QRCode的資料矩陣
            BitMatrix result = writer.encode(QRCodeContent, BarcodeFormat.QR_CODE, QRCodeWidth, QRCodeHeight, hints);

            //建立矩陣圖
            Bitmap bitmap = Bitmap.createBitmap(QRCodeWidth, QRCodeHeight, Bitmap.Config.ARGB_4444);
            for (int y = 0; y < QRCodeHeight; y++) {
                for (int x = 0; x < QRCodeWidth; x++) {
                    bitmap.setPixel(x, y, result.get(x, y) ? Color.BLACK : Color.WHITE);
                }
            }

            //設定給xml
            ImageView imageView = (ImageView) findViewById(R.id.imageView);
            imageView.setImageBitmap(bitmap);
        } catch (WriterException e) {
            e.printStackTrace();
        }
    }
}

完成囉!
QRCodeContent內就是QRCode產生出來的字串。


eidt(2017/06/12)
我發現如果QRCode你要放到很大很大,直接調整QRCodeWidth和Height會因為產生bitmap而有卡頓狀況。
此時可以用一個方法改善
  bitmap = Bitmap.createScaledBitmap(bitmap,
                    bitmap.getWidth() * 4,
                    bitmap.getHeight() * 4, false);


eidt(2017/11/27)
兩件事
一、控制QRCode旁邊白邊的大小
hints.put(EncodeHintType.MARGIN, 0);
 
後面的0 這個int參數,設得越大白邊就越寬
二、QRCode圖片太大有時候會造成app卡頓
使用AsyncTask http://nikeru8.blogspot.tw/2017/11/androidasynctask_26.html




文獻:
http://gnehcic.azurewebsites.net/android%E5%BB%BA%E7%AB%8Bqr-code/
https://github.com/zxing/zxing


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


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

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