2

I want to implement an Android application that reads QR codes. I have read several post here and I don't serve any of the options I 've tried, in fact I have some trouble with as many options as I've found. I tried to do the following with the Zxing library without good result:

  • Copy com package of android to my src directory. There are errors in some classes.
  • Copy com package of core/src/main , and com package of core/src/test to my src directory.
  • Copy com package of android-integration to my src directory.
  • Create a library jar with the core directory using 'ant apache'. Error using the 'ant' command in cmd, I don't know what to do with the zip file downloaded of apache.
  • Download the 'andorid-zxinglib-1.0' directory to include it as a library to the project.

None of the options used allows me to run my project properly.

Please if anyone can help me and tell me the basic steps to read QR codes with my application, both in Eclipse emulator settings, as especially to add the Zxing library to my project and code for it.

Greetings , thank you very much.

KryNaC
  • 379
  • 4
  • 21

3 Answers3

3

The simplest way is to add Core.jar library from ZXing and follow this. But it require install BarcodeScanner app from Google PLAY

The harder way is that what You try. Add src and res files to your project (probably there were some problems with resources, but it is easy to fix). Also You should add Core.jar. This solution is better, becouse You don't need any other apps. But is much harder. I can help if You will have problems with that

Don't forget add permissions.

Edit:

Ok, everytihng again step by step.

  1. Download http://code.google.com/p/zxing/downloads/detail?name=ZXing-2.3.0.zip&can=2&q=
  2. Enter android catalog.
  3. Add core-2.3.0.jar as external jar to your project (if not present, the you have to build core folder with maven). Eventually I added here
  4. copy ZXing's src to your src files (copy com catalog from ZXing folder to your src catalog)
  5. copy ZXing's res to your res files (copy every catalog from ZXing's catalog to your res catalog). IMPORTANT. If you already have some files with the same name as ZXing's then you should rename them
  6. There will be some roors in src classes. You should enter every class and update reference to R class with your own R class (eg replace import com.google.zxing.client.android.R; to import com.your.package.name.R;)
  7. The scanner class is in CaptureActiviy.class

You can also create your own Capture Activity

/*
 * Copyright (C) 2008 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


import com.yourpackage.name.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.google.zxing.Result;
import com.google.zxing.client.android.CaptureActivityHandler;
import com.google.zxing.client.android.ViewfinderView;
import com.google.zxing.client.android.camera.CameraManager;
import com.google.zxing.client.android.result.ResultHandler;
import com.google.zxing.client.android.result.ResultHandlerFactory;

public final class CaptureActivity extends Activity implements SurfaceHolder.Callback 
{
  private CameraManager cameraManager=null;
  private CaptureActivityHandler handler=null;
  private Result savedResultToShow=null;
  private ViewfinderView viewfinderView=null;
  private boolean hasSurface=false;
  ProgressDialog progressDialog=null;

  FrameLayout root=null;

  @Override
    protected void onStop() {
        super.onStop();

        if(progressDialog!=null)
        {
            progressDialog.dismiss();
        }
    }

  public ViewfinderView getViewfinderView() {
    return viewfinderView;
  }

  public Handler getHandler() {
    return handler;
  }

  public CameraManager getCameraManager() {
    return cameraManager;
  }

  @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    restoreLanguage(null);
    Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    setContentView(R.layout.capture);
  }

  @Override
  protected void onResume() {
    super.onResume();aManager = new CameraManager(getApplication());
    viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
    viewfinderView.setCameraManager(cameraManager);


    handler = null;

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


  @Override
  protected void onPause() 
  {
    if (handler != null) 
    {
      handler.quitSynchronously();
      handler = null;
    }

    cameraManager.closeDriver();
    if (!hasSurface) 
    {
      SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
      SurfaceHolder surfaceHolder = surfaceView.getHolder();
      surfaceHolder.removeCallback(this);
    }

    super.onPause();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
  }

  private void decodeOrStoreSavedBitmap(Bitmap bitmap, Result result) 
  {
    if (handler == null) {
      savedResultToShow = result;
    } else {
      if (result != null) {
        savedResultToShow = result;
      }
      if (savedResultToShow != null) {
        Message message = Message.obtain(handler, R.id.decode_succeeded, savedResultToShow);
        handler.sendMessage(message);
      }
      savedResultToShow = null;
    }
  }

  @Override
  public void surfaceCreated(SurfaceHolder holder) {
    if (holder == null) {
    }
    if (!hasSurface) {
      hasSurface = true;
      initCamera(holder);
    }
  }

  @Override
  public void surfaceDestroyed(SurfaceHolder holder) 
  {
    hasSurface = false;
    cameraManager.stopPreview();
    cameraManager.closeDriver();
  }

  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
  {
  }

  public void handleDecode(Result rawResult, Bitmap barcode) 
  {

    ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);

    if (barcode == null) 
    {
      handleDecodeInternally(rawResult, resultHandler, null);
    } 
    else 
    {
            handleDecodeInternally(rawResult, resultHandler, barcode);
    }
  }

  @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
  {
        super.onActivityResult(requestCode, resultCode, data);
  }

  private void handleDecodeInternally(Result rawResult, ResultHandler resultHandler, Bitmap barcode) 
  {
    CharSequence displayContents = resultHandler.getDisplayContents(); //here is readed code. Do ehatever you want

    cameraManager.stopPreview();
}

  private void initCamera(SurfaceHolder surfaceHolder) 
  {
    try 
    {
      cameraManager.openDriver(surfaceHolder);
      if (handler == null) 
      {
        handler = new CaptureActivityHandler(this, null, null, cameraManager);
      }
      decodeOrStoreSavedBitmap(null, null);
    } catch (Exception e) 
    {
    }
  }

  public void drawViewfinder() 
  {
    viewfinderView.drawViewfinder();
  }
}

and Permissions

<uses-permission android:name="android.permission.CAMERA"/>
     <uses-permission
    android:name="android.permission.FLASHLIGHT"
    android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
    android:protectionLevel="normal" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
  <uses-feature android:name="android.hardware.camera"/>
  <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>

  <uses-feature android:name="android.hardware.camera.flash" android:required="false"/>
Gooziec
  • 2,736
  • 1
  • 13
  • 18
  • OK, I need not have to install BarcodeScanner app in smartphone, because is uncomfortable for users. What src and res files I have to add to my project? Thanks so much. – KryNaC Dec 18 '13 at 09:52
  • I add whole `src` and whole `res` folders from `android` folder. Then probably in many files there will be problem with the R class. So You have to replace ZXing R class import with Your own – Gooziec Dec 18 '13 at 09:56
  • Ok, done. But I have errors in almost all the packages I have stuck in my src directory. – KryNaC Dec 18 '13 at 10:00
  • what kind of errors? As I said You have to replace import R class form default to Yours – Gooziec Dec 18 '13 at 10:02
  • Where is Zxing R class? – KryNaC Dec 18 '13 at 10:03
  • I don't know how to explain that (my english is rather poor). In each class You have to add import to Your R class (eg. import com.your.package.name.R;). That will "tell" eclipse to get resources from your project not, from the original – Gooziec Dec 18 '13 at 10:04
  • ok, ... in my Project/gen/mypackage directory is my R.java file. Then, I have change it for R.java file of Zxing not? Where is this file? I don't found it. – KryNaC Dec 18 '13 at 10:08
  • no, in each ZXing's class you have to import your R class. Or maybe we try in other way. What kind of errors do you have? – Gooziec Dec 18 '13 at 10:11
  • Ok understood, thanks for the patience. I have already imported R.java to all classes imported of Zxing to my src directory, but I think my R.java file is not updated, ie, I have the file res/layout/capture (I added it before of Zxing) but I gives the error: 'R.layout.capture' ... because my R.java is not updated with the res directory Zxing that I imported before. – KryNaC Dec 18 '13 at 10:20
  • So rename your old layout to not interfere with the XXing's resources (I should not be a problem - remember to change it in your src files too). Then clean the project – Gooziec Dec 18 '13 at 10:23
  • I have cleaned the project and my R.java file is missing, it is not in the 'gen' directory. So, I still have the same errors in classes. – KryNaC Dec 18 '13 at 10:27
  • so probably you have some errors in res folders. Did you change name of Your old capture.xml file and copy, the new one? – Gooziec Dec 18 '13 at 10:28
  • I edited my answer to clarify each step. I hope now all will be clear – Gooziec Dec 18 '13 at 10:44
  • This is wrong in many ways. 1) You need `android-integration.jar` to integrate by Intent, not `core.jar`. That's what uses the external app. 2) Why would you both add `core.jar` and the source code? 3) You are helping someone clone our app, which by itself violates trademark law: https://code.google.com/p/zxing/wiki/LicenseQuestions – Sean Owen Dec 18 '13 at 11:15
  • Sean please if you don't know how it works don't speak up. 1) android-integration is fine, but you have to install additional app (barcode scanner). 2) core.jar include only some base functions and can not be used separately if you don't want to implement all flow that ZXing provide – Gooziec Dec 18 '13 at 11:20
  • Thanks again, but ... How I add core-2.3.0.jar as external jar to my project in step 3?? ie. How do I get the core-2.3.0.jar? – KryNaC Dec 18 '13 at 11:22
  • Go to Project properties->Java Build Path -> Libraries -> Add External jar. The jar file should be in libs in ZXing folder – Gooziec Dec 18 '13 at 11:25
  • I know how add external jars, but there isn't a folder called 'libs' inside zxing-2.3.0 folder. There are folders like 'actionscript', 'android', 'android-integration', 'androidtest', 'core', ... – KryNaC Dec 18 '13 at 11:36
  • android\libs i thought that was obvious if we talk about android all the time :) – Gooziec Dec 18 '13 at 11:37
  • Yes, it's obvious. But in android folder there isn't a folder called libs...in all Zxing folder there isn't a folder called libs. – KryNaC Dec 18 '13 at 11:45
  • oh, so you have to build it yourself (with maven). If you don't have maven let me know, so i upload that – Gooziec Dec 18 '13 at 11:53
  • This is a thing that I wrote in my message...how I can make a jar file from android directory? I don't know how it makes, and I have never used maven. Sorry, and thanks again for help me. – KryNaC Dec 18 '13 at 12:01
  • Ok, jar file successfully added. Now, my project doesn't generate R.java file and when I import my R.java to all classes continue the errors =( – KryNaC Dec 18 '13 at 12:18
  • Probably you have some errors in your res files. Try to look for them and repair. If you are sure that there is no error, then maybe you wrong imported res folder. Post screen with structure of your res folder (in Eclipse) if you can – Gooziec Dec 18 '13 at 12:57
  • The problem is that Eclipse doesn't generate the R.java file when I create a new project, before doing the above steps =[ – KryNaC Dec 18 '13 at 13:25
  • Eclipse should generate R.java unless you have some errors in your res files or file structure. Please make screenshot with eclipse and expand res folder. I don't know how help you if i don't see where the problem could be – Gooziec Dec 18 '13 at 13:27
  • Fixed @Gooziec. Things of R.java that nobody understands, after changing a few things I got and I was able to generate it and correct errors of Zxing classes. What is the difference between CaptureActivity.class Zxing that comes in and you put up there in the message? Now I have to implement the intent to CaptureActivity.class from my main activity is it not? Thanks dude – KryNaC Dec 18 '13 at 19:25
  • You can implement your own CaptureActivity class (I posted simple example int that case you have to modify some other ZXing's classes - that's rather easy but have to remember that my example won't work instantly). You can also modify ZXing's CaptureActivity class and adapt to your needs – Gooziec Dec 19 '13 at 08:13
  • @Gooziec, can you read and reply the last answer that I have written in this post? Thanks so much. – KryNaC Dec 19 '13 at 12:14
1

add to your manifest

<uses-permission android:name="android.permission.CAMERA"/>
     <uses-permission
    android:name="android.permission.FLASHLIGHT"
    android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
    android:protectionLevel="normal" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
  <uses-feature android:name="android.hardware.camera"/>
  <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>

  <uses-feature android:name="android.hardware.camera.flash" android:required="false"/>

and declare CaptureActivity activity in manifest

then in code

startActivityForResult(new Intent(this, CaptureActivity.class), 0);
Gooziec
  • 2,736
  • 1
  • 13
  • 18
  • Permits were written, and I have already added CaptureActivity class to Manifest. Within the 'onClick' method I have only added the line you put of startActivityForResult ... but when I press the button the app continues giving error. – KryNaC Dec 19 '13 at 12:46
  • java.lang.ExceptionInitializerError – KryNaC Dec 19 '13 at 12:52
  • at java.lang.Class.newInstanceImpl(Native Method) – KryNaC Dec 19 '13 at 12:52
  • could you post whole message? And update how you start Activity now – Gooziec Dec 19 '13 at 12:53
  • at dalvik.system.NativeStart.main(Native Method) ... Caused by: java.lang.NoClassDefFoundError: com.google.zxing.ResultMetadataType – KryNaC Dec 19 '13 at 12:54
  • http://stackoverflow.com/questions/9889737/updating-sdk-got-noclassdeffounderror-for-zxing – Gooziec Dec 19 '13 at 12:55
  • Oooohh yes, thanks again @Gooziec, my app works correctly now. I had read that post before, but I didn't remember it. When I use my app for reading QR codes, a rectangle appears for introducing QR code, but the red line is in horizontal and I guess that it reads from down to up, and not from left to right as all apps for reading QR codes, not? – KryNaC Dec 19 '13 at 15:29
  • set set screenOrientation of CaptureActivity to landscape in manifest – Gooziec Dec 19 '13 at 16:32
  • I thought that was it...but I have in Manifest in CaptureActivity: 'android:configChanges="orientation"', and it remains the same – KryNaC Dec 19 '13 at 17:17
  • That should be `android:screenOrientation="landscape"` – Gooziec Dec 19 '13 at 18:09
  • OK, now the app forces you to put the phone in landscape mode to capture the QR code, but then I can not read it with the phone in portrait mode? Another thing, how I can get the String that is obtained from QR code in a variable? Thank you, if I could give you +1000 reputation =) – KryNaC Dec 20 '13 at 08:36
  • I don't understand the first question. If you want you can prepare your own activity to capture the codes and scan it in both landscape and portrait mode. The original activity looks good only in landscape mode, so it is highly recommended to set screenOrientation to landscape in that view. If you want to customize it look at `capture.xml` in resources and `ViewfinderView` class. And the second question. If you want to do something with the scanning result look at `handleDecode` method of `CaptureActivity` class. This method is called when scanning returns some data – Gooziec Dec 20 '13 at 08:44
0

If anyone wants to use Zxing now (jul-2015) on android studio, please follow this reply, hope this help

https://stackoverflow.com/a/30628337/2904625

Community
  • 1
  • 1