EDIT: Added Adapter code
EDIT: I updated the codes of my main project alongside with its logcat
I have this app that is a shop-like and displays clothes to select. Every clothes has a button and I want that button to redirect to a custom camera but everytime I open my app, it just opens the launcher activity and crash afterwards and never reaches the main activity.
Is it possible to use intent just like what I did? If yes, where did I go wrong?
If not, what should I do?
These are my codes for the button as the main activity.
CLARTIPS_Home.java
public class CLARTIPS_Home extends AppCompatActivity {
private ListView lvProduct;
private ListProductAdapter adapter;
private List<Product> mProductList;
private DatabaseHelper mDBHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clartips__home);
lvProduct = (ListView) findViewById(R.id.listview_product);
mDBHelper = new DatabaseHelper(this);
Button tryMe = (Button) findViewById(R.id.tryMe);
tryMe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openCam();
}
});
//Check exists database
File database = getApplicationContext().getDatabasePath(DatabaseHelper.DBNAME);
if(false==database.exists()) {
mDBHelper.getReadableDatabase();
//Copy db
if (copyDatabase(this)) {
Toast.makeText(this, "Success Copying Database", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Error Copying Database", Toast.LENGTH_SHORT).show();
return;
}
}
//Get product list in db when db exists
mProductList = mDBHelper.getListProduct();
//Init adapter
adapter = new ListProductAdapter(this,mProductList);
//Set adapter for listview
lvProduct.setAdapter(adapter);
}
private void openCam() {
Intent cameraIntent = new Intent(CLARTIPS_Home.this, Camera.class);
startActivity(cameraIntent);
}
private boolean copyDatabase(Context context) {
try {
InputStream inputStream = context.getAssets().open(DatabaseHelper.DBNAME);
String outFileName = DatabaseHelper.DBLOCATION + DatabaseHelper.DBNAME;
OutputStream outputStream = new FileOutputStream(outFileName);
byte[]buff = new byte[1024];
int length = 0;
while ((length = inputStream.read(buff)) > 0) {
outputStream.write(buff, 0, length);
}
outputStream.flush();
outputStream.close();
Log.w("MainActivity","DB copied");
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected (MenuItem item){
switch (item.getItemId()) {
case R.id.about:
Intent aboutIntent = new Intent(CLARTIPS_Home.this, About.class);
startActivity(aboutIntent);
}
return super.onOptionsItemSelected(item);
}
}
These are my codes for the Camera. I used Camera2 by the way.
Camera.java
public class Camera extends AppCompatActivity {
private Button btnCapture;
private TextureView textureView;
//Check state orientation of output image
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
private String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSessions;
private CaptureRequest.Builder captureRequestBuilder;
private android.util.Size imageDimension;
private ImageReader imageReader;
//Save to FILE
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
CameraDevice.StateCallback stateCallBack = new CameraDevice.StateCallback(){
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice=null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.show_camera);
textureView = (TextureView)findViewById(R.id.textureView);
//to check if expression is true or false
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnCapture = (Button)findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
takePicture();
}
});
}
private void takePicture() {
if(cameraDevice == null)
return;
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
android.util.Size[] jpegSizes = null;
if(characteristics != null)
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
//Capture image with custom size
int width = 640;
int height = 480;
if(jpegSizes != null && jpegSizes.length > 0){
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width,height,ImageFormat.JPEG,1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
outputSurface.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
//Check orientation base on device
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
file = new File(Environment.getExternalStorageDirectory()+"/"+UUID.randomUUID().toString()+".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener(){
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try{
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
}
catch (FileNotFoundException e){
e.printStackTrace();
}
catch (IOException e){
e.printStackTrace();
}
finally {
{
if (image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputSteam = null;
try{
outputSteam = new FileOutputStream(file);
outputSteam.write(bytes);
}finally {
if(outputSteam != null)
outputSteam.close();
}
}
};
reader.setOnImageAvailableListener(readerListener,mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(Camera.this, "Saved "+file, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback(){
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try{
cameraCaptureSession.capture(captureBuilder.build(),captureListener,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
},mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreview() {
try{
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(),imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if(cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(Camera.this, "Changed", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,CaptureRequest.CONTROL_MODE_AUTO);
try{
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
//Check realtime permission if run higher API 23
if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{
android.Manifest.permission.CAMERA,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
},REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId,stateCallBack,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener(){
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == REQUEST_CAMERA_PERMISSION){
if(grantResults[0] != PackageManager.PERMISSION_GRANTED){
Toast.makeText(this, "You can't use camera without permission", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if(textureView.isAvailable())
openCamera();
else
textureView.setSurfaceTextureListener(textureListener);
}
#Override
protected void onPause() {
stopBackgroundThread();
super.onPause();
}
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try{
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
}
My final year in college is on the line here. All your kind answers will be so much appreciated. Thank you so much.
Logcat
02-13 08:11:13.608 20959-20959/? I/art: Late-enabling -Xcheck:jni
02-13 08:11:13.804 20959-20959/? W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
02-13 08:11:13.953 20959-20959/? I/ViewRootImpl: CPU Rendering VSync enable = true
02-13 08:11:13.962 20959-21000/? D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
02-13 08:11:14.032 20959-20959/? D/Atlas: Validating map...
02-13 08:11:14.055 20959-20959/? V/PhoneWindow: updateColorViewInt()if drawable=null color=ff000000
02-13 08:11:14.096 20959-21000/? I/Adreno-EGL: <qeglDrvAPI_eglInitialize:379>: EGL 1.4 QUALCOMM build: Nondeterministic_AU_msm8916_32_LA.BR.1.2.4_RB1__release_AU (Ic8ede1fb34)
OpenGL ES Shader Compiler Version: E031.25.03.04
Build Date: 12/10/15 Thu
Local Branch: mybranch17178083
Remote Branch: quic/LA.BR.1.2.4_rb1.30
Local Patches: NONE
Reconstruct Branch: NOTHING
02-13 08:11:14.157 20959-21000/nerds.thesis.clartips I/OpenGLRenderer: Initialized EGL, version 1.4
02-13 08:11:14.478 20959-21000/nerds.thesis.clartips D/OpenGLRenderer: Enabling debug mode 0
02-13 08:11:14.627 20959-20959/nerds.thesis.clartips I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy#2d38ca61 time:44076123
02-13 08:11:17.990 20959-20959/nerds.thesis.clartips I/Timeline: Timeline: Activity_launch_request id:nerds.thesis.clartips time:44079486
02-13 08:11:18.221 20959-20969/nerds.thesis.clartips W/art: Suspending all threads took: 10.057ms
02-13 08:11:18.230 20959-20959/nerds.thesis.clartips D/AndroidRuntime: Shutting down VM
02-13 08:11:18.232 20959-20959/nerds.thesis.clartips E/AndroidRuntime: FATAL EXCEPTION: main
Process: nerds.thesis.clartips, PID: 20959
java.lang.RuntimeException: Unable to start activity ComponentInfo{nerds.thesis.clartips/nerds.thesis.clartips.CLARTIPS_Home}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2335)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2397)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1310)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5270)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:902)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:697)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at nerds.thesis.clartips.CLARTIPS_Home.onCreate(CLARTIPS_Home.java:42)
at android.app.Activity.performCreate(Activity.java:6057)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288
Below are my codes for the adapter.
ListProductAdapter.java
public class ListProductAdapter extends BaseAdapter {
private Context mContext;
private List<Product> mProductList;
public ListProductAdapter(Context mContext, List<Product> mProductList) {
this.mContext = mContext;
this.mProductList = mProductList;
}
#Override
public int getCount() {
return mProductList.size();
}
#Override
public Object getItem(int position) {
return mProductList.get(position);
}
#Override
public long getItemId(int position) {
return mProductList.get(position).getId();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = View.inflate(mContext, R.layout.listview, null);
TextView pName = (TextView) v.findViewById(R.id.product_name);
ImageView pImage = (ImageView) v.findViewById(R.id.product_image);
TextView pPrice = (TextView) v.findViewById(R.id.product_price);
TextView pDescription = (TextView) v.findViewById(R.id.product_description);
TextView pCategory = (TextView) v.findViewById(R.id.product_category);
pName.setText(mProductList.get(position).getName());
Product image = mProductList.get(position);
byte[] img = image.getImage();
Bitmap bitmap = BitmapFactory.decodeByteArray(img, 0, img.length);
pImage.setImageBitmap(bitmap);
pPrice.setText("$" + String.valueOf(mProductList.get(position).getPrice()));
pDescription.setText(mProductList.get(position).getDescription());
pCategory.setText(mProductList.get(position).getCategory());
return v;
}
}
You have ActivityNotFoundException exception. It happens because Camera.java is not registered as an activity in manifest.xml file. Try this, edit manifest.xml, add <activity android:name=".Camera"/> inside <application> opening and closing </application> tags as follows.
<application>
<!--<activity android:name=".OtherActivities"/> Declaration of other activities -->
<activity android:name=".Camera"/>
</application>
To get rid of nullpointer exception, add this inside adapter class' getView method
Button tryMe = (Button) v.findViewById(R.id.tryMe);
tryMe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent cameraIntent = new Intent(mContext, Camera.class);
mContext.startActivity(cameraIntent);
}
});
and remove button related code from your activity.
Related
am writing a body measurement app. I have been able to create the camera and it stores the image. I want to use the captured image in another activity where i called the method 'bodyMeasurement'
I really need help in achieving this. Further corrections are also welcomed. Thanks
Here is my Camera Activity;
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice=null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView)findViewById(R.id.textureView);
//From Java 1.4 , you can use keyword 'assert' to check expression true or false
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
btnCapture = (ImageButton)findViewById(R.id.btnCapture);
/* Dexter.withActivity(this)
.withPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
.withListener(new MultiplePermissionsListener() {
#Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
if (!report.areAllPermissionsGranted()) {
Toast.makeText(MainActivity.this, "You need to grant all permission to use this app features", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
}
})
.check();*/
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
takePicture();
}
});
}
private void takePicture() {
if(cameraDevice == null)
return;
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
if(characteristics != null)
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
.getOutputSizes(ImageFormat.JPEG);
//Capture image with custom size
int width = 4608;
int height = 3456;
if(jpegSizes != null && jpegSizes.length > 0)
{
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width,height,ImageFormat.JPEG,1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
outputSurface.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
//Check orientation base on device
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));
file = new File(Environment.getExternalStorageDirectory()+"/"+ ".CnatraSamp"+".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try{
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
{
if(image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try{
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
}finally {
if(outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener,mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(MainActivity.this, "Saved "+file, Toast.LENGTH_SHORT).show();
finish();
Intent i = new Intent(MainActivity.this,BlankActivity.class);
startActivity(i);
finish();
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try{
cameraCaptureSession.capture(captureBuilder.build(),captureListener,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
},mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void createCameraPreview() {
try{
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(),imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if(cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(MainActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
},null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if(cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,CaptureRequest.CONTROL_MODE_AUTO);
try{
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
cameraId = manager.getCameraIdList()[1];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[1];
//Check realtime permission if run higher API 23
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId,stateCallback,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == REQUEST_CAMERA_PERMISSION)
{
if(grantResults[0] != PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(this, "You can't use camera without permission", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if(textureView.isAvailable())
openCamera();
else
textureView.setSurfaceTextureListener(textureListener);
}
#Override
protected void onPause() {
stopBackgroundThread();
super.onPause();
}
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try{
mBackgroundThread.join();
mBackgroundThread= null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
the activity i need the image;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blank);
height = findViewById(R.id.height);
cancel = findViewById(R.id.cancel);
btnctn = findViewById(R.id.continuebtn);
cmIn = findViewById(R.id.cmIn);
height.setInputType(InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_NUMBER_FLAG_DECIMAL |
InputType.TYPE_NUMBER_FLAG_SIGNED);
btnctn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (height.getText().toString().trim().isEmpty()){
Toast.makeText(BlankActivity.this,"Please input your height..",Toast.LENGTH_LONG).show();
}else {
final ProgressDialog progressDialog = new ProgressDialog(BlankActivity.this);
progressDialog.setMessage("Getting Your Measurement");
progressDialog.setTitle("Please wait!");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show(); // Display Progress Dialog
progressDialog.setCancelable(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(BlankActivity.this, SettingsActivity.class);
startActivity(i);
progressDialog.dismiss();
}
},5000);
}
//place measurement object
bodyMeasurement();
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BlankActivity.this.finish();
Intent i = new Intent(BlankActivity.this, HomeActivity.class);
startActivity(i);
finish();
}
});
cmIn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
num = Double.parseDouble(String.valueOf(height.getText()));
in = 0.3937 * num;
String r = String.valueOf(in);
height.setText(r);
}else {
num = Double.parseDouble(String.valueOf(height.getText()));
cm = num / 0.3937;
String r = String.valueOf(cm);
height.setText(r);
}
}
});
}
private void bodyMeasurement() {
}
}
As mentioned in the comment, you can get the absolute path from the saved image and pass it through an intent to the Activity that it needs it.
To achieve this, you might want to convert your image file to a BitMap first, which will give you the actual path of the image (sometimes .getAbsolutePath() method returns a wrong file path, so it is a better solution to convert your image to a bitmap first).
This can be achieved:
String filePath = file.getPath();
Bitmap imgBitmap = BitmapFactory.decodeFile(filePath);
Then to obtain the real path of the image you saved you need to
1) Obtain the Uri of the created Bitmap:
public Uri getUri(Context context, Bitmap imgBitmap) {
ByteArrayOutputStream bOutputStream = new ByteArrayOutputStream();
String path = MediaStore.Images.Media.insertImage(context.getContentResolver(),
imgBitmap, "Title", null);
return Uri.parse(path);
}
2) Fetch the real path from Uri:
public String getRealPath(Uri uri) {
String [] proj={MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String path = cursor.getString(column_index);
cursor.close();
return path;
}
In your first activity you can pass the path of your image through an intent to the other activity, then fetch it and display it/etc.
Intent intent = new Intent(context,OtherActivity.class);
intent.putExtra("PATH",path);
startActivity(intent);
Receive the data you passed:
Intent intent = getIntent();
String path = intent.getStringExtra("PATH");
//convert the path to image/bitmap and display the image
You can also pass the entire Bitmap to the Activity you need it, but I strongly recommend that you don't, because it will use a lot of memory.
This question already has answers here:
TextureView with camera preview
(2 answers)
Closed 4 years ago.
I recently developed a special camera preview, because I needed to unmirror the default preview. The code is as follows:
public class CameraApi extends AppCompatActivity {
private static final String TAG = "CameraAPI";
protected TextureView textureView;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
private String cameraId;
protected CameraDevice cameraDevice;
protected CameraCaptureSession cameraCaptureSessions;
protected CaptureRequest captureRequest;
protected CaptureRequest.Builder captureRequestBuilder;
protected Size imageDimension;
private ImageReader imageReader;
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_full_screen);
textureView = (TextureView) findViewById(R.id.texture_revcam);
assert textureView != null;
textureView.setSurfaceTextureListener(textureListener);
}
protected TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//create a matrix to invert the x-plane, i.e undo the mirror
Matrix matrix = new Matrix();
matrix.setScale(-1, 1);
//move it back to in view otherwise it'll be off to the left.
matrix.postTranslate(width, 0);
textureView.setTransform(matrix);
//open your camera here
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Transform you image captured size according to the surface width and height
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
//This is called when the camera is open
Log.e(TAG, "onOpened");
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(CameraDevice camera) {
cameraDevice.close();
}
#Override
public void onError(CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};
final CameraCaptureSession.CaptureCallback captureCallbackListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(CameraApi.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
createCameraPreview();
}
};
protected void startBackgroundThread() {
mBackgroundThread = new HandlerThread("Camera Background");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
protected void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
protected void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
//The camera is already closed
if (null == cameraDevice) {
return;
}
// When the session is ready, we start displaying the preview.
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(CameraApi.this, "Configuration change", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Log.e(TAG, "is camera open");
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
// Add permission for camera and let user grant the permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(CameraApi.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e(TAG, "openCamera X");
}
protected void updatePreview() {
if(null == cameraDevice) {
Log.e(TAG, "updatePreview error, return");
}
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void closeCamera() {
if (null != cameraDevice) {
cameraDevice.close();
cameraDevice = null;
}
if (null != imageReader) {
imageReader.close();
imageReader = null;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// close the app
Toast.makeText(CameraApi.this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show();
finish();
}
}
}
#Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume");
startBackgroundThread();
if (textureView.isAvailable()) {
openCamera();
} else {
textureView.setSurfaceTextureListener(textureListener);
}
}
#Override
protected void onPause() {
Log.e(TAG, "onPause");
//closeCamera();
stopBackgroundThread();
super.onPause();
}
public void hideSystemUI() {
//for new api versions.
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(8);
}
public void checkCameraPermissions() {
final boolean cameraGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
final boolean audioGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;
final boolean audioNeeded = true;
String[] perms = null;
if (cameraGranted) {
if (audioNeeded && !audioGranted) {
perms = new String[]{Manifest.permission.RECORD_AUDIO};
}
} else {
if (audioNeeded && !audioGranted) {
perms = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
} else {
perms = new String[]{Manifest.permission.CAMERA};
}
}
if (perms != null) {
ActivityCompat.requestPermissions(this, perms, 69);
}
}
}
I just want to switch to fullscreen when clicking a button, but it crashes the app. I've tried something like this:
cpHover.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
AlertDialog.Builder loadingFullscreen = new Builder(IdleModeFragment.this.getContext());
loadingFullscreen.setMessage(getString(R.string.load_fullscreen));
AlertDialog dialog = loadingFullscreen.show();
Intent intent = new Intent(getContext(),CameraApi.class);
startActivity(intent);
}
});
I don't know if there's another way, in principle I would just like to create a new instance of the camera (I suppose) and then switch to another tab (meaning another window) that only has the container of that preview.
Thanks in advance!
EDIT: Log is
03-09 11:41:46.936 8432-8432/com.microlay.nanodlp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.microlay.nanodlp, PID: 8432
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.microlay.nanodlp/com.microlay.nanodlp.utils.CameraApi}; have you declared this activity in your AndroidManifest.xml?
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1777)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1501)
at android.app.Activity.startActivityForResult(Activity.java:3745)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
at android.support.v4.app.ActivityCompatJB.startActivityForResult(ActivityCompatJB.java:30)
at android.support.v4.app.ActivityCompat.startActivityForResult(ActivityCompat.java:146)
at android.support.v4.app.FragmentActivity.startActivityFromFragment(FragmentActivity.java:932)
at android.support.v4.app.FragmentActivity$HostCallbacks.onStartActivityFromFragment(FragmentActivity.java:1047)
at android.support.v4.app.Fragment.startActivity(Fragment.java:940)
at android.support.v4.app.Fragment.startActivity(Fragment.java:929)
at com.microlay.nanodlp.fragments.IdleModeFragment$2.onClick(IdleModeFragment.java:168)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:955)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:750)
EDIT 2: Black screen throws this error
03-09 13:10:52.838 28985-28985/com.microlay.nanodlp E/CameraAPI: onResume
03-09 13:10:52.852 28985-28985/com.microlay.nanodlp W/TextureView: A TextureView or a subclass can only be used with hardware acceleration enabled.
03-09 13:10:53.269 28985-28985/com.microlay.nanodlp E/WindowManager: android.view.WindowLeaked: Activity com.microlay.nanodlp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{24cf85c6 V.E..... R.....I. 0,0-520,77} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:363)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:271)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
at android.app.Dialog.show(Dialog.java:298)
at android.app.AlertDialog$Builder.show(AlertDialog.java:993)
at com.microlay.nanodlp.fragments.IdleModeFragment$2.onClick(IdleModeFragment.java:166)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:955)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:750)
As written in error log you haven't declared your activity in your manifest.
Add this line in your manifest.xml
<activity android:name="utils.CameraApi" />
As I have explained in my comment, you should not display a dialog, then start another Activity. That is what the WindowLeaked message is all about. To avoid it, you should dismiss any dialogs that are open – or not open this one at all:
AlertDialog.Builder loadingFullscreen = new Builder(IdleModeFragment.this.getContext());
loadingFullscreen.setMessage(getString(R.string.load_fullscreen));
AlertDialog dialog = loadingFullscreen.show();
If you really want to show a dialog, then launch the other Activity, you could do it like this:
Intent intent = new Intent(getContext(), CameraApi.class);
new AlertDialog.Builder(this)
.setMessage(getString(R.string.load_fullscreen))
.setPositiveButton("OK", (dialog, which) -> startActivity(intent);)
.setNegativeButton(null, null).create().show();
Once the user dismisses the dialog, the other Activity will launch. Thus no window will be leaked.
I am trying to create an application which takes a photo without showing a preview. Using this tutorial- https://www.youtube.com/watch?v=oPu42I0HSi4 I managed to make it work if I use and Activity. Now I am trying to move the code that handles the picture-taking action into and IntentService.
and this is what I got so far:
MainActivity.java - Activity
private void startCameraService()
{
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},REQUEST_CAMERA_PERMISSION);
return;
}
Intent cameraService = new Intent(this, CameraService.class);
startService(cameraService);
}
CameraService.java - (Intent Service)
public class CameraService extends IntentService {
//Input image state
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static{
ORIENTATIONS.append(Surface.ROTATION_90,90);
ORIENTATIONS.append(Surface.ROTATION_0,0);
ORIENTATIONS.append(Surface.ROTATION_180,270);
ORIENTATIONS.append(Surface.ROTATION_270,180);
}
//Camera variables
private String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSessions;
private CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
private ImageReader imageReader;
//Output file variables
private File file;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private boolean mFlashSupported;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
//the orientation of the device
int rotation;
//bitmap of the taken photo
private Bitmap bitmapImage;
//camera state callback
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice=null;
}
};
public CameraService() {
super("CameraService");
}
#Override
protected void onHandleIntent(Intent intent)
{
takePicture();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void takePicture() {
Log.d("CameraService","inside TakePicture");
if(cameraDevice == null)
{
return;
}
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
if(characteristics != null)
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
.getOutputSizes(ImageFormat.JPEG);
//Capture image with custom size
int width = 640;
int height = 480;
if(jpegSizes != null && jpegSizes.length > 0)
{
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
}
final ImageReader reader = ImageReader.newInstance(width,height,ImageFormat.JPEG,1);
List<Surface> outputSurface = new ArrayList<>(2);
outputSurface.add(reader.getSurface());
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
File file = new File(Environment.getExternalStorageDirectory() + "/"+UUID.randomUUID().toString()+".jpg");
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader imageReader) {
Image image = null;
try{
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
bitmapImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, null);
//TODO: fix the orientation so despite the phone position the photo is always correct and not rotated
// use ORIENTATIONS.get(rotation)
bitmapImage = rotateImage(bitmapImage, 270);
}
catch (Exeption e)
{
e.printStackTrace();
}
finally {
{
if(image != null)
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream outputStream = null;
try{
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
}finally {
if(outputStream != null)
outputStream.close();
}
}
};
reader.setOnImageAvailableListener(readerListener,mBackgroundHandler);
final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Log.d("CameraService","image is saved");
}
};
cameraDevice.createCaptureSession(outputSurface, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
try{
cameraCaptureSession.capture(captureBuilder.build(),captureListener,mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
}
},mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void openCamera() {
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
try{
cameraId = manager.getCameraIdList()[1];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
manager.openCamera(cameraId,stateCallback,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
My problem is that, when I call the service the cameraDevice is null. It should be populated here:
//camera state callback
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
}
but CameraDevice camera is null.
Any suggestions why this is working as an Activity and not as an IntentService? I would much appreciate it if you could help me
After calling onHandleIntent(), stopSelf() is called. So service is stopped by the time camera events come. I guess you have to somehow keep the Looper.loop() running within your onHandleIntent().
i have problem to build screen recording function when we are on video calling. i mean i want to start record screen and video calling at the same time. try to combine source code between this https://www.simplifiedcoding.net/video-call-android-tutorial/ and this http://www.truiton.com/2015/05/capture-record-android-screen-using-mediaprojection-apis/ but app suddenly crash when start record screen while on video call.
the code shown below
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != REQUEST_CODE) {
Log.e(TAG, "Unknown request code: " + requestCode);
return;
}
if (resultCode != RESULT_OK) {
Toast.makeText(this,
"Screen Cast Permission Denied", Toast.LENGTH_SHORT).show();
mToggleButton.setChecked(false);
return;
}
mMediaProjectionCallback = new MediaProjectionCallback();
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
mMediaProjection.registerCallback(mMediaProjectionCallback, null);
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
and this is the logcat
11-14 16:51:55.265 13200-13200/com.example.prasetyo.videocallapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.prasetyo.videocallapp, PID: 13200
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1000, result=-1, data=Intent { (has extras) }} to activity {com.example.prasetyo.videocallapp/com.example.prasetyo.videocallapp.Activities.CallScreenActivity}: java.lang.IllegalStateException
at android.app.ActivityThread.deliverResults(ActivityThread.java:3574)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3617)
at android.app.ActivityThread.access$1300(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.IllegalStateException
at android.media.MediaRecorder.start(Native Method)
at com.example.prasetyo.videocallapp.Activities.CallScreenActivity.onActivityResult(CallScreenActivity.java:214)
at android.app.Activity.dispatchActivityResult(Activity.java:6192)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3570)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3617)
at android.app.ActivityThread.access$1300(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
and last, this is the full java class
public class CallScreenActivity extends BaseActivity {
static final String TAG = CallScreenActivity.class.getSimpleName();
static final String CALL_START_TIME = "callStartTime";
static final String ADDED_LISTENER = "addedListener";
private AudioPlayer mAudioPlayer;
private Timer mTimer;
private UpdateCallDurationTask mDurationTask;
private String mCallId;
private long mCallStart = 0;
private boolean mAddedListener = false;
private boolean mVideoViewsAdded = false;
private TextView mCallDuration;
private TextView mCallState;
private TextView mCallerName;
private static final int REQUEST_CODE = 1000;
private int mScreenDensity;
private MediaProjectionManager mProjectionManager;
private static final int DISPLAY_WIDTH = 720;
private static final int DISPLAY_HEIGHT = 1280;
private MediaProjection mMediaProjection;
private VirtualDisplay mVirtualDisplay;
private MediaProjectionCallback mMediaProjectionCallback;
private ToggleButton mToggleButton;
private MediaRecorder mMediaRecorder;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private static final int REQUEST_PERMISSIONS = 10;
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
private class UpdateCallDurationTask extends TimerTask {
#Override
public void run() {
CallScreenActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
updateCallDuration();
}
});
}
}
#Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putLong(CALL_START_TIME, mCallStart);
savedInstanceState.putBoolean(ADDED_LISTENER, mAddedListener);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
mCallStart = savedInstanceState.getLong(CALL_START_TIME);
mAddedListener = savedInstanceState.getBoolean(ADDED_LISTENER);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call_screen);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mScreenDensity = metrics.densityDpi;
mMediaRecorder = new MediaRecorder();
mProjectionManager = (MediaProjectionManager) getSystemService
(Context.MEDIA_PROJECTION_SERVICE);
mAudioPlayer = new AudioPlayer(this);
mCallDuration = (TextView) findViewById(R.id.callDuration);
mCallerName = (TextView) findViewById(R.id.remoteUser);
mCallState = (TextView) findViewById(R.id.callState);
ImageButton endCallButton = (ImageButton) findViewById(R.id.hangupButton);
mToggleButton = (ToggleButton) findViewById(R.id.toggle);
mToggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(CallScreenActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) + ContextCompat
.checkSelfPermission(CallScreenActivity.this,
Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale
(CallScreenActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
ActivityCompat.shouldShowRequestPermissionRationale
(CallScreenActivity.this, Manifest.permission.RECORD_AUDIO)) {
mToggleButton.setChecked(false);
Snackbar.make(findViewById(android.R.id.content), R.string.label_permissions,
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
new View.OnClickListener() {
#Override
public void onClick(View v) {
ActivityCompat.requestPermissions(CallScreenActivity.this,
new String[]{Manifest.permission
.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO},
REQUEST_PERMISSIONS);
}
}).show();
} else {
ActivityCompat.requestPermissions(CallScreenActivity.this,
new String[]{Manifest.permission
.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO},
REQUEST_PERMISSIONS);
}
} else {
onToggleScreenShare(v);
}
}
});
mCallId = getIntent().getStringExtra(SinchService.CALL_ID);
if (savedInstanceState == null) {
mCallStart = System.currentTimeMillis();
}
endCallButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
endCall();
mToggleButton.setChecked(false);
onToggleScreenShare(mToggleButton);
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != REQUEST_CODE) {
Log.e(TAG, "Unknown request code: " + requestCode);
return;
}
if (resultCode != RESULT_OK) {
Toast.makeText(this,
"Screen Cast Permission Denied", Toast.LENGTH_SHORT).show();
mToggleButton.setChecked(false);
return;
}
mMediaProjectionCallback = new MediaProjectionCallback();
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
mMediaProjection.registerCallback(mMediaProjectionCallback, null);
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
public void onToggleScreenShare(View view) {
if (((ToggleButton) view).isChecked()) {
initRecorder();
shareScreen();
} else {
mMediaRecorder.stop();
mMediaRecorder.reset();
Log.v(TAG, "Stopping Recording");
stopScreenSharing();
}
}
private void shareScreen() {
if (mMediaProjection == null) {
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
return;
}
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
private VirtualDisplay createVirtualDisplay() {
return mMediaProjection.createVirtualDisplay("CallScreenActivity",
DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null /*Callbacks*/, null
/*Handler*/);
}
private void initRecorder() {
try {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setOutputFile(Environment
.getExternalStorageDirectory().getAbsolutePath() + "/video.mp4");
mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncodingBitRate(512 * 1000);
mMediaRecorder.setVideoFrameRate(30);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int orientation = ORIENTATIONS.get(rotation + 90);
mMediaRecorder.setOrientationHint(orientation);
mMediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
private class MediaProjectionCallback extends MediaProjection.Callback {
#Override
public void onStop() {
if (mToggleButton.isChecked()) {
mToggleButton.setChecked(false);
mMediaRecorder.stop();
mMediaRecorder.reset();
Log.v(TAG, "Recording Stopped");
}
mMediaProjection = null;
stopScreenSharing();
}
}
private void stopScreenSharing() {
if (mVirtualDisplay == null) {
return;
}
mVirtualDisplay.release();
//mMediaRecorder.release(); //If used: mMediaRecorder object cannot
// be reused again
destroyMediaProjection();
}
#Override
public void onDestroy() {
super.onDestroy();
destroyMediaProjection();
}
private void destroyMediaProjection() {
if (mMediaProjection != null) {
mMediaProjection.unregisterCallback(mMediaProjectionCallback);
mMediaProjection.stop();
mMediaProjection = null;
}
Log.i(TAG, "MediaProjection Stopped");
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[],
#NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSIONS: {
if ((grantResults.length > 0) && (grantResults[0] +
grantResults[1]) == PackageManager.PERMISSION_GRANTED) {
onToggleScreenShare(mToggleButton);
} else {
mToggleButton.setChecked(false);
Snackbar.make(findViewById(android.R.id.content), R.string.label_permissions,
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);
}
}).show();
}
return;
}
}
}
#Override
public void onServiceConnected() {
Call call = getSinchServiceInterface().getCall(mCallId);
if (call != null) {
if (!mAddedListener) {
call.addCallListener(new SinchCallListener());
mAddedListener = true;
}
} else {
Log.e(TAG, "Started with invalid callId, aborting.");
finish();
}
updateUI();
}
//method to update video feeds in the UI
private void updateUI() {
if (getSinchServiceInterface() == null) {
return; // early
}
Call call = getSinchServiceInterface().getCall(mCallId);
if (call != null) {
mCallerName.setText(call.getRemoteUserId());
mCallState.setText(call.getState().toString());
if (call.getState() == CallState.ESTABLISHED) {
//when the call is established, addVideoViews configures the video to be shown
addVideoViews();
}
}
}
//stop the timer when call is ended
#Override
public void onStop() {
super.onStop();
mDurationTask.cancel();
mTimer.cancel();
removeVideoViews();
}
//start the timer for the call duration here
#Override
public void onStart() {
super.onStart();
mTimer = new Timer();
mDurationTask = new UpdateCallDurationTask();
mTimer.schedule(mDurationTask, 0, 500);
updateUI();
}
#Override
public void onBackPressed() {
// User should exit activity by ending call, not by going back.
}
//method to end the call
private void endCall() {
mAudioPlayer.stopProgressTone();
Call call = getSinchServiceInterface().getCall(mCallId);
if (call != null) {
call.hangup();
}
finish();
}
private String formatTimespan(long timespan) {
long totalSeconds = timespan / 1000;
long minutes = totalSeconds / 60;
long seconds = totalSeconds % 60;
return String.format(Locale.US, "%02d:%02d", minutes, seconds);
}
//method to update live duration of the call
private void updateCallDuration() {
if (mCallStart > 0) {
mCallDuration.setText(formatTimespan(System.currentTimeMillis() - mCallStart));
}
}
//method which sets up the video feeds from the server to the UI of the activity
private void addVideoViews() {
if (mVideoViewsAdded || getSinchServiceInterface() == null) {
return; //early
}
final VideoController vc = getSinchServiceInterface().getVideoController();
if (vc != null) {
RelativeLayout localView = (RelativeLayout) findViewById(R.id.localVideo);
localView.addView(vc.getLocalView());
localView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//this toggles the front camera to rear camera and vice versa
vc.toggleCaptureDevicePosition();
}
});
LinearLayout view = (LinearLayout) findViewById(R.id.remoteVideo);
view.addView(vc.getRemoteView());
mVideoViewsAdded = true;
}
}
//removes video feeds from the app once the call is terminated
private void removeVideoViews() {
if (getSinchServiceInterface() == null) {
return; // early
}
VideoController vc = getSinchServiceInterface().getVideoController();
if (vc != null) {
LinearLayout view = (LinearLayout) findViewById(R.id.remoteVideo);
view.removeView(vc.getRemoteView());
RelativeLayout localView = (RelativeLayout) findViewById(R.id.localVideo);
localView.removeView(vc.getLocalView());
mVideoViewsAdded = false;
}
}
private class SinchCallListener implements VideoCallListener {
#Override
public void onCallEnded(Call call) {
CallEndCause cause = call.getDetails().getEndCause();
Log.d(TAG, "Call ended. Reason: " + cause.toString());
mAudioPlayer.stopProgressTone();
setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
String endMsg = "Call ended: " + call.getDetails().toString();
Toast.makeText(CallScreenActivity.this, endMsg, Toast.LENGTH_LONG).show();
endCall();
mToggleButton.setChecked(false);
onToggleScreenShare(mToggleButton);
}
#Override
public void onCallEstablished(Call call) {
Log.d(TAG, "Call established");
mAudioPlayer.stopProgressTone();
mCallState.setText(call.getState().toString());
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
AudioController audioController = getSinchServiceInterface().getAudioController();
audioController.enableSpeaker();
mCallStart = System.currentTimeMillis();
Log.d(TAG, "Call offered video: " + call.getDetails().isVideoOffered());
}
#Override
public void onCallProgressing(Call call) {
Log.d(TAG, "Call progressing");
mAudioPlayer.playProgressTone();
}
#Override
public void onShouldSendPushNotification(Call call, List pushPairs) {
// Send a push through your push provider here, e.g. GCM
}
#Override
public void onVideoTrackAdded(Call call) {
Log.d(TAG, "Video track added");
addVideoViews();
}
}
}
hope someone can help me, thanksa lot!
I was facing the same issue.
java.lang.IllegalStateException is due to that you are accessing the main thread view from another thread, // Play dial tones mDialTone.start();, which is giving the exception. Just call initRecorder() on main thread. It will resolve your problem.
I've been trying for hours now, still can't seem to get this to work..
Using this as reference. I coded an application that records and saves a video. I have no problems running the reference application but many issues occurred when i ran my own application.
Issue:
The application have no issues recording video, saving the video, etc. However after recording and saving the first video, if i try to record a second video it crashes. The second error is supposedly caused by MediaRecorder: prepare failed: -2147483648, which in turned caused a IllegalStateException.(Log below) How do I go about solving this issue?
Manifest Permissions:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-feature android:name="android.hardware.camera2.full" />
Code:
public class VideoCapture extends AppCompatActivity {
static final int REQUEST_CODE_CAMERA = 0;
static final int REQUEST_CODE_EXTERNAL_WRITE = 1;
static final int REQUEST_CODE_MICROPHONE = 2;
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);
}
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()));
}
}
File videoFolder;
File videoFile;
ImageButton recordButton;
Chronometer chronometer;
String cameraID;
MediaRecorder mediaRecorder;
Size previewSize;
Size videoSize;
int totalRotation;
boolean isRecording;
HandlerThread backgroundHandlerThread;
Handler backgroundHandler;
CaptureRequest.Builder captureRequestBuilder;
CameraCaptureSession previewCaptureSession;
CameraCaptureSession recordCaptureSession;
TextureView textureView;
TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
setupCamera(width, height);
startCamera();
Log.e("onSurfaceTextureAvail", "startCamera width:"+String.valueOf(width)+" height" +String.valueOf(height));
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
Log.e("onSurfaceTextureDestroy","Surface destroyed" + String.valueOf(surface));
return false;
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
Log.e("onSurfaceTextureSizeCha","Surface changed" + String.valueOf(surface) +"width" +String.valueOf(width)+" height" +String.valueOf(height));
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
CameraDevice cameraDevice;
CameraDevice.StateCallback cameraDeviceStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
cameraDevice = camera;
mediaRecorder = new MediaRecorder();
Log.e("cameraDeviceStateCalbac","onOpened mediaRecorder = new MediaRecorder(); camera:"+String.valueOf(camera));
/**
* Application will "Reset" when granting write storage permission and call onPause and onResume.
* The check is to ensure that the camera will correctly follow up with start record.
**/
Log.e("cameraDeviceStateCalbac", "onOpened calling startPreview");
startPreview();
}
#Override
public void onDisconnected(CameraDevice camera) {
Log.e("cameraDeviceStateCalbac", "onDisconnected closing camera" + String.valueOf(camera));
camera.close();
cameraDevice = null;
Log.e("cameraDeviceStateCalbac", "onDisconnected nulling camera to value:" + String.valueOf(cameraDevice));
}
#Override
public void onError(CameraDevice camera, int error) {
Log.e("cameraDeviceStateCalbac", "onError closing camera" + String.valueOf(camera)+"Error value: "+String.valueOf(error));
camera.close();
cameraDevice = null;
Log.e("cameraDeviceStateCalbac", "onError nulling camera to value:" + String.valueOf(cameraDevice));
}
};
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
finish();
}
return super.onKeyDown(keyCode, event);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_videocapture);
Log.e("onCreate", "Running");
if (checkCameraPermission() != PackageManager.PERMISSION_GRANTED) requestCameraPermission();
if (checkWriteExternalStoragePermission() != PackageManager.PERMISSION_GRANTED)
requestWriteExternalStoragePermission();
if (checkMicrophonePermission() != PackageManager.PERMISSION_GRANTED)
requestMicrophonePermission();
Log.e("onCreate", "Calling createVideoFolder");
createVideoFolder();
isRecording = false;
Log.e("onCreate", "setting isRecording Value" + String.valueOf(isRecording));
// Chronometer is the timer during a video recording
chronometer = (Chronometer) findViewById(R.id.chronometer);
// TextureView is the container that displays the preview
textureView = (TextureView) findViewById(R.id.textureView);
// Set up video capture click handler
recordButton = (ImageButton) findViewById(R.id.recordButton);
Log.e("onCreate", "recordButton setOnClickListener");
recordButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) // Record/Stop button click
{
Log.e("recordOnClick","RUNNING");
if (!isRecording) // Start Recording
{
Log.e("recordOnClick","isRecording = false");
if (checkCameraPermission() == PackageManager.PERMISSION_GRANTED &&
checkWriteExternalStoragePermission() == PackageManager.PERMISSION_GRANTED) {
try {
isRecording = true;
Log.e("recordOnClick"," set isRecording = true. Final value: "+String.valueOf(isRecording));
recordButton.setImageResource(R.mipmap.btn_video_busy);
Log.e("recordOnClick", "Calling createVideoFile()");
createVideoFile();
Log.e("recordOnClick", "Calling startRecord()");
startRecord();
Log.e("recordOnClick", "Calling mediaRecorder.start()");
mediaRecorder.start();
Log.e("recordOnClick", "If you see this, mediaRecorder.start() passed.");
chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.setVisibility(View.VISIBLE);
chronometer.start();
} catch (IllegalArgumentException iaEx) {
Log.e("recordOnClick","click to record failed.");
StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
iaEx.printStackTrace(printWriter);
printWriter.flush();
String stackTrace = writer.toString();
Toast.makeText(getApplicationContext(), stackTrace, Toast.LENGTH_LONG).show();
} catch (IOException ex) {
Log.e("recordOnClick","click to record failed.");
}
}
} else // Stop recording
{
Log.e("recordOnClick","isRecording = true");
isRecording = false;
Log.e("recordOnClick"," set isRecording = false. Final value: "+String.valueOf(isRecording));
chronometer.stop();
chronometer.setVisibility(View.INVISIBLE);
recordButton.setImageResource(R.mipmap.btn_video_online);
Log.e("recordOnClick","Calling mediaRecorder.stop()");
mediaRecorder.stop();
Log.e("recordOnClick", "If you see this, mediaRecorder.stop() passed.");
Log.e("recordOnClick","Calling mediaRecorder.reset()");
mediaRecorder.reset();
Log.e("recordOnClick", "If you see this, mediaRecorder.reset() passed.");
Intent mediaStoreUpdateIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaStoreUpdateIntent.setData(Uri.fromFile(videoFile));
sendBroadcast(mediaStoreUpdateIntent);
Log.e("recordOnClick","Calling startPreview()");
startPreview();
Log.e("recordOnClick", "If you see this, startPreview() passed.");
Intent intent = new Intent(VideoCapture.this, FrameExtraction.class);
intent.putExtra("videoUri", Uri.fromFile(videoFile));
Log.e("recordOnClick","Video Uri Saved" + String.valueOf(Uri.fromFile(videoFile)));
startActivity(intent);
finish();
}
}
});
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE_CAMERA)
{
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Application will not be able to capture videos without camera permission.", Toast.LENGTH_SHORT).show();
}
} else if (requestCode == REQUEST_CODE_EXTERNAL_WRITE)
{
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Application doesn't have write permission. Videos cannot be saved.", Toast.LENGTH_SHORT).show();
}
} else if (requestCode == REQUEST_CODE_MICROPHONE) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Application doesn't have microphone permission. Videos will have no audio.", Toast.LENGTH_SHORT).show();
}
}
}
#Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if (textureView.isAvailable()) {
setupCamera(textureView.getWidth(), textureView.getHeight());
startCamera();
Log.e("RESUME", "RESUME STARTCAMERA");
} else {
textureView.setSurfaceTextureListener(surfaceTextureListener);
Log.e("RESUME", "ELSE, SET TEXTURE LISTENER");
}
}
#Override
protected void onPause() {
Log.e("PAUSE", "PAUSE CloseCAMERA");
cameraDevice.close();
cameraDevice = null;
stopBackgroundThread();
super.onPause();
}
#Override
public void onWindowFocusChanged(boolean hasFocas) {
super.onWindowFocusChanged(hasFocas);
View decorView = getWindow().getDecorView();
if (hasFocas) {
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 setupCamera(int width, int height) {
Log.e("setupCamera","RUNNING");
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
identification number
for (String currentCameraId : cameraManager.getCameraIdList()) {
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(currentCameraId);
if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT)
continue;
int deviceOrientation = getWindowManager().getDefaultDisplay().getRotation();
totalRotation = sensorToDeviceRotation(cameraCharacteristics, deviceOrientation);
boolean swapRotation = totalRotation == 90 || totalRotation == 270;
int rotatedWidth = width;
int rotatedHeight = height;
if (swapRotation) {
rotatedWidth = height;
rotatedHeight = width;
}
StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedWidth, rotatedHeight);
videoSize = chooseOptimalSize(map.getOutputSizes(MediaRecorder.class), rotatedWidth, rotatedHeight);
cameraID = currentCameraId;
return;
}
} catch (CameraAccessException e) {
}
}
private int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics, int deviceOrientation) {
int sensorOrienatation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
deviceOrientation = ORIENTATIONS.get(deviceOrientation);
return (sensorOrienatation + deviceOrientation + 360) % 360;
}
private Size chooseOptimalSize(Size[] choices, int width, int height) {
List<Size> bigEnough = new ArrayList<>();
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, new CompareSizeByArea());
} else {
return choices[0];
}
}
private void startCamera() {
Log.e("startCamera()","RUNNING");
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkCameraPermission() == PackageManager.PERMISSION_GRANTED)
cameraManager.openCamera(cameraID, cameraDeviceStateCallback, backgroundHandler);
else {
requestCameraPermission();
}
} else
cameraManager.openCamera(cameraID, cameraDeviceStateCallback, backgroundHandler);
} catch (CameraAccessException e) {
Log.e("startCamera()", "Failed to cameraManager.openCamera" + String.valueOf(e));
}
}
private void startPreview() {
Log.e("startPreview","RUNNING");
SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
try {
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(previewSurface);
cameraDevice.createCaptureSession(Arrays.asList(previewSurface),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
previewCaptureSession = session;
try {
previewCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler);
} catch (CameraAccessException e) {
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.e("startPreview", "onConfigureFailed");
}
}, null);
} catch (CameraAccessException e) {
Log.e("startPreviewCATCH", "StartPreview FAILED CATCH: " + String.valueOf(e));
}
}
private void startRecord() {
try {
Log.e("startRecord", "RUNNING");
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(videoFile.getAbsolutePath());
mediaRecorder.setVideoEncodingBitRate(1000000);
mediaRecorder.setVideoFrameRate(60);
mediaRecorder.setVideoSize(videoSize.getWidth(), videoSize.getHeight());
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setOrientationHint(totalRotation);
}catch(Exception e){
}
try {
mediaRecorder.prepare();
Log.e("startRecord","mediaRecorder.prepare()");
SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
Surface recordSurface = mediaRecorder.getSurface();
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
captureRequestBuilder.addTarget(previewSurface);
captureRequestBuilder.addTarget(recordSurface);
cameraDevice.createCaptureSession(Arrays.asList(previewSurface, recordSurface),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
recordCaptureSession = session;
try {
recordCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
}
}, null);
} catch (IOException ioEx) {
Log.e("prepare Failed", String.valueOf(ioEx));
} // mediaRecorder.prepare()
catch (CameraAccessException caEx) {
} // cameraDevice.createCaptureSession()
}
private void closeCamera() {
if (cameraDevice != null) {
cameraDevice.close();
cameraDevice = null;
}
if (mediaRecorder != null) {
mediaRecorder.reset();
Log.e("closeCamera()","mediaRecorder.reset()");
mediaRecorder = null;
Log.e("closeCamera()","mediaRecorder = null");
}
}
private int checkCameraPermission() {
return ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA);
}
private int checkWriteExternalStoragePermission() {
return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
private int checkMicrophonePermission() {
return ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO);
}
private void requestCameraPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_CAMERA);
}
private void requestWriteExternalStoragePermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_EXTERNAL_WRITE);
}
private void requestMicrophonePermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_CODE_MICROPHONE);
}
private void createVideoFolder() {
// Create the folder for video files to be written to if it doesn't exist.
// Battery Videos is the folder name created under the movies public directory.
Log.e("createVideoFolder", "RUNNING");
videoFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "Battery Videos");
if (!videoFolder.exists()) videoFolder.mkdirs();
}
private File createVideoFile() throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fileName = "Video_" + timestamp + ".mp4";
videoFile = new File(videoFolder, fileName);
return videoFile;
}
private void startBackgroundThread() {
backgroundHandlerThread = new HandlerThread("Camera2VideoImage");
backgroundHandlerThread.start();
backgroundHandler = new Handler(backgroundHandlerThread.getLooper());
}
private void stopBackgroundThread() {
backgroundHandlerThread.quitSafely();
try {
backgroundHandlerThread.join();
backgroundHandlerThread = null;
backgroundHandler = null;
} catch (InterruptedException e) {
}
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.e("onDestroy", "It Happened");
mediaRecorder.release();
}
}
Stack Trace in startRecord():
W/System.err: java.io.IOException: prepare failed.
W/System.err: at android.media.MediaRecorder._prepare(Native Method)
W/System.err: at android.media.MediaRecorder.prepare(MediaRecorder.java:782)
W/System.err: at com.application.batterysoc.activity.VideoCapture.startRecord(VideoCapture.java:490)
W/System.err: at com.application.batterysoc.activity.VideoCapture.access$600(VideoCapture.java:55)
W/System.err: at com.application.batterysoc.activity.VideoCapture$3.onClick(VideoCapture.java:214)
W/System.err: at android.view.View.performClick(View.java:4861)
W/System.err: at android.view.View$PerformClick.run(View.java:19980)
W/System.err: at android.os.Handler.handleCallback(Handler.java:739)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err: at android.os.Looper.loop(Looper.java:211)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5373)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at java.lang.reflect.Method.invoke(Method.java:372)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815)
E/recordOnClick: Calling mediaRecorder.start()
I've solved the issue, with reference from this site
by removing the line mediaRecorder.setVideoFrameRate(60);
The application now runs without any issues.