I came across a weird bug in my app.
I'm using a SurfaceView to allow the user to scan a QR code.
Sometimes it works as expected, but sometimes the SurfaceView remains black.
I've checked other posts, but unfortunately didn't find any relevant one.
Here is a code snippet:
//Called when QR scan is needed
private void tryToScan(){
final BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.QR_CODE).build();
final CameraSource cameraSource = new CameraSource.Builder(this, barcodeDetector).setRequestedPreviewSize(256, 256).build();
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> codes = detections.getDetectedItems();
if (codes.size() > 0) {//if codes detected
sendQr(codes.valueAt(0).displayValue);//send it
}
}
});
//Adds SurfaceHolder.Callback to SurfaceHolder of SurfaceView by id R.id.scanQr (valid id)
((SurfaceView)findViewById(R.id.scanQr)).getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
//Sometimes starts successfully but sometimes stays black
cameraSource.start(holder);
} catch (IOException e) {
e.printStackTrace();
}catch (SecurityException e){
askCameraPermission();
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
public void surfaceDestroyed(SurfaceHolder holder) {
cameraSource.stop();
}
});
}
Related
This is a part of QR Code scanner app. In the very beginning of the app it asks for camera permission, when i click to allow, app doesn't respond. but from second time, app works correctly. I think the error may be in checking permission. Please help me to find the mistake.
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
cameraSource.start(surfaceView.getHolder());
} else {
ActivityCompat.requestPermissions(MainActivity.this, new
String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
cameraSource.stop();
}
});
I`m trying to create bar code reader for my app, and it works fine, but the problem is when I keep focusing on QR-Code, it continues to read and never stops!!!
How can I make this happen only once?
In this code, it continues to "Toast" until I close the app, and when I use Intent for for closing the current activity and open another activity, the activity opens several times!!!
Here is the code:
public class BarcodeCaptureActivity extends AppCompatActivity {
private SurfaceView camera_preview;
TextView text;
BarcodeDetector barcodeDetector;
CameraSource cameraSource;
final int requestCameraPermissionID = 1001;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_barcode_capture);
camera_preview = (SurfaceView) findViewById(R.id.camera_preview);
text = (TextView) findViewById(R.id.text);
barcodeDetector = new BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.QR_CODE).build();
cameraSource = new CameraSource.Builder(this, barcodeDetector).setRequestedPreviewSize(640, 480).build();
camera_preview.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(BarcodeCaptureActivity.this, new String[]{Manifest.permission.CAMERA},requestCameraPermissionID);
return;
}
try {
cameraSource.start(camera_preview.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
cameraSource.stop();
}
});
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> qrcode = detections.getDetectedItems();
if (qrcode.size() != 0){
text.post(new Runnable() {
#Override
public void run() {
Vibrator vibrator = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000);
text.setText(qrcode.valueAt(0).displayValue);
String title = text.getText().toString();
Toast.makeText(BarcodeCaptureActivity.this, "" + title, Toast.LENGTH_SHORT).show();
finish();
}
});
}
}
});
}
Thank for any help...
UPDATE
Problem solved with adding onDestroy and onPause methods...
#Override
protected void onPause() {
super.onPause();
cameraSource.stop();
}
#Override
protected void onDestroy() {
super.onDestroy();
cameraSource.stop();
}
I am using the com.google.android.gms.vision dependency to scan a QR-code.
The problem I am facing is that it keeps scanning the QR-code again and again. I want it to scan only once.
Here is my code :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final SurfaceView cameraView = (SurfaceView) findViewById(R.id.camera_view);
final TextView barcodeInfo = (TextView) findViewById(R.id.code_info);
barcodeDetector =
new BarcodeDetector.Builder(this)
.setBarcodeFormats(Barcode.QR_CODE)
.build();
cameraSource = new CameraSource
.Builder(this, barcodeDetector)
.setAutoFocusEnabled(true)
.setRequestedPreviewSize(640, 640)
.build();
cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (ActivityCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
cameraSource.start(cameraView.getHolder());
} catch (IOException ie) {
Log.e("CAMERA SOURCE", ie.getMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
cameraSource.stop();
}
});
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> barcodes = detections.getDetectedItems();
if (barcodes.size() != 0) {
barcodeInfo.post(new Runnable() { // Use the post method of the TextView
public void run() {
barcodeInfo.setText( // Update the TextView
barcodes.valueAt(0).displayValue
);
QRData = barcodeInfo.getText().toString().trim();
Log.d("TAG", barcodeInfo.getText().toString().trim());
}
});
}
}
});
Just set result and call finish when your scan is completed in that activity. After that you need to catch result in parent activity (onActivityResult).
PS. You need to start QRScanner activity with startActivityForResult.
Edit: If QRScan is the same activity stop camera. And maybe you need to hide that surface.
Cheers :)
I have searched some solutions with my problem and sure there are many related issues regarding it but nothing solves my concern.
I am receiving a runtime exception : takepicture failed:native_autofocus..etc.
I tried to take picture from camera using autofocus and I can't seem to understand what could have caused the error.
Here is my code.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mholder;
private Camera mcamera;
private Handler handler = new Handler();
public CameraPreview(Context context, Camera camera) {
super(context);
this.mcamera = camera;
mholder = getHolder();
mholder.addCallback(this);
mholder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (mholder.getSurface() == null) {
return;
}
try {
mcamera.stopPreview();
} catch (Exception e) {
Log.d("surfaceChanged", e.toString());
}
try {
mcamera.setPreviewDisplay(holder);
mcamera.startPreview();
} catch (IOException e) {
Log.d("surfaceChanged--->surfaceCreated", e.toString());
}
}
I think somethings is lacking in my runnable code, I tried to omit the runnable and execute autofocus once, it removed the runtime error. Did I missed to reinitialize something in this part?
private void autoFocus(Camera mcamera){
final Camera cam=mcamera;
handler.postDelayed(new Runnable() {
#Override
public void run() {
cam.autoFocus(autoFocusCallback);
handler.postDelayed(this, 1500L);
}
}, 1500L);
}
AutoFocusCallback autoFocusCallback=new AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
camera.takePicture(null, null, mPicture);
}
};
private PictureCallback mPicture=new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//do something
}
};
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mcamera.setPreviewDisplay(holder);
mcamera.startPreview();
mcamera.autoFocus(autoFocusCallback);
} catch (IOException e) {
Log.d("surfaceCreated", e.toString());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
You didn't mention it but be sure to include the permission in your manifest.
< uses-feature android:name="android.hardware.camera.autofocus" />
Have a look here
or here
and you are calling autofocus on surfacecreated ,
It should be called on surface changed
I am creating a video player using MediaPlayer class in android. I set a SurfaceHolder in MediaPlayer.setDisplay(), it shows video successfully but when this activity resumed again then no video is diplayed. So what is wrong ??
The Code is:
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
player = new MediaPlayer();
surface = (SurfaceView)findViewById(R.id.surface);
surface.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
VideoDemo.this.startActivity(new Intent(VideoDemo.this, AnotherActivity.class));//Video not displayed when return from this activity by pressing back button
}
});
holder = surface.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
try
{
String songName = Environment.getExternalStorageDirectory().toString()+File.separator+"1.mp4";
player.setDataSource(songName);
player.prepare();
player.start();
}
catch (Exception e)
{
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
player.setDisplay(holder);
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
Log.d(TAG, "surfaceCreated() is called ************ holder.getSurface() = "+holder.getSurface());
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
Log.d(TAG, "surfaceDestroyed() is called ************");
}
I have initialized media player again and now its working fine