4

I am trying to develop a camera instant app, but it always posts a crash when I open the camera by manager.openCamera(cameraId, mStateCallback, null);:

09-10 21:00:55.333 9472-9472/com.pixelslab.stickerpe I/CameraManager: Using legacy camera HAL.
09-10 21:00:55.340 1402-1914/? I/CameraService: CameraService::connect call (PID -1 "com.pixelslab.stickerpe", camera ID 0) for HAL version default and Camera API version 1
09-10 21:00:55.340 1402-1914/? W/ServiceManager: Permission failure: android.permission.CAMERA from uid=10088 pid=9472
09-10 21:00:55.340 1402-1914/? E/CameraService: Permission Denial: can't use the camera pid=9472, uid=10088
09-10 21:00:55.345 9472-9472/com.pixelslab.stickerpe D/AndroidRuntime: Shutting down VM
09-10 21:00:55.348 9472-9472/com.pixelslab.stickerpe E/AndroidRuntime: FATAL EXCEPTION: 
     main Process: com.pixelslab.stickerpe, PID: 9472
     java.lang.SecurityException: Lacking privileges to access camera service
     at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:643)
     at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:340)
     at android.hardware.camera2.CameraManager.openCameraForUid(CameraManager.java:466)
     at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:430)
     at com.gomo.minivideo.camera2.Camera2VideoFragment.openCamera(Camera2VideoFragment.java:378)
     at com.gomo.minivideo.camera2.Camera2VideoFragment.access$000(Camera2VideoFragment.java:65)
     at com.gomo.minivideo.camera2.Camera2VideoFragment$1.onSurfaceTextureAvailable(Camera2VideoFragment.java:120)
     at android.view.TextureView.getHardwareLayer(TextureView.java:390)
     at android.view.TextureView.draw(TextureView.java:339)
     at android.view.View.updateDisplayListIfDirty(View.java:18069)
     at android.view.View.draw(View.java:18847)
     at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
     at android.view.View.updateDisplayListIfDirty(View.java:18060)
     at android.view.View.draw(View.java:18847)
     at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
     at android.view.View.updateDisplayListIfDirty(View.java:18060)
     at android.view.View.draw(View.java:18847)
     at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
     at android.view.View.updateDisplayListIfDirty(View.java:18060)
     at android.view.View.draw(View.java:18847)
     at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
     at android.view.View.updateDisplayListIfDirty(View.java:18060)
     at android.view.View.draw(View.java:18847)
     at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
     at android.view.View.updateDisplayListIfDirty(View.java:18060)
     at android.view.View.draw(View.java:18847)
     at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
     at android.view.View.updateDisplayListIfDirty(View.java:18060)
     at android.view.View.draw(View.java:18847)
     at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
     at android.view.View.updateDisplayListIfDirty(View.java:18060)
     at android.view.View.draw(View.java:18847)
     at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
     at android.view.View.draw(View.java:19122)
     at com.android.internal.policy.DecorView.draw(DecorView.java:785)
     at android.view.View.updateDisplayListIfDirty(View.java:18069)
     at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:643)
     at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:649)
     at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:757)
     at android.view.ViewRootImpl.draw(ViewRootImpl.java:2980)
     at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2794)
     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2347)
     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1386)
     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6733)
     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
     at android.view.Choreographer.doCallbacks(Choreographer.java:723)
     at android.view.Choreographer.doFrame(Choreographer.java:658)
     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
     at android.os.Handler.handleCallback(Handler.java:789)
     at android.os.Handler.dispatchMessage(Handler.java:98)
     at android.os.Looper.loop(Looper.java:164)
     at android.app.ActivityThread.main(ActivityThread.java:6541)
09-10 21:00:55.349 9472-9472/com.pixelslab.stickerpe E/AndroidRuntime:
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
       Caused by: android.os.ServiceSpecificException: Lacking privileges to access camera service (code 1)
     at android.hardware.camera2.legacy.LegacyExceptionUtils.throwOnServiceError(LegacyExceptionUtils.java:132)
     at android.hardware.camera2.legacy.CameraDeviceUserShim.connectBinderShim(CameraDeviceUserShim.java:374)
     at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:317)
     ... 61 more

However, I am sure that I have camera-permission granted, because the same code run successfully in installed version.

Can anyone solve this? Thank you!

Here is the code went crash:

// CameraFragment.java
private TextureView.SurfaceTextureListener mSurfaceTextureListener
        = new TextureView.SurfaceTextureListener() {

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
                                          int width, int height) {
        openCamera(width, height);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
                                            int width, int height) {
        configureTransform(width, height);
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
    }

};

private void openCamera(int width, int height) {
    final Activity activity = getActivity();
    if (null == activity || activity.isFinishing()) {
        return;
    }
    CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
    try {
        Log.d(TAG, "tryAcquire");
        if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
            throw new RuntimeException("Time out waiting to lock camera opening.");
        }
        String cameraId = manager.getCameraIdList()[0];

        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
        StreamConfigurationMap map = characteristics
                .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
        if (map == null) {
            throw new RuntimeException("Cannot get available preview/video sizes");
        }
        mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
        mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
                width, height, mVideoSize);

        int orientation = getResources().getConfiguration().orientation;
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        } else {
            mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
        }
        configureTransform(width, height);
        mMediaRecorder = new MediaRecorder();
        manager.openCamera(cameraId, mStateCallback, null); // here will crash!!!
    } catch (CameraAccessException e) {
        Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
        activity.finish();
    } catch (NullPointerException e) {
        ErrorDialog.newInstance(getString(R.string.camera_error))
                .show(getChildFragmentManager(), FRAGMENT_DIALOG);
    } catch (InterruptedException e) {
        throw new RuntimeException("Interrupted while trying to lock camera opening.");
    }
}

And here is how I get the camera permission:

// MainActivity.java
private void requestCameraPermission() {
    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
            Manifest.permission.CAMERA)) {
        Snackbar.make(mRootView, R.string.permission_camera_rationale,
                Snackbar.LENGTH_INDEFINITE)
                .setAction(R.string.ok, new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        ActivityCompat.requestPermissions(MainActivity.this,
                                new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, REQUEST_CAMERA);
                    }
                })
                .show();
    } else {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA,
                Manifest.permission.INTERNET, Manifest.permission.RECORD_AUDIO}, REQUEST_CAMERA);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CAMERA) {
        if (grantResults.length >= 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            getSupportFragmentManager().beginTransaction().replace(R.id.content_layout, Camera2VideoFragment.newInstance()).commitAllowingStateLoss();
            //getSupportFragmentManager().beginTransaction().replace(R.id.content_layout, new CameraFragment()).commitAllowingStateLoss();
        }
    }
}

And then here is my full manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.pixelslab.stickerpe">

    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:xlargeScreens="true" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.RECORD_VIDEO" />
    <uses-permission android:name="android.permission.CAMERA" />

    <application
        android:name="com.gomo.minivideo.CameraApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/CameraTheme">
        <activity
            android:name="com.gomo.minivideo.MainActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:launchMode="singleTop"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data
                android:name="default-url"
                android:value="https://hugo775128583.github.io/main" />

            <intent-filter android:order="1" android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:scheme="https"
                    android:host="hugo775128583.github.io"
                    android:pathPrefix="/main" />
            </intent-filter>
            <intent-filter android:order="1" android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:scheme="http"
                    android:host="hugo775128583.github.io"
                    android:pathPrefix="/main" />
            </intent-filter>
        </activity>

        <service android:name="com.jb.zcamera.camera.ProcessVideoService" />

        <activity android:name="com.gomo.minivideo.camera.ShareActivity" />
        <activity android:name="com.gomo.minivideo.camera.VideoViewActivity" />
    </application>

</manifest>
Volo
  • 28,673
  • 12
  • 97
  • 125
JavenRuan
  • 51
  • 4
  • We need the code too please! Can't tell what's going on without the code. – chrips Sep 10 '17 at 16:29
  • Thank you for suggestions. And I just posted the code. – JavenRuan Sep 10 '17 at 16:59
  • @JavenRuan So, the request permission dialog appears in your instant app, and after you grant the Camera permission, the fragment tries to open Camera and crashes with the exception above. Is that right? Can you please post your manifest file as well? – Volo Sep 10 '17 at 21:17
  • @Idolon, Yes, you're exactly right! And I posted my manifest file, please check. – JavenRuan Sep 11 '17 at 01:18
  • @JavenRuan There is no such thing as `android.permission.RECORD_VIDEO` permission. This is probably not the source of your issue but you can safely remove it from the manifest. – Volo Sep 11 '17 at 09:28
  • @JavenRuan Can you post your Instant App zip file? As I run the Instant App with the code similar to yours and everything works fine. – Volo Sep 13 '17 at 22:37
  • @JavenRuan, what device are you testing with, and which Android version is it running? Are you able to see whether it happens on other devices or emulators? It sounds like a device-specific bug. Would be very helpful if you could please file a bug at https://issuetracker.google.com/issues?q=componentid:316045 (and if you are able to show that it's device specific, that would help too). – philo Sep 14 '17 at 18:00
  • @Idolon I use Samsung s7(android 7.0) and everything works fine. But the crash in this post just happened on android 8.0 such as Nexus 6p or emulators. – JavenRuan Sep 19 '17 at 14:05
  • @philo, yes, I found that only android 7.0 can run my code perfectly, such as Samsung s7. – JavenRuan Sep 19 '17 at 14:07
  • @JavenRuan can you publish your Instant App APK somewhere, so I can test it on another devices with Android 8.0? – Volo Sep 19 '17 at 14:08
  • @JavenRuan please do file a bug at issuetracker.google.com/issues?q=componentid:316045. We can route that directly to the responsible team. – philo Sep 19 '17 at 21:06
  • @Idolon Thank you, You can check this repository https://github.com/FlareMars/MiniVideo-Instant/ , and run it by yourself. It is a example project, don't complain the terrible code, :) – JavenRuan Sep 20 '17 at 03:49
  • @philo, OK, and I hope you can check my repository https://github.com/FlareMars/MiniVideo-Instant/ as well. Because I am afraid of writing the wrong code in my repository.If not, I will file a bug. – JavenRuan Sep 20 '17 at 03:55
  • 3
    @philo I've filed a bug: https://issuetracker.google.com/issues/66942980 – Volo Sep 26 '17 at 13:59

3 Answers3

2

That looks like a bug reproducible on the Android O. It could be reproduced as well with the sample Camera2Basic project adapted into an Instant App:
https://github.com/Idolon-V/InstantApp-Camera

I've filed a bug on the Google tracker: https://issuetracker.google.com/issues/66942980

Volo
  • 28,673
  • 12
  • 97
  • 125
0

add this line in your manifest file

<uses-feature android:name="android.hardware.camera"></uses-feature>
Shiva Kanumala
  • 284
  • 5
  • 5
0

With reference to Google issue tracker,

This issue has been fixed and rolled out on 8.1 devices already. We are working with our partners to roll out the fix into the update for 8.0 devices. We expect those updates to be rolled out in the coming months.

If any issue persists, please report at Google issue tracker they will re-open to examine.

Prags
  • 2,457
  • 2
  • 21
  • 38