I'm developing an application where I read some barcode. In a first step I had a big SurfaceView where I can see well the camera preview, but now I would set the dimensions of Surfaceview like the dimensions of barcode but I have bad camera visualization (it is too small). Can someone help me to stretch camera preview? Thanks
Here manage detector and surfaceview:
public class LettoreBarcode extends Fragment {
View view;
SurfaceView surfaceView;
Handler handler;
private BarcodeDetector detector;
private CameraSource cameraSource;
private TextView code;
SparseArray<Barcode> items;
private static Button btnBack;
String barcode = "" ;
SparseArray<Articoli> groups = new SparseArray<Articoli>();
Context _context = null;
ProductsAdapter.ViewHolder _ViewHolder = null;
public LettoreBarcode(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_barcode_scanner, container, false);
surfaceView = (SurfaceView) view.findViewById(R.id.surfaceView);
detector = new BarcodeDetector.Builder(getActivity()).setBarcodeFormats(Barcode.ALL_FORMATS).build();
final Dialog d = new Dialog(getActivity());
btnBack = (Button) view.findViewById(R.id.btnBack);
handler = new Handler();
if(!detector.isOperational()){
Toast.makeText(getActivity(), "Detector non attivabile", Toast.LENGTH_LONG).show();
}
cameraSource = new CameraSource.Builder(getActivity(), detector).setAutoFocusEnabled(true).build();
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
AttivaCamera();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
detector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
items = detections.getDetectedItems();
if (items.size() > 0){
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (items.valueAt(0) != null){
//do something
handler.postDelayed(new Runnable() {
#Override
public void run() {
DisattivaCamera();
}
},10); //1000
}else
{
d.setContentView(R.layout.dialog_barcode_assente);
d.setTitle("Scanner");
d.setCancelable(true);
d.show();
DisattivaCamera();
}
}
});
}
}
});
btnBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getActivity().onBackPressed();
}
});
return view;
}
private void AttivaCamera()
{
try{
cameraSource.start(surfaceView.getHolder());
}catch(IOException e){
Toast.makeText(getActivity(), "Errore nell'avvio della fotocamera", Toast.LENGTH_LONG).show();
}
}
private void DisattivaCamera()
{
cameraSource.stop();
}
}
It is how I visualize camera with small surfaceview:
https://i.stack.imgur.com/TMunJ.png
I'm new in android development so I'm sorry if could be a lot of mistake in the code.
Sorry for my english also..
Thanks you guys!
In order to display only part of the camera input, i.e. to crop it on the screen, you need a surface view that has dimensions that fit the camera frame aspect ratio, and overlay it with some nontransparent views to leave only part of it visible. Don't put the SurfaeView inside scrolling layout:
So, instead of
<SurfaceView width: match_parent height: 400dp />
you need e.g. FrameLayout as explained here: Is it possible to crop camera preview?
This will not change the frame that arrives to the barcode detector. But this should not worry you; the detector will handle the uncropped image correctly.
Related
I have this code and Iam using the Barcode Google API Vision. When i open the Fragment and rotate the device many times 6 or more, i see in the Dump Heap that many instances remain in memory (see pic.) Even after i do a forced Garbage Collection they stay the same. In my code below i dont see any memory leaks.
Image is after GC
The weird part is that some devices only show 1 instance of the
classes after GC which is normal.
Emulator API 27 : NO MEMORY LEAKS
Samsung j500FN : NO MEMORY LEAKS
Xiaomi mi8 : Memory Leak
Galaxy Tablet E : Memory Leak
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment sf = getSupportFragmentManager().findFragmentByTag("Scanner");
transaction.add(R.id.root, new Scanner(), "Scanner");
transaction.addToBackStack(null);
transaction.commit();
}
});
}
Scanner
public class Scanner extends Fragment{
public SurfaceView cameraView;
public BarcodeDetector barcode;
public CameraSource cameraSource;
private SurfaceHolder.Callback cameraCallback;
private ActivityScanBinding mbinding;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("ActivityScan","onCreate");
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.d("ActivityScan","onCreateView");
mbinding = DataBindingUtil.inflate(inflater, R.layout.activity_scan, container, false);
mbinding.getRoot().setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
cameraView = mbinding.getRoot().findViewById(R.id.cameraView);
return mbinding.getRoot();
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Scan();
}
#Override
public void onDestroy() {
Log.d("ActivityScan","Destroyed");
if(barcode!=null) {
barcode.release();
Log.d("barcode","Released");
}
if(cameraSource!=null) {
cameraSource.release();
Log.d("cameraSource ","Released");
}
if(cameraView!=null) {
removeCameraViewCallback();
}
super.onDestroy();
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
}
public void Scan(){
cameraView.setZOrderMediaOverlay(true);
barcode = new BarcodeDetector.Builder(getActivity())
.setBarcodeFormats(Barcode.QR_CODE)
.build();
if(!barcode.isOperational()){
return;
}
cameraSource = new CameraSource.Builder(getActivity(), barcode)
.setFacing(CameraSource.CAMERA_FACING_FRONT)
.setRequestedFps(24)
.setAutoFocusEnabled(true)
.setRequestedPreviewSize(1920,1080)
.build();
cameraCallback = new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
if(ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
cameraSource.start(cameraView.getHolder());
}
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
cameraSource.stop();
}
};
cameraView.getHolder().addCallback(cameraCallback);
barcode.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){
}
}
});
}
public void removeCameraViewCallback(){
cameraView.getHolder().removeCallback(cameraCallback);
}
}
Please see my code and let me know if there is a memory leak.
Leak Canary shows this:
Why you're releasing barcode and cameraSource in onDestroy method?
According to this onDestroy() method could be skipped and not called. Maybe onStop() is more proper place to release resources? And acquire them in onStart() respectively.
#Override
public void onStop() {
Log.d("ActivityScan","Destroyed");
if(barcode!=null) {
barcode.release();
Log.d("barcode","Released");
}
if(cameraSource!=null) {
cameraSource.release();
Log.d("cameraSource ","Released");
}
if(cameraView!=null) {
removeCameraViewCallback();
}
super.onStop();
}
Also, do not pass Activity when creating BarcodeDetector and CameraSource, and pass ApplicationContext if possible.
I am new to android and currently working on an app which uses the camera API. I am having trouble with the implementation of Zoom function in the app. I am using Camera kit API to make the app and Camera-kit Api does not provide support for zoom controls. Please help me with the code required. I am unable to figure it out since a week. I need to implement Zoom to the camera Preview.
this is my Code.
public class MicroscopeAcitvity extends AppCompatActivity implements View.OnClickListener {
CameraView cameraView;
ImageButton cameraTakePic;
ImageButton buttonFlash;
Camera mCamera; //= Camera.open();
Camera.Parameters params;
TextView T1,T2;
int counter = 0;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_microscope_acitvity);
cameraView = (CameraView) findViewById(R.id.camera);
cameraTakePic = (ImageButton) findViewById(R.id.button_take_picture);
cameraTakePic.setOnClickListener(this);
buttonFlash = (ImageButton) findViewById(R.id.button_Flash);
buttonFlash.setOnClickListener(this);
T1 = (TextView) findViewById(R.id.flash_text1);
T1.setOnClickListener(this);
//T1.setVisibility(View.GONE);
T2 = (TextView) findViewById(R.id.flash_text2);
T2.setOnClickListener(this);
//T2.setVisibility(View.GONE);
cameraView.setCameraListener(new CameraListener() {
#Override
public void onPictureTaken(byte[] picture) {
super.onPictureTaken(picture);
// Create a bitmap
Bitmap result = BitmapFactory.decodeByteArray(picture, 0, picture.length);
}
});
cameraView.setFocus(CameraKit.Constants.FOCUS_TAP);
}
#Override
protected void onResume() {
super.onResume();
cameraView.start();
}
#Override
protected void onPause() {
cameraView.stop();
super.onPause();
}
#Override
public void onClick(View v) {
int id;
id = v.getId();
if(id == R.id.button_take_picture){
cameraView.captureImage();
}
if(id == R.id.button_Flash){
if(counter % 2 != 0){
T1.setVisibility(View.VISIBLE);
T2.setVisibility(View.VISIBLE);
counter = counter+1;
}
else{
T1.setVisibility(View.GONE);
T2.setVisibility(View.GONE);
counter = counter+1;
}
}
if(id == R.id.flash_text1){
T1.setTextColor(Color.RED);
T2.setTextColor(Color.DKGRAY);
cameraView.setFlash(CameraKit.Constants.FLASH_ON);
}
if (id == R.id.flash_text2){
T2.setTextColor(Color.RED);
T1.setTextColor(Color.DKGRAY);
cameraView.setFlash(CameraKit.Constants.FLASH_OFF);
}
}
}
If you want to zoom by pinch you have to implement a ScaleGestureDetector.SimpleOnScaleGestureListener
To set the zoom you simply have to change the camera parameters
Camera.Parameters parameters = camera.getParameters();
parameters.setZoom(zoomFactorValue);
camera.setParameters(parameters);
if you have some time you can code the rest yourself or look up how he did it
http://opencamera.sourceforge.net/
He uses pinch zoom on a surfaceview (but his code is not efficient and really ugly, very hard to understand on some points)
I am developing an android application in which open camera in a fragment. Whenever Camera is opened for the FIRST TIME. It loads with a small jerk of 1 second approximately. Making screen black. How to prevent screen from turning black for that second completely.
Detailed Explanation:
When we open camera in Facebook messenger or even try to open camera normally in your phone. It takes one second to open and meanwhile screens turns black. The same thing is happening. Can this be prevented? Any how? your reply will be highly appreciated Please guys.
Below Is the working code with same problem as described above.
public class scan extends Fragment implements ZXingScannerView.ResultHandler{
private ZXingScannerView zXingScannerView;
private SurfaceView mySurfaceView;
private QREader qrEader;
private Camera mCamera;
private CameraPreview mPreview;
private String m_Text="";
private String number="";
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public scan() {
}
#Override
public void handleResult(Result rawResult) {
Log.e("handler", rawResult.getText());
Log.e("handler", rawResult.getBarcodeFormat().toString());
AlertDialog.Builder builder = new AlertDialog.Builder(this.getActivity());
builder.setTitle("Scan Result");
builder.setMessage(rawResult.getText());
number = rawResult.getText().substring(rawResult.getText().length() - 13);
//
final EditText input = new EditText(this.getActivity());
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
builder.setView(input);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
m_Text = input.getText().toString();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.setNegativeButton("NO",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog alert1 = builder.create();
alert1.show();
zXingScannerView.resumeCameraPreview(this);
}
public static scan newInstance(String param1, String param2) {
scan fragment = new scan();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
if(checkCameraHardware(getActivity().getApplicationContext())) {
zXingScannerView = new ZXingScannerView(this.getActivity().getApplicationContext());
zXingScannerView.setResultHandler(this);
zXingScannerView.startCamera();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_scan, container, false);
FrameLayout preview =(FrameLayout)view.findViewById(R.id.camera_preview);
preview.addView(zXingScannerView);
return view;
}
#Override
public void onPause()
{
super.onPause();
zXingScannerView.stopCamera();
}
#Override
public void onResume() {
super.onResume();
zXingScannerView.setResultHandler(this); // Register ourselves as a handler for scan results.
zXingScannerView.startCamera(); // Start camera on resume
}
/** Check if this device has a camera */
public boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
if (mCamera!= null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
I see that you use the deprecated Camera API. If you want your app to perform the best on devices with Lollipop or higher, you should switch to the new camera2 API. Please see the discussion here: Android camera android.hardware.Camera deprecated.
The new API can improve performance significantly, but if you are stuck with the old one, don't despair. If you are not using the latest version of ZXingScannerView, update this class to open the camera in a background thread. This change improved startup significantly.
If your fragment is part of a ViewPager (like camera preview within viewpager), make sure that the camera preview is started before the pager brings the scan fragment to screen.
In other scenarios, it is preferable to go for a variation of splash screen paradigm, which has it pros and cons. You can show for a short while another non-black view on top of the camera preview surface, or show a predefined texture if you use OpenGL preview.
Try this below code to open camera and click picture as it works for me.
public class CameraImage extends Fragment {
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 1888;
Button button;
ImageView imageView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.camera_image,
container, false);
button = (Button) rootView.findViewById(R.id.button);
imageView = (ImageView) rootView.findViewById(R.id.imageview);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,
CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
});
return rootView;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
Bitmap bmp = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
// convert byte array to Bitmap
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0,
byteArray.length);
imageView.setImageBitmap(bitmap);
}
}
}
}
Hope it will work for you.
I am trying to blur a LinearLayout in Service class.But when I try to blur the layout it blurs only the contents inside the layout.I want layout to be completely blurred so that behind that everything will look blurrish.
here is my code:
public class Exa extends Service {
LinearLayout LLayout,inner;
WindowManager windowManager;
RenderScript mRS;
Button button;
ImageView imageView;
ScriptIntrinsicBlur script;
Allocation allocOriginalScreenshot,allocBlurred;
TextureView textureViewBlurred;
private static final String TAG="MainActivity";
#Override
public void onCreate(){
final LayoutInflater inflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//LLayout=(RelativeLayout)inflater.inflate(R.layout.activity_main,null);
LLayout=(LinearLayout)inflater.inflate(R.layout.blur_layout,null);
inner=(LinearLayout)LLayout.findViewById(R.id.innerL);
button=(Button)inner.findViewById(R.id.blurButton);
imageView=(ImageView)inner.findViewById(R.id.imageView2);
example();
windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams windowp=new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);
windowManager.addView(LLayout,windowp);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
blurView(inner);
}
});
}
////all these code helps to give blurring effect
private void example() {
mRS=RenderScript.create(this);
script=ScriptIntrinsicBlur.create(mRS, Element.RGBA_8888(mRS));
script.setRadius(5);
}
Bitmap getViewScreenshot(View v){
v.setDrawingCacheEnabled(true);
Bitmap b=Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false);
return b;
}
void replaceView(View originalView,View newView){
originalView.setTag(newView);
newView.setLayoutParams(new FrameLayout.LayoutParams(originalView.getLayoutParams()));
ViewGroup parent=(ViewGroup)originalView.getParent();
int index=parent.indexOfChild(originalView);
parent.removeView(originalView);
parent.addView(newView,index);
}
void restoreView(View v){
Log.i("hii","unblurring view");
View otherView=(View)v.getTag();
if (otherView!=null&&otherView.getParent()!=null){
replaceView(otherView,v);
}
else if (v!=null&&v.getParent()!=null){
replaceView(v,otherView);
}
}
void blurView(View v){
Bitmap viewScreenshot=getViewScreenshot(v);
if(allocOriginalScreenshot!=null&&(allocOriginalScreenshot.getType().getX()!=viewScreenshot.getWidth()||allocOriginalScreenshot.getType().getY()!=viewScreenshot.getHeight())){
allocOriginalScreenshot.destroy();
allocBlurred.destroy();
textureViewBlurred=null;
allocOriginalScreenshot=null;
allocBlurred=null;
}
if(allocOriginalScreenshot==null){
allocOriginalScreenshot=Allocation.createFromBitmap(mRS,viewScreenshot);
allocBlurred=Allocation.createTyped(mRS,allocOriginalScreenshot.getType(),Allocation.USAGE_SCRIPT|Allocation.USAGE_IO_OUTPUT);
textureViewBlurred=new TextureView(this);
textureViewBlurred.setOpaque(false);
textureViewBlurred.setSurfaceTextureListener(surfaceTextureListener);
}
else {
allocOriginalScreenshot.copyFrom(viewScreenshot);
}
replaceView(v,textureViewBlurred);
}
void unblur(View v){
restoreView(v);
}
void executeBlur(){
Log.d(TAG,"Executing blur");
script.setInput(allocOriginalScreenshot);
script.forEach(allocBlurred);
allocBlurred.ioSend();
}
TextureView.SurfaceTextureListener surfaceTextureListener=new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
allocBlurred.setSurface(new Surface(surface));
executeBlur();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I am trying to implement camera features on my application. Since it's my first time doing so, I'm running a little issue with my camera preview.
My current layout looks like this:
Which is producing a preview like this:
However I want something like this:
And here is the code for my camera:
public class FragmentPhoto extends Fragment implements TextureView.SurfaceTextureListener {
private Camera camera;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_photo, container, false);
final TextureView textureView = (TextureView) view.findViewById(R.id.photo_view);
textureView.setSurfaceTextureListener(this);
return view;
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
try {
camera = Camera.open();
camera.setDisplayOrientation(90);
camera.setPreviewTexture(surface);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
camera.stopPreview();
camera.release();
return true;
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, the Camera does all the work for us
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Update your view here!
}
}
Is there any way to crop the camera? To not make the preview this chubby? What is the best aproach to do this?