libGDX using android device camera - java

I am trying to implement a barcode scanning function in my Libgdx project.
i have tried to follow : https://github.com/libgdx/libgdx/wiki/Integrating-libgdx-and-the-device-camera
but it seems to be outdated.
Does anyone have a clue on how to get the device camera working in libgdx?

I have a project that implemented the android camera. Heres the important code:
Manifest
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
AndroidDeviceCameraController (New Class)
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Pixmap;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
public class AndroidDeviceCameraController implements DeviceCameraControl,
Camera.PictureCallback, Camera.AutoFocusCallback {
private static final int ONE_SECOND_IN_MILI = 1000;
private final MainActivity activity;
private CameraSurface cameraSurface;
private byte[] pictureData;
FileHandle jpgfile;
Pixmap pixmap;
FileHandle jpgfile2;
Pixmap pixmap2;
public AndroidDeviceCameraController(MainActivity activity) {
this.activity = activity;
}
#Override
public synchronized void prepareCamera() {
activity.setFixedSize(960,640);
if (cameraSurface == null) {
cameraSurface = new CameraSurface(activity);
}
activity.addContentView( cameraSurface, new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT ) );
}
#Override
public synchronized void startPreview() {
setCameraParametersForPicture(cameraSurface.getCamera());
if (cameraSurface != null && cameraSurface.getCamera() != null) {
cameraSurface.getCamera().startPreview();
}
}
#Override
public synchronized void stopPreview() {
if (cameraSurface != null) {
ViewParent parentView = cameraSurface.getParent();
if (parentView instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) parentView;
viewGroup.removeView(cameraSurface);
}
if (cameraSurface.getCamera() != null) {
cameraSurface.getCamera().stopPreview();
}
}
activity.restoreFixedSize();
}
public void setCameraParametersForPicture(Camera camera) {
camera.setDisplayOrientation(90);
Camera.Parameters p = camera.getParameters();
List<Camera.Size> supportedSizes = p.getSupportedPictureSizes();
int maxSupportedWidth = -1;
int maxSupportedHeight = -1;
for (Camera.Size size : supportedSizes) {
if (size.width > maxSupportedWidth) {
maxSupportedWidth = size.width;
maxSupportedHeight = size.height;
}
}
p.setPictureSize(maxSupportedWidth, maxSupportedHeight);
p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
camera.setParameters( p );
}
#Override
public synchronized void takePicture() {
setCameraParametersForPicture(cameraSurface.getCamera());
cameraSurface.getCamera().autoFocus(this);
}
#Override
public synchronized void onAutoFocus(boolean success, Camera camera) {
if (success) {
if (camera != null) {
camera.startPreview();
ShutterCallback shutterCallback = new ShutterCallback() {
#Override
public void onShutter() {
}
};
camera.takePicture(shutterCallback, null, null, this);
}
}
}
#Override
public synchronized void onPictureTaken(byte[] pictureData, Camera camera) {
main.makefoto = true;
this.pictureData = pictureData;
}
#Override
public synchronized byte[] getPictureData() {
return pictureData;
}
#Override
public void prepareCameraAsync() {
Runnable r = new Runnable() {
public void run() {
prepareCamera();
}
};
activity.post(r);
}
#Override
public synchronized void startPreviewAsync() {
Runnable r = new Runnable() {
public void run() {
startPreview();
}
};
activity.post(r);
}
#Override
public synchronized void stopPreviewAsync() {
Runnable r = new Runnable() {
public void run() {
stopPreview();
}
};
activity.post(r);
}
#Override
public synchronized byte[] takePictureAsync(long timeout) {
timeout *= ONE_SECOND_IN_MILI;
pictureData = null;
Runnable r = new Runnable() {
public void run() {
takePicture();
}
};
activity.post(r);
while (pictureData == null && timeout > 0) {
try {
Thread.sleep(ONE_SECOND_IN_MILI);
timeout -= ONE_SECOND_IN_MILI;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (pictureData == null) {
cameraSurface.getCamera().cancelAutoFocus();
}
return pictureData;
}
public void convert() {
new Thread(new Runnable() {
#Override
public void run() {
FileOutputStream fos;
int x=0,y=0;
int xl=0,yl=0;
try {
Bitmap bmp = Bitmap.createBitmap(pixmap.getWidth(),
pixmap.getHeight(), Bitmap.Config.ARGB_8888);
for (x=0,xl=pixmap.getWidth(); x<xl;x++) {
for (y=0,yl=pixmap.getHeight(); y<yl;y++) {
int color = pixmap.getPixel(x, y);
// RGBA => ARGB
int RGB = color >> 8;
int A = (color & 0x000000ff) << 24;
int ARGB = A | RGB;
bmp.setPixel(x, y, ARGB);
}
}
fos = new FileOutputStream(jpgfile.file());
bmp.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
jpgfile = jpgfile2;
pixmap = pixmap2;
}
}).start();
}
#Override
public void saveAsJpeg(FileHandle jpgfile, Pixmap pixmap) {
convert();
this.jpgfile = jpgfile;
this.pixmap = pixmap;
jpgfile2 = this.jpgfile;
pixmap2 = this.pixmap;
}
#Override
public boolean isReady() {
if (cameraSurface!=null && cameraSurface.getCamera() != null) {
return true;
}
return false;
}
}

Related

How to remove useless fragments in ViewPager2

How to destroy retain Fragments or unused Fragments(Fragment with number 1-4) in ViewPager2 when right swap. I want only retain one Fragment in left of visible Fragment (Fragment 5)?
private static class SettingAdapter extends FragmentStateAdapter {
public SettingAdapter(#NonNull Fragment fragment) {
super(fragment);
}
public void destroyUnusedFragment(){
// ?
}
#NonNull
#Override
public Fragment createFragment(int position) {
Log.i("xxx", "createFragment: " + position);
switch (position) {
default:
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
case 3:
return new Fragment4();
case 4:
return new Fragment5();
case 5:
return new DispenserFragment();
case 6:
return new Fragment7();
case 7:
return new Fragment8();
case 8:
return new Fragment9();
case 9:
return new Fragment10();
case 10:
return new Fragment11();
case 11:
return new Fragment12();
case 12:
return new Fragment13();
case 13:
return new Fragment14();
case 14:
return new Fragment15();
}
}
#Override
public int getItemCount() {
return 15;
}
}
// call above from onCreateView in Fragment
String[] titles = getSettingTabTitlesRes(context);
settingAdapter = new SettingAdapter(this);
binding.settingViewpager.setOffscreenPageLimit(1);
binding.settingViewpager.setAdapter(settingAdapter);
new TabLayoutMediator(binding.settingTablayout, binding.settingViewpager, (tab, position) -> {
tab.setText(titles[position]);
}).attach();
package id.ctech.dispenser_pos.ui.fragment.setting.dispenser.view;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import java.util.List;
import id.ctech.dispenser_pos.R;
import id.ctech.dispenser_pos.databinding.FragmentDispenserBinding;
import id.ctech.dispenser_pos.db.local.datasource.setting.dispenser.dispenser.DispenserDataSource;
import id.ctech.dispenser_pos.db.local.datasource.setting.dispenser.dispenser_brand.DispenserBrandDataSource;
import id.ctech.dispenser_pos.db.local.datasource.setting.nozzle.NozzleDataSourceHelper;
import id.ctech.dispenser_pos.db.local.datasource.setting.work_schedule.shift_work.ShiftWorkDataSourceHelper;
import id.ctech.dispenser_pos.db.local.datasource.setting.work_schedule.work_schedule.WorkScheduleDataSourceHelper;
import id.ctech.dispenser_pos.etc.ChooseColor;
import id.ctech.dispenser_pos.etc.ThreadExecutors;
import id.ctech.dispenser_pos.ui.activity.main.MainActivity;
import id.ctech.dispenser_pos.ui.compound.table.listeners.ITableDataClickListener;
import id.ctech.dispenser_pos.ui.compound.table.listeners.ITableDataLongClickListener;
import id.ctech.dispenser_pos.ui.fragment.etc.DebouncedOnClickListener;
import id.ctech.dispenser_pos.ui.fragment.setting.SettingFragment;
import id.ctech.dispenser_pos.ui.fragment.setting.dispenser.model.Dispenser;
import id.ctech.dispenser_pos.ui.fragment.setting.dispenser.model.DispenserBrand;
import id.ctech.dispenser_pos.ui.fragment.setting.dispenser.presenter.DispenserPresenter;
import id.ctech.dispenser_pos.ui.fragment.setting.dispenser.presenter.IDispenserPresenter;
import id.ctech.dispenser_pos.ui.fragment.setting.dispenser.view.table.dispenser.DispenserDataAdapter;
import id.ctech.dispenser_pos.ui.fragment.setting.dispenser.view.table.dispenser_brand.DispenserBrandDataAdapter;
import id.ctech.dispenser_pos.ui.fragment.setting.nozzle.model.Nozzle;
import id.ctech.dispenser_pos.ui.fragment.setting.user_account.model.UserAccount;
import id.ctech.dispenser_pos.ui.fragment.setting.work_schedule.model.ShiftWork;
import id.ctech.dispenser_pos.ui.fragment.setting.work_schedule.model.WorkSchedule;
import static android.widget.Toast.LENGTH_SHORT;
import static id.ctech.dispenser_pos.dev.dispenser.ENozzleStatus.IN_HOLSTER;
import static id.ctech.dispenser_pos.etc.Common.ADMIN;
import static id.ctech.dispenser_pos.etc.Common.getDispenser;
import static id.ctech.dispenser_pos.etc.Common.getNozzles;
import static id.ctech.dispenser_pos.etc.Common.getShiftWorks;
import static id.ctech.dispenser_pos.etc.Common.getWorkSchedules;
import static id.ctech.dispenser_pos.etc.CommonColor.readThemeFromPref;
import static id.ctech.dispenser_pos.etc.CommonDate.toShortTime24;
import static id.ctech.dispenser_pos.ui.compound.alert_dialog.SweetAlertDialog.showConfirmDialog;
import static id.ctech.dispenser_pos.ui.compound.snackbar.SweetSnackbar.showSnackbarError;
import static id.ctech.dispenser_pos.ui.compound.snackbar.SweetSnackbar.showSnackbarInfo;
import static id.ctech.dispenser_pos.ui.compound.snackbar.SweetSnackbar.showSnackbarSuccess;
public class DispenserFragment extends Fragment implements IDispenserView {
private final static int PREV_PAGE = 3;
private final static int NEXT_PAGE = 5;
private Context context;
private IDispenserPresenter iDispenserPresenter;
// Dispenser
private DispenserDataAdapter dispenserDataAdapter;
private Dispenser dispenserClicked = null, dispenserLongClicked = null;
private int dispenserClickedRowIndex = -1, dispenserLongClickedRowIndex = -1;
private int hiddenNewID;
// DispenserBrand
private DispenserBrandDataAdapter dispenserBrandDataAdapter;
private DispenserBrand dispenserBrandClicked = null, dispenserBrandLongClicked = null;
private int dispenserBrandClickedRowIndex = -1, dispenserBrandLongClickedRowIndex = -1;
private int dispenserBrandNewID;
private FragmentDispenserBinding binding;
private ThreadExecutors threadExecutors;
private UserAccount signInAccount;
//
private Dispenser dispenser;
private Nozzle[] nozzles;
private ShiftWork[] shiftWorks;
private WorkSchedule[] workSchedules;
private int nozzleQty;
private int shiftWorkQty;
public DispenserFragment() {
}
private void readDispenser() {
try {
dispenser = getDispenser(context);
if (dispenser == null) {
showSnackbarError(getString(R.string.message_failed_to_load_dispenser_module), LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void readNozzles() {
try {
nozzles = getNozzles(context);
if (nozzles.length == 0) {
showSnackbarError(getString(R.string.message_failed_to_load_nozzle_module), LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void readShiftWorks() {
try {
shiftWorks = getShiftWorks(context);
if (shiftWorks.length == 0) {
showSnackbarError(getString(R.string.message_failed_to_load_shift_work_module), LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void readWorkSchedules() {
try {
workSchedules = getWorkSchedules(context);
if (workSchedules.length == 0) {
showSnackbarError(getString(R.string.message_failed_to_load_work_schedule_module), LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void nozzleSync() {
try {
readDispenser();
readNozzles();
// nozzle sync
if (dispenser != null && nozzles != null) {
nozzleQty = dispenser.getNozzleQty(); // references
if (nozzleQty < nozzles.length) {
for (int i = nozzleQty + 1; i <= nozzles.length; i++) {
NozzleDataSourceHelper.deleteNozzle(context, i);
}
} else if (nozzleQty > nozzles.length) {
for (int i = nozzles.length + 1; i <= nozzleQty; i++) {
Nozzle nozzle = new Nozzle(i, i, 0, 0, 0, 0, IN_HOLSTER);
NozzleDataSourceHelper.createNozzle(context, nozzle);
}
}
nozzles = getNozzles(context);
// nozzle validation
nozzleQty = dispenser.getNozzleQty();
if (nozzleQty != nozzles.length) {
showSnackbarError(getString(R.string.message_nozzle_sync_failed), LENGTH_SHORT);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void shiftWorkSync() {
try {
readDispenser();
readShiftWorks();
// shift work sync
if (dispenser != null && shiftWorks != null) {
shiftWorkQty = dispenser.getShiftWorkQty(); // references
if (shiftWorkQty < shiftWorks.length) {
for (int i = shiftWorkQty + 1; i <= shiftWorks.length; i++) {
ShiftWorkDataSourceHelper.deleteShiftWork(context, i);
}
} else if (shiftWorkQty > shiftWorks.length) {
for (int i = shiftWorks.length + 1; i <= shiftWorkQty; i++) {
String strTime24 = "";
switch (i) {
case 1:
strTime24 = "06:00";
break;
case 2:
strTime24 = "14:00";
break;
case 3:
strTime24 = "22:00";
break;
}
// create shift work
ShiftWork shiftWork = new ShiftWork(i, toShortTime24(strTime24));
ShiftWorkDataSourceHelper.createShiftWork(context, shiftWork);
}
}
shiftWorks = getShiftWorks(context);
// shiftWorks validation
shiftWorkQty = dispenser.getShiftWorkQty();
if (shiftWorkQty != shiftWorks.length) {
showSnackbarError(getString(R.string.message_shiftworks_sync_failed), LENGTH_SHORT);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void workScheduleSync() {
try {
readDispenser();
readWorkSchedules();
// work schedule sync
if (dispenser != null && workSchedules != null) {
nozzleQty = dispenser.getNozzleQty(); // references
if (nozzleQty < workSchedules.length) {
for (int i = nozzleQty + 1; i <= workSchedules.length; i++) {
WorkScheduleDataSourceHelper.deleteWorkSchedule(context, i);
}
} else if (nozzleQty > workSchedules.length) {
for (int i = workSchedules.length + 1; i <= nozzleQty; i++) {
WorkSchedule workSchedule = new WorkSchedule(i, i, 1, 1, 1);
WorkScheduleDataSourceHelper.createWorkSchedule(context, workSchedule);
}
}
workSchedules = getWorkSchedules(context);
// work schedule validation
nozzleQty = dispenser.getNozzleQty();
if (nozzleQty != workSchedules.length) {
showSnackbarError(getString(R.string.message_workschedule_sync_failed), LENGTH_SHORT);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void doSyncs() {
try {
nozzleSync();
shiftWorkSync();
workScheduleSync();
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
try {
Log.i("xxx", "DispenserFragment onCreateView");
context = getActivity();
if (context != null) {
binding = FragmentDispenserBinding.inflate(inflater, container, false);
View rootView = binding.getRoot();
threadExecutors = ThreadExecutors.getInstance();
doSyncs();
DispenserDataSource dispenserDataSource = DispenserDataSource.getInstance(context);
DispenserBrandDataSource dispenserBrandDataSource = DispenserBrandDataSource.getInstance(context);
new DispenserPresenter(context, dispenserDataSource, dispenserBrandDataSource, this);
// DispenserBrand
binding.dispenserBrandAddButton.setOnClickListener(new DispenserBrandAddButtonClickListener());
binding.dispenserBrandEditButton.setOnClickListener(new DispenserBrandEditButtonClickListener());
binding.dispenserBrandDeleteButton.setOnClickListener(new DispenserBrandDeleteButtonClickListener());
iDispenserPresenter.readDispenserBrands();
// dispenser
binding.dispenserPrevButton.setOnClickListener(new DispenserPrevButtonClickListener());
binding.dispenserNextButton.setOnClickListener(new DispenserNextButtonClickListener());
binding.dispenserAddButton.setOnClickListener(new DispenserAddButtonClickListener());
binding.dispenserEditButton.setOnClickListener(new DispenserEditButtonClickListener());
binding.dispenserDeleteButton.setOnClickListener(new DispenserDeleteButtonClickListener());
signInAccount = ((MainActivity) getActivity()).getSignInAccount();
iDispenserPresenter.readDispensers();
setTheme(context);
return rootView;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
private void setTheme(#NonNull Context context) {
try {
// set theme from pref
ChooseColor chooseColor = readThemeFromPref(context);
if (chooseColor != null) {
context.setTheme(chooseColor.getTheme()); // app theme (default: R.style.app_theme_red)
}
Activity activity = getActivity();
if (activity != null) {
int colorPrimary = ((MainActivity) activity).getColorPrimary();
binding.dispenserAddButton.setBackgroundColor(colorPrimary);
binding.dispenserDeleteButton.setBackgroundColor(colorPrimary);
binding.dispenserEditButton.setBackgroundColor(colorPrimary);
binding.dispenserPrevButton.setBackgroundColor(colorPrimary);
binding.dispenserNextButton.setBackgroundColor(colorPrimary);
binding.dispenserBrandAddButton.setBackgroundColor(colorPrimary);
binding.dispenserBrandDeleteButton.setBackgroundColor(colorPrimary);
binding.dispenserBrandEditButton.setBackgroundColor(colorPrimary);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public void onDestroyView() {
super.onDestroyView();
Log.i("xxx", "DispenserFragment onDestroyView");
binding = null;
threadExecutors = null;
dispenserBrandDataAdapter = null;
dispenserBrandClicked = null;
dispenserBrandLongClicked = null;
dispenserDataAdapter = null;
dispenserClicked = null;
dispenserLongClicked = null;
}
#Override
public void setPresenter(#NonNull IDispenserPresenter iPresenter) {
iDispenserPresenter = iPresenter;
}
// DispenserBrand
#Override
public void onCreateDispenserBrand(boolean result) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
if (result) {
showSnackbarSuccess(getString(R.string.message_successfully_to_save_data), LENGTH_SHORT);
iDispenserPresenter.readDispenserBrands();
binding.dispenserBrandAddButton.setText(getString(R.string.button_add));
binding.dispenserBrandEditButton.setEnabled(true);
binding.dispenserBrandDeleteButton.setEnabled(true);
binding.dispenserBrandAddButton.setTextColor(Color.WHITE);
} else {
showSnackbarError(getString(R.string.message_failed_to_save_data), LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onReadDispenserBrands(#NonNull List<DispenserBrand> dispenserBrandList) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
dispenserBrandDataAdapter = new DispenserBrandDataAdapter(context, dispenserBrandList, binding.dispenserBrandTable);
dispenserBrandDataAdapter.setSelectedColor(-1);
binding.dispenserBrandTable.setDataAdapter(dispenserBrandDataAdapter);
binding.dispenserBrandTable.sort(0, true);
binding.dispenserBrandTable.invalidate();
binding.dispenserBrandTable.removeDataClickListener(new DispenserBrandClickListener());
binding.dispenserBrandTable.removeDataLongClickListener(new DispenserBrandLongClickListener());
binding.dispenserBrandTable.addDataClickListener(new DispenserBrandClickListener());
binding.dispenserBrandTable.addDataLongClickListener(new DispenserBrandLongClickListener());
dispenserBrandClickedRowIndex = -1;
dispenserBrandClicked = null;
dispenserBrandLongClickedRowIndex = -1;
dispenserBrandLongClicked = null;
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onUpdateDispenserBrand(boolean result) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
if (result) {
showSnackbarSuccess(getString(R.string.message_successfully_to_save_data), LENGTH_SHORT);
iDispenserPresenter.readDispenserBrands();
binding.dispenserBrandEditButton.setText(getString(R.string.button_edit));
binding.dispenserBrandAddButton.setEnabled(true);
binding.dispenserBrandDeleteButton.setEnabled(true);
binding.dispenserBrandEditButton.setTextColor(Color.WHITE);
} else {
showSnackbarError(getString(R.string.message_failed_to_save_data), LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onDeleteDispenserBrand(boolean result) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
if (result) {
showSnackbarSuccess(getString(R.string.message_data_deleted), LENGTH_SHORT);
} else {
showSnackbarError(getString(R.string.message_failed_to_delete_data), LENGTH_SHORT);
}
iDispenserPresenter.readDispenserBrands();
binding.dispenserBrandAddButton.setEnabled(true);
binding.dispenserBrandEditButton.setEnabled(true);
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onNewIDDispenserBrand(int ID) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
dispenserBrandNewID = ID;
dispenserBrandDataAdapter.add(new DispenserBrand(dispenserBrandNewID, ""));
dispenserBrandDataAdapter.notifyDataSetChanged();
binding.dispenserBrandTable.enterEditMode();
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onErrorDispenserBrand(#NonNull Throwable result) {
Runnable r = () -> {
try {
String strMessage = result.getMessage();
if (strMessage != null) {
showSnackbarError(strMessage, LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
// Dispenser
#Override
public void onCreateDispenser(boolean result) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
if (result) {
showSnackbarSuccess(getString(R.string.message_successfully_to_save_data), LENGTH_SHORT);
iDispenserPresenter.readDispensers();
binding.dispenserAddButton.setText(getString(R.string.button_add));
binding.dispenserEditButton.setEnabled(true);
binding.dispenserDeleteButton.setEnabled(true);
binding.dispenserAddButton.setTextColor(Color.WHITE);
doSyncs();
} else {
showSnackbarError(getString(R.string.message_failed_to_save_data), LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onReadDispensers(#NonNull List<Dispenser> result) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
dispenserDataAdapter = new DispenserDataAdapter(context, result, binding.dispenserTable);
dispenserDataAdapter.setSelectedColor(-1);
binding.dispenserTable.setDataAdapter(dispenserDataAdapter);
binding.dispenserTable.sort(0, true);
binding.dispenserTable.invalidate();
binding.dispenserTable.removeDataClickListener(new DispenserClickListener());
binding.dispenserTable.removeDataLongClickListener(new DispenserLongClickListener());
binding.dispenserTable.addDataClickListener(new DispenserClickListener());
binding.dispenserTable.addDataLongClickListener(new DispenserLongClickListener());
dispenserClickedRowIndex = -1;
dispenserClicked = null;
dispenserLongClickedRowIndex = -1;
dispenserLongClicked = null;
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onUpdateDispenser(boolean result) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
if (result) {
showSnackbarSuccess(getString(R.string.message_successfully_to_save_data), LENGTH_SHORT);
iDispenserPresenter.readDispensers();
binding.dispenserEditButton.setText(getString(R.string.button_edit));
binding.dispenserAddButton.setEnabled(true);
binding.dispenserDeleteButton.setEnabled(true);
binding.dispenserEditButton.setTextColor(Color.WHITE);
doSyncs();
} else {
showSnackbarError(getString(R.string.message_failed_to_save_data), LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onDeleteDispenser(boolean result) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
if (result) {
showSnackbarSuccess(getString(R.string.message_data_deleted), LENGTH_SHORT);
doSyncs();
} else {
showSnackbarError(getString(R.string.message_failed_to_delete_data), LENGTH_SHORT);
}
iDispenserPresenter.readDispensers();
binding.dispenserAddButton.setEnabled(true);
binding.dispenserEditButton.setEnabled(true);
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onNewIDDispenser(int ID) {
Runnable r = () -> {
try {
if (binding == null) {
return;
}
hiddenNewID = ID;
// create default dispenser (dispenserId:1, dispenserType:new, nozzleQty:8, workScheduleQty:3)
dispenserDataAdapter.add(new Dispenser(hiddenNewID, 1, 2, 8, 3));
dispenserDataAdapter.notifyDataSetChanged();
binding.dispenserTable.enterEditMode();
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
#Override
public void onErrorDispenser(#NonNull Throwable result) {
Runnable r = () -> {
try {
String strMessage = result.getMessage();
if (strMessage != null) {
showSnackbarError(strMessage, LENGTH_SHORT);
}
} catch (Exception ex) {
ex.printStackTrace();
}
};
threadExecutors.getMainThreadExecutor().execute(r);
}
// DispenserBrand
private class DispenserBrandAddButtonClickListener extends DebouncedOnClickListener {
#Override
public void onDebouncedClick(final View v) {
}
}
private class DispenserBrandEditButtonClickListener extends DebouncedOnClickListener {
#Override
public void onDebouncedClick(View v) {
}
}
private class DispenserBrandDeleteButtonClickListener extends DebouncedOnClickListener {
#Override
public void onDebouncedClick(View v) {
}
}
private class DispenserBrandClickListener implements ITableDataClickListener<DispenserBrand> {
#Override
public void onDataClicked(int rowIndex, DispenserBrand clickedData) {
}
}
private class DispenserBrandLongClickListener implements ITableDataLongClickListener<DispenserBrand> {
#Override
public boolean onDataLongClicked(int rowIndex, DispenserBrand clickedData) {
return false;
}
}
// Dispenser
private class DispenserPrevButtonClickListener extends DebouncedOnClickListener {
#Override
public void onDebouncedClick(View v) {
}
}
private class DispenserNextButtonClickListener extends DebouncedOnClickListener {
#Override
public void onDebouncedClick(View v) {
}
}
private class DispenserAddButtonClickListener extends DebouncedOnClickListener {
#Override
public void onDebouncedClick(final View v) {
}
}
private class DispenserEditButtonClickListener extends DebouncedOnClickListener {
#Override
public void onDebouncedClick(View v) {
}
}
private class DispenserDeleteButtonClickListener extends DebouncedOnClickListener {
#Override
public void onDebouncedClick(View v) {
}
}
private class DispenserClickListener implements ITableDataClickListener<Dispenser> {
#Override
public void onDataClicked(int rowIndex, Dispenser clickedData) {
}
}
private class DispenserLongClickListener implements ITableDataLongClickListener<Dispenser> {
#Override
public boolean onDataLongClicked(int rowIndex, Dispenser clickedData) {
return false;
}
}
}
Its bug of ViewPager2 and I get solution as follows:
/**
* Sets whether the LayoutManager should be queried for views outside of
* its viewport while the UI thread is idle between frames.
*
* <p>If enabled, the LayoutManager will be queried for items to inflate/bind in between
* view system traversals on devices running API 21 or greater. Default value is true.</p>
*
* <p>On platforms API level 21 and higher, the UI thread is idle between passing a frame
* to RenderThread and the starting up its next frame at the next VSync pulse. By
* prefetching out of window views in this time period, delays from inflation and view
* binding are much less likely to cause jank and stuttering during scrolls and flings.</p>
*
* <p>While prefetch is enabled, it will have the side effect of expanding the effective
* size of the View cache to hold prefetched views.</p>
*
* #param enabled <code>True</code> if items should be prefetched in between traversals.
*
* #see #isItemPrefetchEnabled()
*/
RecyclerView.LayoutManager layoutManager = ((RecyclerView)(binding.settingViewpager.getChildAt(0))).getLayoutManager();
if(layoutManager != null) {
layoutManager.setItemPrefetchEnabled(false);
}
/**
* Set the number of offscreen views to retain before adding them to the potentially shared
* {#link #getRecycledViewPool() recycled view pool}.
*
* <p>The offscreen view cache stays aware of changes in the attached adapter, allowing
* a LayoutManager to reuse those views unmodified without needing to return to the adapter
* to rebind them.</p>
*
* #param size Number of views to cache offscreen before returning them to the general
* recycled view pool
*/
RecyclerView recyclerView= ((RecyclerView)(binding.settingViewpager.getChildAt(0)));
if(recyclerView != null) {
recyclerView.setItemViewCacheSize(0);
}

How to take screenshot of activity with camera feed in it?

I'm currently developing an android application which detect objects using camera using tensorflow detection API. I want to take screenshot of the camera activity where the detection is happening.
How can I take screenshot of the camera activity including the camera preview itself?
This code came from tensorflow demo application. I just want to add a screenshot functionality using a button. That's why I added a button and an Image View. The Image View is where the screenshot preview will show but I dont have any idea on how to implement this :(
This is the code for the camera activity:
CameraActivity.java
public abstract class CameraActivity extends Activity
implements OnImageAvailableListener, Camera.PreviewCallback {
private static final Logger LOGGER = new Logger();
private static final int PERMISSIONS_REQUEST = 1;
private static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;
private static final String PERMISSION_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
private boolean debug = false;
private Handler handler;
private HandlerThread handlerThread;
private boolean useCamera2API;
private boolean isProcessingFrame = false;
private byte[][] yuvBytes = new byte[3][];
private int[] rgbBytes = null;
private int yRowStride;
protected int previewWidth = 0;
protected int previewHeight = 0;
private Runnable postInferenceCallback;
private Runnable imageConverter;
#Override
protected void onCreate(final Bundle savedInstanceState) {
LOGGER.d("onCreate " + this);
super.onCreate(null);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_camera);
if (hasPermission()) {
setFragment();
} else {
requestPermission();
}
}
private byte[] lastPreviewFrame;
protected int[] getRgbBytes() {
imageConverter.run();
return rgbBytes;
}
protected int getLuminanceStride() {
return yRowStride;
}
protected byte[] getLuminance() {
return yuvBytes[0];
}
/**
* Callback for android.hardware.Camera API
*/
#Override
public void onPreviewFrame(final byte[] bytes, final Camera camera) {
if (isProcessingFrame) {
LOGGER.w("Dropping frame!");
return;
}
try {
// Initialize the storage bitmaps once when the resolution is known.
if (rgbBytes == null) {
Camera.Size previewSize = camera.getParameters().getPreviewSize();
previewHeight = previewSize.height;
previewWidth = previewSize.width;
rgbBytes = new int[previewWidth * previewHeight];
onPreviewSizeChosen(new Size(previewSize.width, previewSize.height), 90);
}
} catch (final Exception e) {
LOGGER.e(e, "Exception!");
return;
}
isProcessingFrame = true;
lastPreviewFrame = bytes;
yuvBytes[0] = bytes;
yRowStride = previewWidth;
imageConverter =
new Runnable() {
#Override
public void run() {
ImageUtils.convertYUV420SPToARGB8888(bytes, previewWidth, previewHeight, rgbBytes);
}
};
postInferenceCallback =
new Runnable() {
#Override
public void run() {
camera.addCallbackBuffer(bytes);
isProcessingFrame = false;
}
};
processImage();
}
/**
* Callback for Camera2 API
*/
#Override
public void onImageAvailable(final ImageReader reader) {
//We need wait until we have some size from onPreviewSizeChosen
if (previewWidth == 0 || previewHeight == 0) {
return;
}
if (rgbBytes == null) {
rgbBytes = new int[previewWidth * previewHeight];
}
try {
final Image image = reader.acquireLatestImage();
if (image == null) {
return;
}
if (isProcessingFrame) {
image.close();
return;
}
isProcessingFrame = true;
Trace.beginSection("imageAvailable");
final Plane[] planes = image.getPlanes();
fillBytes(planes, yuvBytes);
yRowStride = planes[0].getRowStride();
final int uvRowStride = planes[1].getRowStride();
final int uvPixelStride = planes[1].getPixelStride();
imageConverter =
new Runnable() {
#Override
public void run() {
ImageUtils.convertYUV420ToARGB8888(
yuvBytes[0],
yuvBytes[1],
yuvBytes[2],
previewWidth,
previewHeight,
yRowStride,
uvRowStride,
uvPixelStride,
rgbBytes);
}
};
postInferenceCallback =
new Runnable() {
#Override
public void run() {
image.close();
isProcessingFrame = false;
}
};
processImage();
} catch (final Exception e) {
LOGGER.e(e, "Exception!");
Trace.endSection();
return;
}
Trace.endSection();
}
#Override
public synchronized void onStart() {
LOGGER.d("onStart " + this);
super.onStart();
}
#Override
public synchronized void onResume() {
LOGGER.d("onResume " + this);
super.onResume();
handlerThread = new HandlerThread("inference");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
#Override
public synchronized void onPause() {
LOGGER.d("onPause " + this);
if (!isFinishing()) {
LOGGER.d("Requesting finish");
finish();
}
handlerThread.quitSafely();
try {
handlerThread.join();
handlerThread = null;
handler = null;
} catch (final InterruptedException e) {
LOGGER.e(e, "Exception!");
}
super.onPause();
}
#Override
public synchronized void onStop() {
LOGGER.d("onStop " + this);
super.onStop();
}
#Override
public synchronized void onDestroy() {
LOGGER.d("onDestroy " + this);
super.onDestroy();
}
protected synchronized void runInBackground(final Runnable r) {
if (handler != null) {
handler.post(r);
}
}
#Override
public void onRequestPermissionsResult(
final int requestCode, final String[] permissions, final int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
setFragment();
} else {
requestPermission();
}
}
}
private boolean hasPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return checkSelfPermission(PERMISSION_CAMERA) == PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(PERMISSION_STORAGE) == PackageManager.PERMISSION_GRANTED;
} else {
return true;
}
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(PERMISSION_CAMERA) ||
shouldShowRequestPermissionRationale(PERMISSION_STORAGE)) {
Toast.makeText(CameraActivity.this,
"Camera AND storage permission are required for this demo", Toast.LENGTH_LONG).show();
}
requestPermissions(new String[] {PERMISSION_CAMERA, PERMISSION_STORAGE}, PERMISSIONS_REQUEST);
}
}
// Returns true if the device supports the required hardware level, or better.
private boolean isHardwareLevelSupported(
CameraCharacteristics characteristics, int requiredLevel) {
int deviceLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
return requiredLevel == deviceLevel;
}
// deviceLevel is not LEGACY, can use numerical sort
return requiredLevel <= deviceLevel;
}
private String chooseCamera() {
final CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
for (final String cameraId : manager.getCameraIdList()) {
final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
// We don't use a front facing camera in this sample.
final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
final StreamConfigurationMap map =
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
continue;
}
// Fallback to camera1 API for internal cameras that don't have full support.
// This should help with legacy situations where using the camera2 API causes
// distorted or otherwise broken previews.
useCamera2API = (facing == CameraCharacteristics.LENS_FACING_EXTERNAL)
|| isHardwareLevelSupported(characteristics,
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
LOGGER.i("Camera API lv2?: %s", useCamera2API);
return cameraId;
}
} catch (CameraAccessException e) {
LOGGER.e(e, "Not allowed to access camera");
}
return null;
}
protected void setFragment() {
String cameraId = chooseCamera();
Fragment fragment;
if (useCamera2API) {
CameraConnectionFragment camera2Fragment =
CameraConnectionFragment.newInstance(
new CameraConnectionFragment.ConnectionCallback() {
#Override
public void onPreviewSizeChosen(final Size size, final int rotation) {
previewHeight = size.getHeight();
previewWidth = size.getWidth();
CameraActivity.this.onPreviewSizeChosen(size, rotation);
}
},
this,
getLayoutId(),
getDesiredPreviewFrameSize());
camera2Fragment.setCamera(cameraId);
fragment = camera2Fragment;
} else {
fragment =
new LegacyCameraConnectionFragment(this, getLayoutId(), getDesiredPreviewFrameSize());
}
getFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
protected void fillBytes(final Plane[] planes, final byte[][] yuvBytes) {
// Because of the variable row stride it's not possible to know in
// advance the actual necessary dimensions of the yuv planes.
for (int i = 0; i < planes.length; ++i) {
final ByteBuffer buffer = planes[i].getBuffer();
if (yuvBytes[i] == null) {
LOGGER.d("Initializing buffer %d at size %d", i, buffer.capacity());
yuvBytes[i] = new byte[buffer.capacity()];
}
buffer.get(yuvBytes[i]);
}
}
public boolean isDebug() {
return debug;
}
public void requestRender() {
final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay);
if (overlay != null) {
overlay.postInvalidate();
}
}
public void addCallback(final OverlayView.DrawCallback callback) {
final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay);
if (overlay != null) {
overlay.addCallback(callback);
}
}
public void onSetDebug(final boolean debug) {}
#Override
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
debug = !debug;
requestRender();
onSetDebug(debug);
return true;
}
return super.onKeyDown(keyCode, event);
}
protected void readyForNextImage() {
if (postInferenceCallback != null) {
postInferenceCallback.run();
}
}
protected int getScreenOrientation() {
switch (getWindowManager().getDefaultDisplay().getRotation()) {
case Surface.ROTATION_270:
return 270;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_90:
return 90;
default:
return 0;
}
}
protected abstract void processImage();
protected abstract void onPreviewSizeChosen(final Size size, final int rotation);
protected abstract int getLayoutId();
protected abstract Size getDesiredPreviewFrameSize();
}
And this is the layout file
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="500dp"
tools:context="org.tensorflow.demo.CameraActivity">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Screenshot" />
</FrameLayout>
<ImageView
android:id="#+id/imageView"
android:layout_width="140dp"
android:layout_height="160dp"
android:layout_marginStart="205dp"
android:layout_marginTop="0dp" />
I just want to take screenshot of the activity including the camera where the detection is happening. I tried some tutorials on how to take screenshot. It captures all the parts of the screen but doesnt capture the camera part. It only shows black screen. HELP!

Android ChangeOverTime method freezing at runtime (but not consistently)

So I am running into a problem with a function I made to slowly change the value of a monitored variable over time that is causing all the java logic to lock up. It doesn't seem to be producing an error or make the application crash so it must be getting stuck in the while loop or something but the logging isn't firing while it is locked so I am just very confused. If anyone can help me figure out how to diagnose what is causing the freezing that would be very much appreciated
EDIT: Turns out the problem was updating the UI from another thread, I manged to get it to crash and got the error and used a CountDownTimer instead of the background thread and now it is working fine. For those curious checkout my GitHub for this project.
Function in question:
public static void changeOverTime(final MonitoredVariable<Integer> tVar, final int tTo, final long tTime, final long tUpdateFreq) {
if (tTime < tUpdateFreq) { Log.e(TAG, "Time must be greater then update freq."); }
if (tVar == null) { Log.e(TAG, "Container cannot be null."); }
else {
final Thread tBackgroundThread = new Thread(new Runnable() {
#Override
public void run() {
float tSteps = tTime / tUpdateFreq; // 2000/100 = 20
float tInterval = (tTo - tVar.get()) / tSteps; // 67-175 = -108/20 = -5.4
float tVal = tVar.get(); //175
while (Math.round(tVal) != tTo) { //67(After 20 Times) != 67 -> FALSE
Debug.Log(TAG, "EQ: " + Math.round(tVal) + "?=" + tTo);
tVal += tInterval; // -5.4 * 20(Times) = -108+175 = 67
tryToSleep(tUpdateFreq); // 100ms * 20(Times) = 2000ms total
tVar.set(Math.round(tVal));
}
}
});
tBackgroundThread.start();
}
}
Supporting Function:
private static void tryToSleep(long tTime) {
try { sleep(tTime); }
catch (InterruptedException e) { e.printStackTrace(); }
}
Monitored Variable Class:
public class MonitoredVariable<Prototype> {
protected Prototype mData;
protected ChangeListener mListener;
public MonitoredVariable(Prototype tData) {
this(tData, null);
}
public MonitoredVariable(Prototype tData, ChangeListener tListener) {
if (tListener != null) setListener(tListener);
mData = tData;
}
public Prototype get() {
return mData;
}
public void set(Prototype tData) {
if (mData != tData) {
mData = tData;
notifyChange();
}
}
public void setListener(ChangeListener tListener) {
mListener = tListener;
}
public ChangeListener getListener() {
return mListener;
}
public void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}
}
Usage:
public static void init() {
MonitoredVariable.ChangeListener tUpdateBackground = new MonitoredVariable.ChangeListener() {
#Override
public void onChange() { updateBackgroud();
}
};
mTop = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mBottom = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mAnimationLoop = new Handler();
mAnimation = new Runnable() {
#Override
public void run() {
Debug.Log(TAG, "RUNNING ANIMATION");
final Random RNG = new Random();
for (MonitoredVariable<Integer>[] tBackground: new MonitoredVariable[][] {mTop, mBottom}) {
for (MonitoredVariable<Integer> tColor : tBackground) {
int tRandomColor = RNG.nextInt(255);
//tColor.set(tRandomColor);
Shift.changeOverTime(tColor, tRandomColor, 2000, 100);
}
}
if(mAnimate.get()) {
mAnimationLoop.postDelayed(mAnimation, 10000);
}
}
};
mAnimate = new MonitoredVariable<>(false, new MonitoredVariable.ChangeListener() {
#Override
public void onChange() {
if (mAnimate.get()) mAnimationLoop.postDelayed(mAnimation, 0);
else mAnimationLoop.removeCallbacks(mAnimation);
}
});
}
public static void setBackground(final Activity tActivity){
final View tActivityBackground = tActivity.findViewById(R.id.background);
mListener = new ChangeListener() {
#Override
public void onChange() { tActivityBackground.setBackground(mBackground); }
};
notifyChange();
}
private static void updateBackgroud() {
int tTop = Color.argb(255, mTop[0].get(), mTop[1].get(), mTop[2].get());
int tBottom = Color.argb(255, mBottom[0].get(), mBottom[1].get(), mBottom[2].get());
int[] colors = {tTop, tBottom};
mBackground = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
mBackground.setCornerRadius(0f);
notifyChange();
}
public static void animateBackground(boolean tAnimate) {
mAnimate.set(tAnimate);
}
public static void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}

cameraId was null(camera2)

So I am new to coding and working with the camera. I don't understand why the cameraId was null. Would really appreciate if someone could help me out. Thanks
Code:
public class CameraFragment extends Fragment {
private TextureView textureView;
private HandlerThread mBackgroundHandlerThread;
private Handler mBackgroundHandler;
private String mCameraId;
private Size mPreviewSize;
public static CameraFragment newInstance() {
return new CameraFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout. fragment_camera, container, false);
textureView = (TextureView) rootView.findViewById(R.id.textureView);
return rootView;
}
private static final int REQUEST_CAMERA_PERMISSION_RESULT = 0;
private TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
setupCamera(width, height);
connectCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private CameraDevice mCameraDevice;
private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
mCameraDevice = camera;
startPreview();
//Toast.makeText(getApplicationContext(), "Camera connected!", Toast.LENGTH_LONG).show();
}
#Override
public void onDisconnected(#NonNull CameraDevice camera) {
camera.close();
mCameraDevice = null;
}
#Override
public void onError(#NonNull CameraDevice camera, int error) {
camera.close();
mCameraDevice = null;
}
};
#Override
public void onResume() {
super.onResume();
startBackgroundThread();
if (textureView.isAvailable()) {
//setupCamera(textureView.getWidth(), textureView.getHeight());
connectCamera();
} else {
textureView.setSurfaceTextureListener(surfaceTextureListener);
}
}
#Override
public void onPause() {
closeCamera();
stopBackgroundThread();
super.onPause();
}
private void closeCamera() {
if(mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
}
private void stopBackgroundThread() {
mBackgroundHandlerThread.quitSafely();
try {
mBackgroundHandlerThread.join();
mBackgroundHandlerThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void setupCamera(int width, int height) {
if(mCameraDevice == null)
return;
CameraManager cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
try {
if (cameraManager != null) {
mCameraId = cameraManager.getCameraIdList()[0];
}
assert cameraManager != null;
for (String cameraId : cameraManager.getCameraIdList()) {
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
CameraCharacteristics.LENS_FACING_FRONT){
continue;
}
StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
int deviceOrientation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
int totalRotation = sensorToDeviceRotation(cameraCharacteristics, deviceOrientation);
boolean swapRotation = totalRotation == 90 || totalRotation == 270;
int rotatedWidth = width;
int rotatedHeight = height;
if (swapRotation){
rotatedWidth = height;
rotatedHeight = width;
}
if (map != null) {
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedWidth, rotatedHeight);
}
mCameraId = cameraId;
return;
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void connectCamera() {
CameraManager cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
try {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_GRANTED) {
assert cameraManager != null;
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
} else {
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
Toast.makeText(getActivity(), "This app requires access to camera", Toast.LENGTH_LONG).show();
}
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION_RESULT);
}
} else {
assert cameraManager != null;
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
}
}catch(CameraAccessException e){
e.printStackTrace();
}
}
private CaptureRequest.Builder mCaptureRequestBuilder;
private static SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 0);
ORIENTATIONS.append(Surface.ROTATION_90, 90);
ORIENTATIONS.append(Surface.ROTATION_180, 180);
ORIENTATIONS.append(Surface.ROTATION_270, 270);
}
private static class CompareSizeByArea implements Comparator<Size> {
#Override
public int compare(Size lhs, Size rhs){
return Long.signum((long) lhs.getWidth() * lhs.getHeight() /
(long) rhs.getWidth() * rhs.getHeight());
}
}
private static int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics, int deviceOrientation){
int sensorOrientation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
deviceOrientation = ORIENTATIONS.get(deviceOrientation);
return(sensorOrientation + deviceOrientation + 360) % 360;
}
public void onWindowFocusChanged (boolean hasFocus) {
super.getActivity().onWindowFocusChanged(hasFocus);
View decorView = getActivity().getWindow().getDecorView();
if(hasFocus){
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
private void startBackgroundThread() {
mBackgroundHandlerThread = new HandlerThread("Camera Background");
mBackgroundHandlerThread.start();
mBackgroundHandler = new Handler(mBackgroundHandlerThread.getLooper());
}
private void startPreview() {
SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
assert surfaceTexture != null;
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
try {
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mCaptureRequestBuilder.addTarget(previewSurface);
mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession session) {
try {
session.setRepeatingRequest(mCaptureRequestBuilder.build(),
null, mBackgroundHandler);
} catch (CameraAccessException e){
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession session) {
Toast.makeText(getActivity(), "Unable to connect to camera", Toast.LENGTH_LONG).show();
}
}, null);
} catch (CameraAccessException e){
e.printStackTrace();
}
}
private static Size chooseOptimalSize(Size[] choices, int width, int height) {
List<Size> bigEnough = new ArrayList<Size>();
for(Size option : choices){
if(option.getHeight() == option.getWidth() * height/width &&
option.getWidth() >= width && option.getHeight() >= height) {
bigEnough.add(option);
}
}
if(bigEnough.size() > 0){
return Collections.min(bigEnough, (Comparator<? super Size>) new CompareSizeByArea());
} else {
return choices[0];
}
}
}
Log:
> FATAL EXCEPTION: main
Process: com.example.patrick.wz, PID: 5246
java.lang.IllegalArgumentException: cameraId was null
at android.hardware.camera2.CameraManager.openCameraForUid(CameraManager.java:454)
at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:430)
at com.example.patrick.wz.Fragments.CameraFragment.connectCamera(CameraFragment.java:214)
at com.example.patrick.wz.Fragments.CameraFragment.access$100(CameraFragment.java:40)
at com.example.patrick.wz.Fragments.CameraFragment$1.onSurfaceTextureAvailable(CameraFragment.java:74)
at android.view.TextureView.getHardwareLayer(TextureView.java:390)
at android.view.TextureView.draw(TextureView.java:339)
at android.view.View.updateDisplayListIfDirty(View.java:18069)
at android.view.View.draw(View.java:18847)
at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
at android.view.View.updateDisplayListIfDirty(View.java:18060)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:659)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:757)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2980)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2794)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2347)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1386)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6733)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
at android.view.Choreographer.doFrame(Choreographer.java:658)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
In onResume, you've commented out the call to setupCamera, which is what sets mCameraId. So it's still null when you get to connectCamera.

How to make an android camera preview stay focused?

I am quite new to Android, thus the code is not from me since I use it only to learn.
The application I want to make has to show a camera preview. I have the preview of the camera on the surface, but it's not focused. As a work-around I made a runnable that calls auto-focus every 750ms.
I would like to know how I can make this better since whenever I call auto-focus the preview will blur until it's focused again.
Thank you for any help.
import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class Draw extends Activity {
private SurfaceView preview = null;
private SurfaceHolder previewHolder = null;
private Camera camera = null;
private boolean inPreview = false;
private boolean cameraConfigured = false;
private Handler handler = new Handler();;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.draw);
preview = (SurfaceView) findViewById(R.id.preview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
final Runnable r = new Runnable() {
#Override
public void run() {
camera.autoFocus(autoFocusCallback);
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 750);
}
private AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {
#Override
public void onAutoFocus(boolean autoFocusSuccess, Camera arg1) {
}
};
#Override
public void onResume() {
super.onResume();
camera = Camera.open();
startPreview();
}
#Override
public void onPause() {
if (inPreview) {
camera.stopPreview();
}
camera.release();
camera = null;
inPreview = false;
super.onPause();
}
private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result = size;
} else {
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea) {
result = size;
}
}
}
}
return (result);
}
private void initPreview(int width, int height) {
if (camera != null && previewHolder.getSurface() != null) {
try {
camera.setPreviewDisplay(previewHolder);
} catch (Throwable t) {
Log.e("KritzelKunst-surfaceCallback", "Exception in setPreviewDisplay()", t);
Toast.makeText(Draw.this, t.getMessage(), Toast.LENGTH_LONG).show();
}
if (!cameraConfigured) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null) {
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
cameraConfigured = true;
}
}
}
}
private void startPreview() {
if (cameraConfigured && camera != null) {
camera.startPreview();
inPreview = true;
}
}
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
// no-op -- wait until surfaceChanged()
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
initPreview(width, height);
startPreview();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// no-op
}
};
}
Try adding
<uses-feature android:name="android.hardware.camera.autofocus" />
in your manifest.

Categories

Resources