how to use zxing core as library on my andorid project

1,904 views
Skip to first unread message

shane

unread,
Feb 15, 2011, 9:43:25 AM2/15/11
to zxing
Hi,

I'm building the android scanning app using zxing library, i have
build the zxing core and include the core.jar to my application build
path, i don't want to use the intent solution provide in this url
"http://code.google.com/p/zxing/wiki/ScanningViaIntent".

My Question is how i can open the camera,capture the contentious
images and pass to zxing core library to decode it, when the decode
method return the success stop the camera and print the result

i found the following link useful for me, "http://www.arp123.com/post/
Identified-in-the-Android-use-ZXing-barcode-QR-Code.html" but having
problems in continuous scanning. when compare to zxing 1.6 android
barcode scanner app my solution is not good :D, if some one can help
me or guide me to sort out this really appreciate

shane.

Daniel Switkin

unread,
Feb 15, 2011, 12:26:07 PM2/15/11
to zx...@googlegroups.com
Have a look at how the Barcode Scanner app does this. The source is in
zxing/android.

samith premetilaka

unread,
Feb 15, 2011, 10:40:53 PM2/15/11
to zx...@googlegroups.com
yep, i already try that, and got it work, need to know few questions on that

01. how to support the camera  portrait view rather than lands cape view

02.how it handle the decoding, i mean capturing a image from camera and passing  to decode continuously,  this is the part i could not understand by looking at the code

03. is it ok if i uses these zxing android classes on my app directly.

shane

Lachezar Dobrev

unread,
Feb 16, 2011, 7:50:34 AM2/16/11
to zx...@googlegroups.com
My few cents:

01: You DON'T! Camera API does not handle well tilting the view.
I've tried a few times, all devices I tested return distorted and
wiggled preview contents in portrait mode. Instead handle the
orientation change using android.view.OrientationEventListener and
rotate the preview frames based on the orientation you get from there.

02: Use the camera preview. With the preview started attach a
Camera.PreviewCallback to the camera using
Camera.setOneShotPreviewCallback(). It will get a single preview
frame, that you feed to the ZXing Barcode Reader. After processing
request another one-shot-preview to avoid race conditions (preview
running faster than decoding).

03: Technically no, it's not a library, it's an application.
Licensewise I have no idea, it's probably not forbidden, subject
to the Apache License 2.0.

However, code vamping is not well looked upon by the application
developer(s). You'd rather use the code as reference how things are
done, and not blindly vamp it. Code vamping is considered an obnoxious
rip-off, and has had negative effect both on this project and the
vamping party. Still if you follow the license it's up to your
conscience.
I am not one of the developers. This is MY view based on
historical conversations on this list.

2011/2/16 samith premetilaka <sami...@gmail.com>:

Daniel Switkin

unread,
Feb 16, 2011, 10:34:35 AM2/16/11
to zx...@googlegroups.com
There's no problem with using code from the zxing/android tree in your own app - it's part of the bigger ZXing project, so it's all under the same license.

The only objection would be a complete clone of Barcode Scanner with an identical UI, which as Lachezar mentions would be pretty lame. But feel free to reuse all the threading code and state machine which does the decoding, which as you can see is somewhat tricky. No reason to reinvent the wheel.

Daniel

Rafael Timmerberg

unread,
Feb 17, 2011, 3:20:44 AM2/17/11
to zxing
Hi,
I'm trying myself to do this: build an Android Project using Zxings
Core as Libary. I looked well in the zxing/android tree how it is
done. So I'm stuck here:
http://groups.google.com/group/zxing/browse_thread/thread/cf83d1da07ed6c80
I get oneShotPreview Frame decode it and when I have a result I call
setResult(RESULT_OK, data) where data is an Intent filled with the
resulting Data, and the Barcode. It seems that I miss something
important, cause onActivityResult never gets triggered.
what am I missing? Im only using core and YUVLuminanceSource , without
any Threads, so decoding is done directly in my Activity.


On 16 Feb., 16:34, Daniel Switkin <dswit...@google.com> wrote:
> There's no problem with using code from the zxing/android tree in your own
> app - it's part of the bigger ZXing project, so it's all under the same
> license.
>
> The only objection would be a complete clone of Barcode Scanner with an
> identical UI, which as Lachezar mentions would be pretty lame. But feel free
> to reuse all the threading code and state machine which does the decoding,
> which as you can see is somewhat tricky. No reason to reinvent the wheel.
>
> Daniel
>
> On Wed, Feb 16, 2011 at 7:50 AM, Lachezar Dobrev <l.dob...@gmail.com> wrote:
> >  My few cents:
>
> >  01: You DON'T! Camera API does not handle well tilting the view.
> > I've tried a few times, all devices I tested return distorted and
> > wiggled preview contents in portrait mode. Instead handle the
> > orientation change using android.view.OrientationEventListener and
> > rotate the preview frames based on the orientation you get from there.
>
> >  02: Use the camera preview. With the preview started attach a
> > Camera.PreviewCallback to the camera using
> > Camera.setOneShotPreviewCallback(). It will get a single preview
> > frame, that you feed to the ZXing Barcode Reader. After processing
> > request another one-shot-preview to avoid race conditions (preview
> > running faster than decoding).
>
> >  03: Technically no, it's not a library, it's an application.
> >      Licensewise I have no idea, it's probably not forbidden, subject
> > to the Apache License 2.0.
>
> >      However, code vamping is not well looked upon by the application
> > developer(s). You'd rather use the code as reference how things are
> > done, and not blindly vamp it. Code vamping is considered an obnoxious
> > rip-off, and has had negative effect both on this project and the
> > vamping party. Still if you follow the license it's up to your
> > conscience.
> >      I am not one of the developers. This is MY view based on
> > historical conversations on this list.
>
> > 2011/2/16 samith premetilaka <samith...@gmail.com>:
> > > yep, i already try that, and got it work, need to know few questions on
> > that
> > > 01. how to support the camera  portrait view rather than lands cape view
> > > 02.how it handle the decoding, i mean capturing a image from camera and
> > > passing  to decode continuously,  this is the part i could
> > not understand by
> > > looking at the code
> > > 03. is it ok if i uses these zxing android classes on my app directly.
> > > shane
>
> > > On Tue, Feb 15, 2011 at 10:56 PM, Daniel Switkin <dswit...@google.com>
> > > wrote:
>
> > >> Have a look at how the Barcode Scanner app does this. The source is in
> > >> zxing/android.
>

simplecy

unread,
Feb 17, 2011, 7:25:16 AM2/17/11
to zxing
On Feb 17, 8:20 am, Rafael Timmerberg <raf...@googlemail.com> wrote:

> what am I missing? Im only using core and YUVLuminanceSource , without
> any Threads, so decoding is done directly in my Activity.

Coudl I suggest that it might be easier (in the early days) to just
write a simple app to get a barcode via intents BUT via your own
compiled version of Barcode Scanner.

You can then make small changes to a known working project and then
once you've got it working they way you want - then move on from there
to either copying the working code into your app or stripping out the
code you don't want/need in Barcode scanner and adding your own code
in.

regards
Simon

Rafael Timmerberg

unread,
Feb 17, 2011, 10:47:15 AM2/17/11
to zxing
Hi,
Yes you can suggest this, but I have done that already. I take
BarcodeScanner App 'as is' firing Intents to it. After that I reduce
it for my needs( i.e. removing the QR-Code-Generator,Intent recievers
in Manifest because I don't want that my app is used by another one,
or removed the 1D Barcode Support).
it is working in 'itself', I'm getting valid results in 'handleDecode'
method of CaptureActivity. If I want to pass this
com.google.zxing.Result I get by passing result-data to an Android
Bundle put this in an Intent as Extra and call
setResult(RESULT_FIRST_USER, extra); finish();
onActivityResult isn't getting fired. So my assumption was, that I
removed something that Android needs to call onActivityResult. This is
why I re-builded a simple Activity without any 'overhead' to see, if I
can pass results. As soon as I get an com.google.zxing.Result
onActivityResult isn't triggered anymore. Now I assume that it has
something to do with the camera, because I read in other forums about
issues with onActivityResult while Activitys are using the cam.

Here is my Code for review:

public class MainActivity extends Activity {

Button mButtonScan;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

mButtonScan = (Button)findViewById(R.id.main_btn_scan);
}

/**
* OnClick Event called from main.xml
* @param v View that called that onClickEvent
*/
public void btnCaptureClick(View v){
Intent intent = new Intent(this, CaptureActivity.class);
//Method to use in Emulator since it has no cam support.
// intent.setAction(Config.ACTION_CAPTURE_DEBUG);
// intent.setAction(Config.ACTION_CAPTURE_QR);
startActivityForResult(intent, Constants.REQUEST_CODE_CAPTURE);

}

/**
* callback for this Activity. Called when an Activity which was
started by
* this.startActivityForResult(intent, requestCode) sets its
result and calls finish()
*/
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
String foo = "foo";
switch (requestCode) {
case Constants.REQUEST_CODE_CAPTURE:
switch (resultCode) {
case RESULT_FIRST_USER:
Toast.makeText(this, data.getStringExtra(Config.SCAN_RESULT_TEXT),
Toast.LENGTH_LONG).show();
break;
case RESULT_CANCELED:

break;
default:
break;
}
break;

default:
super.onActivityResult(requestCode, resultCode, data);
break;
}

}
}

public class CaptureActivity extends Activity
implements ActivityCallback , SurfaceHolder.Callback, PreviewCallback{

private Preview mPreview;
private Camera mCam;
private SurfaceHolder mHolder;
// private final Activity mActivity;
private Size size;


protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.capture);

mPreview = (Preview)findViewById(R.id.capture_preview);
}

@Override
public void onValidDecodeResult(Result rawResult, Bitmap barcode) {
Intent intent = new Intent();
if (rawResult != null && barcode != null){

intent.putExtra(Config.SCAN_RESULT_TEXT, rawResult.getText());
intent.putExtra(Config.SCAN_RESULT_FORMAT,
rawResult.getBarcodeFormat().getName());
intent.putExtra(Config.SCAN_RESULT_BMP, barcode);
} else {
intent.putExtra(Config.SCAN_RESULT_TEXT, "foo");
intent.putExtra(Config.SCAN_RESULT_FORMAT, "bar");
intent.putExtra(Config.SCAN_RESULT_BMP, "barcode");
}
mPreview = null;
setResult(Activity.RESULT_FIRST_USER, intent);
finish();
}

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
MultiFormatReader reader = new MultiFormatReader();
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data,
size.width, size.height, 160, 60, 480, 360);
GlobalHistogramBinarizer binarizer = new
GlobalHistogramBinarizer(source);
BinaryBitmap bb = new BinaryBitmap(binarizer);
Result result = null;
try {
result = reader.decode(bb);
}catch (NotFoundException e) {
//do NOTHING cause e == null
}catch (Exception e){
e.printStackTrace();
} finally {
reader.reset();
}
if (result != null){
mCam.stopPreview();
releaseCameraResources();
onValidDecodeResult(result, source.renderCroppedGreyscaleBitmap());
} else {
camera.setOneShotPreviewCallback(this);
}
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCam = Camera.open();
mCam.setPreviewDisplay(mPreview.getHolder());
} catch (IOException e) {
releaseCameraResources();
e.printStackTrace();
}

}

private void releaseCameraResources(){
mCam.release();
mCam = null;
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int
width,
int height) {
//begin Preview
Camera.Parameters parameters = mCam.getParameters();

List<Size> sizes = parameters.getSupportedPreviewSizes();

size = getOptimalPreviewSize(sizes, width, height);
parameters.setPreviewSize(size.width, size.height);

mCam.setParameters(parameters);
mCam.startPreview();
mCam.setOneShotPreviewCallback(this);
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCam != null){
mCam.stopPreview();
releaseCameraResources();
}
}

private Size getOptimalPreviewSize(List<Size> sizes, int width, int
height){
final double ASPECT_TOLERANCE = 0.05;
double targetRatio = (double) width / height;
if (sizes == null) return null;

Size optimalSize = null;
double minDiff = Double.MAX_VALUE;

int targetHeight = height;

for (Size size: sizes){
double ratio = (double) size.width / size.height;
if(Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE){
continue;
}
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}

if (optimalSize == null){
//cannot find matching aspect-ratio
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}


}

You can see, that it is really simple. But still I don't have any idea
what to try next.

Rafael Timmerberg

unread,
Feb 18, 2011, 7:25:26 AM2/18/11
to zxing
I haved solved my Problem now.
It seems that the resulting BitMap is too large to pass it through an
Intent as Result.
if I remove the
intent.putExtra(Config.SCAN_RESULT_BMP,
barcode);
line, it works an onActivityResult is getting triggered with the data
Intent.

What you guys do, that your BitMap fits into an Intent?

Lachezar Dobrev

unread,
Feb 18, 2011, 8:11:07 AM2/18/11
to zx...@googlegroups.com
You don't!

See the API of the Media Store's method of taking a picture. If you
expect to get a result, than you're getting a small thumbnail.
Otherwise you need to supply the EXTRA_OUTPUT parameter.

Instead of getting the image returned from the call, do the
opposite: create a new WORLD_READABLE file, and pass its URI to the
scanner intent. The scanner intent checks if such a parameter has been
specified and saves the bitmap to the file pointed by the parameter.
Voilà!

2011/2/18 Rafael Timmerberg <raf...@googlemail.com>:

Reply all
Reply to author
Forward
0 new messages