Hi Cedric,
Did you also make sure to enable camera in the app settings as well?
Thanks
Eva
E/AndroidRuntime: FATAL EXCEPTION: main Process: wikitude.wikitudedemo, PID: 7203 java.lang.RuntimeException: Unable to start activity ComponentInfo{wikitude.wikitudedemo/wikitude.wikitudedemo.MainActivity}: android.util.AndroidRuntimeException: requestFeature() must be called before adding content at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5258) 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: android.util.AndroidRuntimeException: requestFeature() must be called before adding content at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:302) at android.app.Activity.requestWindowFeature(Activity.java:3605) at wikitude.wikitudedemo.MainActivity.onCreate(MainActivity.java:47) at android.app.Activity.performCreate(Activity.java:5994) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5258) 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)New main
package wikitude.wikitudedemo; import android.app.Activity; import android.graphics.PixelFormat; import android.hardware.Camera; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.Window; import android.view.WindowManager; import java.io.IOException; import com.wikitude.architect.ArchitectStartupConfiguration; import com.wikitude.architect.WearableArchitectView; public class MainActivity extends Activity implements SurfaceHolder.Callback { private WearableArchitectView architectView; private Camera camera; private SurfaceView surfaceCamera; private Boolean isPreview; @Override protected void onPostCreate(final Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); architectView.onPostCreate(); try { architectView.load("index.html"); }catch (IOException e){ e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); architectView = new WearableArchitectView(this); ArchitectStartupConfiguration configuration = new ArchitectStartupConfiguration(); configuration.setLicenseKey("2F40U/M96j4r6kbDJxSZtmu21Ue39TjMImJJrSY/4PBmXpXXCHiWLVyJMeIouODKzgZopK6BdWnPlAybo3Y5ccKZoqv2yoaRSri+38e6ORkyhVqrvn5g5RDBFg79h2ykm31ZOvlNSH9ohwU9dgQgk7gXIVPeuG2jxpo1+VAESuRTYWx0ZWRfX6FAccwFGifIuaPv8Wv07BRiZlLI/ANcanfHUMcN2DqSpc+paOi7inK5bSeW7l8cCFQA+UONJn7xLJnNqP/u2CdhJO5wPcxygb/NAN+0z+hiJlahwqS6mGIwVB5BnUJS/0YYZYfSA2tshmnRSyP9kb/xsyVQl8bhFLE+Fs1PX59vBYa8bhMVpG7aJiFQLq1JU7KYndKp4MMKUDjKICIT094Px//CAbKB5jXBuh1GmGndzNm0VBZbgNiF3iIV0e83wyFaWg34W63aNNX2qGd0VWv8rakacVJjBjoBNFw0EDZQMaQqR1PFSS2jg1rApQ325bZMXFKJefYXu9/5D4reNsErQT9tMDCFq4jt7HaFPqYLH+YNTEOakG13VyNdI5lA2Fwmk9Glt9SDJucllIeaoZ2yCvhLkgIqMVQ6adYm4/GFzsYUi5ouvK84S6fW69ErgoyhxlCuktB1FY5/4V7R5xzznOrEUbTGLfFmE9TCTEIFcqQy1P7t2Bo="); architectView.onCreate(configuration); setContentView(architectView); getWindow().setFormat(PixelFormat.TRANSLUCENT); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); isPreview = false; setContentView(R.layout.layout); surfaceCamera = (SurfaceView) findViewById(R.id.surfaceViewCamera); InitializeCamera(); } @Override protected void onResume(){ super.onResume(); architectView.onResume(); camera = Camera.open(); } @Override protected void onPause(){ super.onPause(); architectView.onPause(); } @Override protected void onDestroy(){ super.onDestroy(); architectView.onDestroy(); } public void InitializeCamera() { surfaceCamera.getHolder().addCallback(this); surfaceCamera.getHolder().setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } @Override public void surfaceCreated(SurfaceHolder holder) { if (camera == null) camera = Camera.open(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (isPreview) { camera.stopPreview(); } Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(width, height); camera.setParameters(parameters); try { camera.setPreviewDisplay(surfaceCamera.getHolder()); } catch (IOException e) { } camera.startPreview(); isPreview = true; } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { camera.stopPreview(); isPreview = false; camera.release(); } } }
Thanks
import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.params.StreamConfigurationMap; import android.media.Image; import android.media.ImageReader; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.util.Size; import android.util.SparseIntArray; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.widget.Button; import android.widget.Toast; import com.inducesmile.androidcameraapi2.R; import com.wikitude.architect.ArchitectStartupConfiguration; import com.wikitude.architect.WearableArchitectView; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MainActivity extends AppCompatActivity { private static final String TAG = "AndroidCameraApi"; private Button takePictureButton; private 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; private 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; private WearableArchitectView architectView; @Override protected void onPostCreate(final Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); architectView.onPostCreate(); try { architectView.load("index.html"); }catch (IOException e){ e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textureView = (TextureView) findViewById(R.id.texture); assert textureView != null; textureView.setSurfaceTextureListener(textureListener); takePictureButton = (Button) findViewById(R.id.btn_takepicture); assert takePictureButton != null; takePictureButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { takePicture(); } }); architectView = new WearableArchitectView(this); ArchitectStartupConfiguration configuration = new ArchitectStartupConfiguration(); configuration.setLicenseKey("2F40U/M96j4r6kbDJxSZtmu21Ue39TjMImJJrSY/4PBmXpXXCHiWLVyJMeIouODKzgZopK6BdWnPlAybo3Y5ccKZoqv2yoaRSri+38e6ORkyhVqrvn5g5RDBFg79h2ykm31ZOvlNSH9ohwU9dgQgk7gXIVPeuG2jxpo1+VAESuRTYWx0ZWRfX6FAccwFGifIuaPv8Wv07BRiZlLI/ANcanfHUMcN2DqSpc+paOi7inK5bSeW7l8cCFQA+UONJn7xLJnNqP/u2CdhJO5wPcxygb/NAN+0z+hiJlahwqS6mGIwVB5BnUJS/0YYZYfSA2tshmnRSyP9kb/xsyVQl8bhFLE+Fs1PX59vBYa8bhMVpG7aJiFQLq1JU7KYndKp4MMKUDjKICIT094Px//CAbKB5jXBuh1GmGndzNm0VBZbgNiF3iIV0e83wyFaWg34W63aNNX2qGd0VWv8rakacVJjBjoBNFw0EDZQMaQqR1PFSS2jg1rApQ325bZMXFKJefYXu9/5D4reNsErQT9tMDCFq4jt7HaFPqYLH+YNTEOakG13VyNdI5lA2Fwmk9Glt9SDJucllIeaoZ2yCvhLkgIqMVQ6adYm4/GFzsYUi5ouvK84S6fW69ErgoyhxlCuktB1FY5/4V7R5xzznOrEUbTGLfFmE9TCTEIFcqQy1P7t2Bo="); architectView.onCreate(configuration); setContentView(architectView); } TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { //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(MainActivity.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 takePicture() { if(null == cameraDevice) { Log.e(TAG, "cameraDevice is 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); } int width = 640; int height = 480; if (jpegSizes != null && 0 < jpegSizes.length) { width = jpegSizes[0].getWidth(); height = jpegSizes[0].getHeight(); } ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1); List<Surface> outputSurfaces = new ArrayList<Surface>(2); outputSurfaces.add(reader.getSurface()); outputSurfaces.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); // Orientation int rotation = getWindowManager().getDefaultDisplay().getRotation(); captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); final File file = new File(Environment.getExternalStorageDirectory()+"/pic.jpg"); ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { 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 output = null; try { output = new FileOutputStream(file); output.write(bytes); } finally { if (null != output) { output.close(); } } } }; reader.setOnImageAvailableListener(readerListener, mBackgroundHandler); final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { super.onCaptureCompleted(session, request, result); Toast.makeText(MainActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show(); createCameraPreview(); } }; cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession session) { try { session.capture(captureBuilder.build(), captureListener, mBackgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(CameraCaptureSession session) { } }, mBackgroundHandler); } catch (CameraAccessException 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(MainActivity.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(MainActivity.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(MainActivity.this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show(); finish(); } } } @Override protected void onResume() { super.onResume(); architectView.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(); architectView.onPause(); } }
Hi Cedric,
In the MainActivity of your first post you are missing runtime permissions for the camera which is why it is unable to start. Please make sure that you have runtime permissions before starting the ArchitectView.
You don't have to implement the camera yourself when using the the Wikitude SDK. In fact the Wikitude SDK will be unable to use the camera if it is already being used.
Best Regards,
Alex
Cedric RIEGER
I have a problem with the live camera when I use your Sample and my application.
The live camera does not appear, I just have a black background but when I look at my image tracker this one works but I don't see what I'm looking at.
I have no errors in the code.
I joined you my project.
Thank you for your help
Best regards
Android Manifest
Gradle App
Main