Personnaliser la Vue de la Caméra pour Android à l'aide de zbar
Je suis nouveau dans le développement android. Mon application doit activer l'appareil photo pour scanner un QR code et décode une chaîne. Cela fonctionne bien, mais j'ai une autre exigence: pour présenter la vue de la caméra dans un cadre et avec un logo dans l'un des coins. Je n'ai pas trouvé une API appropriée dans zbar sdk pour faire le cadre et fixez le logo. C'est mon code:
ZBarScannerActivity.java:
package com.myCompany.android;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
public class ZBarScannerActivity extends Activity implements Camera.PreviewCallback, ZBarConstants {
private static final String TAG = "ZBarScannerActivity";
private CameraPreview mPreview;
private Camera mCamera;
private ImageScanner mScanner;
private Handler mAutoFocusHandler;
private boolean mPreviewing = true;
static {
System.loadLibrary("iconv");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Hide the window title.
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
mAutoFocusHandler = new Handler();
//Create and configure the ImageScanner;
setupScanner();
//Create a RelativeLayout container that will hold a SurfaceView,
//and set it as the content of our activity.
mPreview = new CameraPreview(this, this, autoFocusCB);
setContentView(mPreview);
}
public void setupScanner() {
mScanner = new ImageScanner();
mScanner.setConfig(0, Config.X_DENSITY, 3);
mScanner.setConfig(0, Config.Y_DENSITY, 3);
int[] symbols = getIntent().getIntArrayExtra(SCAN_MODES);
if (symbols != null) {
mScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
for (int symbol : symbols) {
mScanner.setConfig(symbol, Config.ENABLE, 1);
}
//test customization
}
}
@Override
protected void onResume() {
super.onResume();
//Open the default i.e. the first rear facing camera.
mCamera = Camera.open();
mPreviewing = true;
mPreview.setCamera(mCamera);
}
@Override
protected void onPause() {
super.onPause();
//Because the Camera object is a shared resource, it's very
//important to release it when the activity is paused.
if (mCamera != null) {
mPreview.setCamera(null);
mCamera.cancelAutoFocus();
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mPreviewing = false;
mCamera = null;
}
}
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = parameters.getPreviewSize();
Image barcode = new Image(size.width, size.height, "Y800");
barcode.setData(data);
int result = mScanner.scanImage(barcode);
if (result != 0) {
mCamera.cancelAutoFocus();
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mPreviewing = false;
SymbolSet syms = mScanner.getResults();
for (Symbol sym : syms) {
String symData = sym.getData();
if (!TextUtils.isEmpty(symData)) {
Intent dataIntent = new Intent();
dataIntent.putExtra(SCAN_RESULT, symData);
dataIntent.putExtra(SCAN_RESULT_TYPE, sym.getType());
setResult(Activity.RESULT_OK, dataIntent);
finish();
break;
}
}
}
}
private Runnable doAutoFocus = new Runnable() {
public void run() {
if(mCamera != null && mPreviewing) {
mCamera.autoFocus(autoFocusCB);
}
}
};
//Mimic continuous auto-focusing
Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
}
};
public void launchQRScanner(View v) {
if (isCameraAvailable()) {
//Toast.makeText(this, "Analyzing Image", Toast.LENGTH_LONG).show();
Intent intent = new Intent(this, ZBarScannerActivity.class);
intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{Symbol.QRCODE});
startActivityForResult(intent, ZBAR_QR_SCANNER_REQUEST);
} else {
Toast.makeText(this, "Camera Unavailable", Toast.LENGTH_SHORT).show();
}
}
public boolean isCameraAvailable() {
PackageManager pm = getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.activity_qrimport_token, menu);
return true;
}
/* @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch (requestCode) {
case ZBAR_SCANNER_REQUEST:
Toast.makeText(this, data.getStringExtra(ZBarConstants.SCAN_RESULT), Toast.LENGTH_LONG).show();
break;
case ZBAR_QR_SCANNER_REQUEST:
playSound();
if (resultCode == RESULT_OK) {
Toast.makeText(this, data.getStringExtra(ZBarConstants.SCAN_RESULT), Toast.LENGTH_LONG).show();
Toast.makeText(this, "Scan Result = " + data.getStringExtra(ZBarConstants.SCAN_RESULT), Toast.LENGTH_SHORT).show();
//put whatever you want to do with the code here
//TextView tv = new TextView(this);
//tv.setText(data.getStringExtra(ZBarConstants.SCAN_RESULT));
Log.d("Data",""+data.getStringExtra(ZBarConstants.SCAN_RESULT));
//setContentView(tv);
}
break;
}
}*/
/*private void playSound()
{
MediaPlayer mp = MediaPlayer.create(getBaseContext(), R.raw.camera_shutter);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener()
{
@Override
public void onCompletion(MediaPlayer mp)
{
mp.release();
}
});
}*/
}
CameraPreview.java:
package com.myCompany.android;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import java.io.IOException;
import java.util.List;
class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "CameraPreview";
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
PreviewCallback mPreviewCallback;
AutoFocusCallback mAutoFocusCallback;
CameraPreview(Context context, PreviewCallback previewCallback, AutoFocusCallback autoFocusCb) {
super(context);
mPreviewCallback = previewCallback;
mAutoFocusCallback = autoFocusCb;
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
//Install a SurfaceHolder.Callback so we get notified when the
//underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
requestLayout();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//We purposely disregard child measurements because act as a
//wrapper to a SurfaceView that centers the camera preview instead
//of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 0) {
final View child = getChildAt(0);
final int width = r - l;
final int height = b - t;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null) {
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
}
//Center the child SurfaceView within the parent.
if (width * previewHeight > height * previewWidth) {
final int scaledChildWidth = previewWidth * height / previewHeight;
child.layout((width - scaledChildWidth) / 2, 0,
(width + scaledChildWidth) / 2, height);
} else {
final int scaledChildHeight = previewHeight * width / previewWidth;
child.layout(0, (height - scaledChildHeight) / 2,
width, (height + scaledChildHeight) / 2);
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
//The Surface has been created, acquire the camera and tell it where
//to draw.
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
//Surface will be destroyed when we return, so stop the preview.
if (mCamera != null) {
mCamera.cancelAutoFocus();
mCamera.stopPreview();
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
//Try to find an size match aspect ratio and size
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);
}
}
//Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
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;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (holder.getSurface() == null){
//preview surface does not exist
return;
}
//Now that the size is known, set up the camera parameters and begin
//the preview.
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
mCamera.setPreviewCallback(mPreviewCallback);
mCamera.startPreview();
mCamera.autoFocus(mAutoFocusCallback);
}
}
Comment personnaliser la vue de la caméra pour android? J'ai vu des solutions proposées pour l'iPhone, mais zbar API pour Android est totalement différent et beaucoup plus petit. Je serais apprécié pour avoir une idée/astuce...
OriginalL'auteur user2336535 | 2013-05-01
Annuler la réponse
Vous devez vous connecter pour publier un commentaire.
De présenter une image dans cameraview, ajouter une imageview dans le framelayout(camerapreview) main.xml .
Utiliser ce code pour faire la trame(imageview) visible. Le cadre(imageview) est déjà présent dans le framelayout dans main.xml nous avons besoin de l'enlever en premier.
Pour analyser les camerapreview seulement à partir de votre image, vous devez utiliser setCrop().Ajuster la taille de camerapreview selon le cadre.
Cela a fonctionné pour moi et j'espère qu'il permettra de résoudre votre problème. Veuillez m'excuser pour mes fautes grammaticales. Merci.
src
pourImageView
, bro?android:src="@drawable/overlay"
Je l'ai fait à l'aide de photoshop. Un simple png dans une petite boîte transparente est coupé à l'opacité de la ligne centrale. Il est similaire à ce que nous voyons en pré-faites scanner de code à barres.
Mais avec une résolution d'écran différente, pourrait-il remplir tout l'écran ou avoir de l'espace à gauche et à droite
fondamentalement, vous fera différentes superpositions de différentes résolutions d'écran. Aussi garder la largeur et la hauteur que match_parent vous aideront à remplir la totalité de l'écran. J'espère que cette aide.
OriginalL'auteur Victor
Je pense que c'est plus facile que vous avez pensé:
Dans l'exemple de code fourni par le ZBar gars, il y a ces deux lignes dans le onCreate() méthode:
qui sont responsables de l'ajout de la "aperçu" à la camerPreview Mise en page.
Trouver les lignes mentionnées dans votre code, créer un nouveau ImageView et également l'ajouter à la aperçu-Mise en page comme ceci:
Ajuster la taille et la position de votre point de vue v et vous avez terminé!
Vous pouvez poster votre Activité?
OriginalL'auteur Elias
J'ai connu le même problème. La solution est tout simplement d'ajouter le CameraPrevie dans votre xml à l'intérieur d'un frameLayout, et juste après que l'image que vous voulez mettre sur le dessus de l'est.
par exemple.:
et de le remplir de votre activité:
OriginalL'auteur MonkeyDroid