Implementation of QR code development using zxing under "Turn" Android platform

Source: Internet
Author: User

Http://www.cnblogs.com/dolphin0520/p/3355728.html

Now walk in the streets can see two-dimensional code, and recently because of the project needs, so research the next two-dimensional code development of things, open source QR Code scanning library mainly has zxing and Zbar,zbar in the IPOs platform application more mature, and on the Android platform mainstream or use zxing library, So here are the main ways to use zxing for QR code development.

1. How to import zxing Android source code into the project.

Import zxing Android source code, first go to the official download zxing Source: http://code.google.com/p/zxing/downloads/list.

I downloaded the 1.6 version of the, I experimented with several versions, found that 2.0 later version of the actual use of no 1.6 and 1.7 version of the good, and finally chose the 1.6 version.

Zxing 1.6 Source structure is as follows:

The Android folder is the official example under the Android platform.

Before importing, we need to compile the source code under the core file and get the kernel package Core.jar.

To compile the method, please refer to: http://blog.163.com/[email protected]/blog/static/671560502011611111116747/

Then you can import the example under the Android platform, and the import method is as follows:

1. Open Eclipse and create a new Android project: (Be careful not to copy the Android folder directly into workspace, which will not be imported)

  

2) Import core package Core.jar.

3) Modify the Strings.xml file. The project will still have an error after importing Core.jar:

  

This error may be caused by a character error, just change all of the%s and%f to%1s and F.

After the modification, the project is re-cleaned and there is no error at this time:

  

4) Operation effect:

  

2. Code simplification

In the above code, many of the features we can not use in their own projects, it needs to be simplified, as to how to simplify here is not to repeat, there are many tutorials on the web. Only the following results are simplified:

  

If only two-dimensional code recognition and two-dimensional code generation, only the files in the above package are required. Where Captureactivity.java is the class for photo framing, the following classes are primarily camera-related classes, decoding and encoding are decoding and encoding-related classes, and view is a viewfinder related class.

3. Embed the simplified zxing code into your own project.

Embed the simplified zxing code in your own project to realize the two-dimensional code generation and recognition function.

Embedding method:

1) Drag the simplified code above into your own project directory;

2) Copy the values folder and the Raw folder under your project directory;

3) Establish the Captureactivity.java layout file capture.xml.

<?xml version= "1.0" encoding= "Utf-8"? ><framelayout xmlns:android= "http://schemas.android.com/apk/res/ Android "Android:layout_width=" Fill_parent "android:layout_height=" fill_parent "> <surfaceview Andro Id:id= "@+id/preview_view" android:layout_width= "wrap_content" android:layout_height= "Wrap_content" an droid:layout_gravity= "center"/> <com.zxing.view.viewfinderview android:id= "@+id/viewfinder_view" a Ndroid:layout_width= "Wrap_content" android:layout_height= "Wrap_content"/> <relativelayout android: Layout_width= "Fill_parent" android:layout_height= "fill_parent" android:layout_gravity= "center" Androi d:orientation= "vertical" > <textview android:layout_width= "fill_parent" Android:layout_            height= "Wrap_content" android:layout_alignparenttop= "true" android:layout_centerinparent= "true"     android:gravity= "Center"       Android:paddingbottom= "10DP" android:paddingtop= "10DP" android:text= "Scan Barcode"        Android:textcolor= "@android: Color/white" android:textsize= "18sp" android:textstyle= "bold"/> <button android:id= "@+id/btn_cancel_scan" android:layout_width= "230DP" Android:lay            out_height= "40DP" android:layout_alignparentbottom= "true" android:layout_centerinparent= "true" Android:layout_marginbottom= "75DP" android:text= "Cancel" android:textsize= "15SP" an droid:textstyle= "Bold"/> </RelativeLayout></FrameLayout>

3) Import Core.jar Package

4) Modify Androdmainfest.xml

<?xml version= "1.0" encoding= "Utf-8"? ><manifest xmlns:android= "http://schemas.android.com/apk/res/ Android "package=" Com.qrcode "android:versioncode=" 1 "android:versionname=" 1.0 "> <uses-sdk Android    : minsdkversion= "7"/> <uses-permission android:name= "Android.permission.VIBRATE"/> <!--vibrate right-- <uses-permission android:name= "Android.permission.CAMERA"/> <uses-feature android:name= " Android.hardware.camera "/> <!--Use camera privileges--<uses-feature android:name=" Android.hardware.camera.aut Ofocus "/> <!--auto-focus rights--<application android:icon=" @drawable/icon "android:label=" @string/app_name "        ; <activity android:name= ". Mainactivity "android:label=" @string/app_name "> <intent-filter> <ac tion android:name= "Android.intent.action.MAIN"/> <category android:name= "Android.intent.category.LAU         Ncher "/>   </intent-filter> </activity> <!--hidden keyboard--><!--fullscreen-<activity Android:configchanges= "Orientation|keyboardhidden" Android:name= "com.zxing.activity.CaptureActi Vity "android:screenorientation=" Portrait "Android:theme=" @android: Style/theme.notitlebar.fullscreen "Android:windowsoftinputmode=" Statealwayshidden "> </activity> </application>< /manifest>

5) Operation effect:

After identifying the QR code here, the result is returned to the previous activity display, so the method called in Mainactivity is:

Intent opencameraintent = new Intent (mainactivity.this,captureactivity.class); Startactivityforresult ( Opencameraintent, 0);

The results are then obtained in Onactivityresult:

@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);        }    }

If you want to pop the recognition results directly in captureactivity, you can change the Handledecode method of the Captureactivity.java:

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 ();    }

The above code is to get the result after the call to the captureactivity activity, so if you want to change only need to the ELSE statement block below the statement and the last sentence to comment out, to fill their own code on it. For example, it can be changed to:

public void Handledecode (result result, Bitmap barcode) {inactivitytimer.onactivity ();        Playbeepsoundandvibrate ();        Final 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); */Alertdialog Resutldialog = new Alertdialog.builder (Captu            Reactivity.this). Create ();            Resutldialog.settitle ("Scan results");            Resutldialog.setmessage (resultstring);                Resutldialog.setbutton (Alertdialog.button_negative, "Cancel", new Dialoginterface.onclicklistener () { @Override PUBlic void OnClick (dialoginterface dialog, int which) {Dialog.dismiss ();                }            });        Resutldialog.show ();    }//captureactivity.this.finish (); }

My project source download: Http://files.cnblogs.com/dolphin0520/QRCode.rar

3. A number of issues relating to zxing source code.

In the actual use of the process found zxing source code has some problems, the following:

1) Vertical screen problem.

Zxing gives the official example is horizontal screen, but for the phone is actually more convenient vertical screen operation, if you want to change to vertical screen, you need to modify the following several files:

First, the configuration of Androdmainfest.xml under captureactivity is changed to vertical screen:

android:screenorientation= "Portrait"

Then you need to modify the Setdesiredcameraparameters method under Cameraconfigurationmanager.java, which directly uses the

Camera.setdisplayorientation (90);

To make the screen rotate 90 degrees, this is possible after the Android 2.2 version, but the version before 2.2 does not provide this interface, so the SDK version needs to be judged:

if (Integer.parseint (Build.VERSION.SDK) >=8)         setdisplayorientation (camera, n);        else     {             if (context.getresources (). GetConfiguration (). Orientation = = configuration.orientation_portrait)         {                 Parameters.set ("Orientation", "Portrait");                 Parameters.set ("rotation");             }             if (Context.getresources (). GetConfiguration (). Orientation = = Configuration.orientation_landscape)         {                 Parameters.set ("Orientation", "landscape");                 Parameters.set ("Rotation", "n");             }      }   

After modifying to a vertical screen, it is found that the viewfinder will stretch, which requires the following modifications:

In Cameramanager.java:

Rect.left = rect.left * cameraresolution.x/screenresolution.x;rect.right = rect.right * Cameraresolution.x/screenresol Ution.x;rect.top = rect.top * Cameraresolution.y/screenresolution.y;rect.bottom = Rect.bottom * CAMERARESOLUTION.Y/SCR EENRESOLUTION.Y;

Modified to:

Rect.left = rect.left * cameraresolution.y/screenresolution.x;rect.right = rect.right * Cameraresolution.y/screenresol Ution.x;rect.top = rect.top * Cameraresolution.x/screenresolution.y;rect.bottom = Rect.bottom * CAMERARESOLUTION.X/SCR EENRESOLUTION.Y;

Then change the method decode in the Decodehandler class to:

private void Decode (byte[] data, int width, int height) {Long start = System.currenttimemillis ();        Result rawresult = null;    Modify here byte[] Rotateddata = new Byte[data.length];  for (int y = 0, y < height; y++) {for (int x = 0; x < width; x + +) rotateddata[x * height + height    -Y-1] = data[x + y * Width]; } int tmp = width;    Here we is swapping, that's the difference to #11 width = height;        height = tmp;    Planaryuvluminancesource Source = Cameramanager.get (). Buildluminancesource (rotateddata, width, height);    Binarybitmap bitmap = new Binarybitmap (new Hybridbinarizer (source));    try {rawresult = multiformatreader.decodewithstate (bitmap);    } catch (Readerexception re) {//Continue} finally {Multiformatreader.reset ();      } if (Rawresult! = null) {Long end = System.currenttimemillis ();      LOG.D (TAG, "Found Barcode (" + (End-start) + "ms): \ n" + rawresult.tostring ()); Message MeSsage = Message.obtain (Activity.gethandler (), r.id.decode_succeeded, Rawresult);      Bundle bundle = new bundle ();      Bundle.putparcelable (Decodethread.barcode_bitmap, Source.rendercroppedgreyscalebitmap ());      Message.setdata (bundle);      LOG.D (TAG, "Sending decode succeeded message ...");    Message.sendtotarget ();      } else {Message message = Message.obtain (Activity.gethandler (), r.id.decode_failed);    Message.sendtotarget (); }  }

Then modify the method Initfromcameraparameters in the Cameraconfigurationmanager class to:

void Initfromcameraparameters (Camera camera) {camera.parameters Parameters = Camera.getparameters ();    Previewformat = Parameters.getpreviewformat ();    previewformatstring = Parameters.get ("Preview-format");    LOG.D (TAG, "Default Preview format:" + Previewformat + '/' + previewformatstring);    WindowManager manager = (WindowManager) context.getsystemservice (Context.window_service);    Display display = Manager.getdefaultdisplay ();    Screenresolution = new Point (Display.getwidth (), Display.getheight ());        LOG.D (TAG, "screen resolution:" + screenresolution);    Point Screenresolutionforcamera = new Point ();    screenresolutionforcamera.x = screenresolution.x;    SCREENRESOLUTIONFORCAMERA.Y = SCREENRESOLUTION.Y; Preview size is all something like 480*320, and other 320*480 if (Screenresolution.x < SCREENRESOLUTION.Y) {SC    reenresolutionforcamera.x = SCREENRESOLUTION.Y;    SCREENRESOLUTIONFORCAMERA.Y = screenresolution.x; } cameraresolution = GetcameraresOlution (parameters, Screenresolutionforcamera);    Cameraresolution = getcameraresolution (parameters, screenresolution);  LOG.D (TAG, "Camera resolution:" + screenresolution); }

Finally, the Rendercroppedgreyscalebitmap method in Planaryuvluminancesource.java is changed to:

Public Bitmap Rendercroppedgreyscalebitmap () {        int width = getwidth ();        int height = getheight ();        int[] pixels = new int[width * height];        byte[] YUV = yuvdata;        int inputoffset = top * dataheight + left;        for (int y = 0; y < height; y++) {          int outputoffset = y * width;          for (int x = 0; x < width; + +) {            int grey = Yuv[inputoffset + x] & 0xFF;            Pixels[outputoffset + x] = 0xff000000 | (Grey * 0x00010101);          }          Inputoffset + = Dataheight;        }        Bitmap Bitmap = bitmap.createbitmap (width, height, Bitmap.Config.ARGB_8888);        Bitmap.setpixels (pixels, 0, width, 0, 0, width, height);        return bitmap;      }

3) Drawing of viewfinder

Viewfinder's drawing can be referred to this blog post: http://www.cnblogs.com/forrestsun/archive/2012/11/06/2757005.html

4) Open and close the flash

If you need to turn the flash on and off, add 2 methods to the Cameramanager.java:

public void Openlight ()   //Open flash    {        if (camera!=null)        {             Parameters parameter= Camera.getparameters ();               Parameter.setflashmode (parameters.flash_mode_torch);              Camera.setparameters (parameter);        }    }        public void Closelight ()  //Turn off flash    {        if (camera!=null)        {             Parameters parameter= Camera.getparameters ();               Parameter.setflashmode (Parameters.flash_mode_off);              Camera.setparameters (parameter);        }    }

Then open the flash in the Initcamera method in Captureactivity:

Cameramanager.get (). Opendriver (Surfaceholder); Cameramanager.get (). Openlight ();   Open Flash

Turn off the flash where needed.

5) Continuous Scan problem

If you need to scan the QR code several times after you have successfully identified the QR code, simply add the code after the scan is complete (added in the Captureactivity Dandledecode method):

if (handler!=null)     //implement continuous scanning   handler.restartpreviewanddecode ();

Like what:

public void Handledecode (result result, Bitmap barcode) {inactivitytimer.onactivity ();        Playbeepsoundandvibrate ();        Final 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); */Alertdialog Resutldialog = new Alertdialog.builder (Captu            Reactivity.this). Create ();            Resutldialog.settitle ("Scan results");            Resutldialog.setmessage (resultstring);                Resutldialog.setbutton (alertdialog.button_positive, "Open link", new Dialoginterface.onclicklistener () {                @Overridepublic void OnClick (Dialoginterface dialog, int which) {Dialog.dismiss (); if (!islegalurl (resultstring))//If the URL is not valid {Toast.maketext (Getapplicati                        Oncontext (), "The link is not a valid URL", Toast.length_short). Show ();                        if (handler!=null)//implement continuous scanning handler.restartpreviewanddecode ();                    Return      } Intent Intent = new Intent ();                        Open the link intent.setaction ("Android.intent.action.VIEW");                       Uri Content_url = Uri.parse (resultstring);                      Intent.setdata (Content_url);                StartActivity (Intent);                        }            });                Resutldialog.setbutton (Alertdialog.button_negative, "Cancel", new Dialoginterface.onclicklistener () { @Override public void OnClick (dialoginterfacedialog, int which) {Dialog.dismiss ();                if (handler!=null)//implement continuous scanning handler.restartpreviewanddecode ();                }            });        Resutldialog.show ();    }//captureactivity.this.finish (); }

6) identify the vibration after completion.

If you need to remove the vibration after the two-dimensional code recognition, you only need to set the vibrate to false in the Onresume method of the Captureactivity class.

7) Modify the viewfinder from the top of the screen

If you need to modify the viewfinder from the top of the screen, you only need to modify the Cameramanager.java Getframingrect method, in the Getframingrect method,

int topoffset = (screenresolution.y-height)/2

This is the distance that controls the viewfinder to the top of the screen, and if you need to reduce the distance from the top of the screen, just make the denominator larger.

8) Draw the text below viewfinder.

Add the following code in front of Viewfinderview.java collection<resultpoint> currentpossible = possibleresultpoints:

  

Textpaint textpaint = new Textpaint ();           
Textpaint.setargb (0xFF, 0xFF, 0xff,0xff); Font Color textpaint.settextsize (text_size * density); Textpaint.setantialias (true); Set anti-aliasing or the handwriting will be blurry
Staticlayout layout = new Staticlayout (Getresources (). getString (R.string.scan_text), Textpaint, Frame.right-frame.left,alignment.align_normal,1.0f,0.0f,true); Canvas.translate (Frame.left, (float) (frame.bottom + (float) text_padding_top *density)); Draw the starting position layout.draw (canvas);

Explain here, Textpaint.setantialias (true); is set to anti-aliasing, otherwise the word experience is very vague. The first parameter of Staticlayout is the string to be drawn, the second is the brush, the third parameter is the width of each row, that is, the line is greater than the width, and the fourth is the alignment.

Canvas.translate (Frame.left, (float) (Frame.bottom + (float) text_padding_top *density) parameters are the starting position of the drawn string.

9) Garbled problem

In the scanning part of the QR code will appear garbled, is due to the problem of coding, you can refer to this article:

Http://www.2cto.com/kf/201209/152900.html

If you do not want to compile the core package, my project source core package is already changed, can identify the GBK QR code, the need for friends can be used directly.

About zxing Two-dimensional code identification problem for the time being discussed so much, interested friends can read the source in-depth study.

Implementation of QR code development using zxing under "Turn" Android platform

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.