Lee*_*ine 4 android android-camera android-permissions android-camera2
我正在关注在Android应用程序中使用相机的教程.我在模拟器和物理设备上运行调试时收到错误"权限拒绝:无法使用相机".我在清单文件中尝试了各种权限.似乎大多数有此错误的人都有错误,缺少权限或权限不在其清单中的正确位置.
这是我的清单文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.karudo.dbzrealpowerup" >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera2" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".DBZHome"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DBZStartPowerUp"
android:label="@string/title_activity_dbzstart_power_up" >
</activity>
</application>
</manifest>
Run Code Online (Sandbox Code Playgroud)
这是我的活动:
package com.example.karudo.dbzrealpowerup;
import android.app.Activity;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Bundle;
import android.util.Size;
import android.view.Menu;
import android.view.MenuItem;
import android.view.TextureView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class DBZStartPowerUp extends Activity {
private Size mPreviewSize;
private String mCameraId;
private TextureView mTextureView;
private TextureView.SurfaceTextureListener mSurfaceTextureListener =
new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
setupCamera(width, height);
openCamera();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private CameraDevice mCameraDevice;
private CameraDevice.StateCallback mCameraDeviceStateCallback
= new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
Toast.makeText(getApplicationContext(), "Camera Opened!", Toast.LENGTH_SHORT).show();
}
@Override
public void onDisconnected(CameraDevice camera) {
camera.close();
mCameraDevice = null;
}
@Override
public void onError(CameraDevice camera, int error) {
camera.close();
mCameraDevice = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dbzstartpowerup);
mTextureView = (TextureView) findViewById(R.id.dbzCameraPreview);
}
@Override
public void onResume() {
super.onResume();
if(mTextureView.isAvailable()) {
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_dbzstartpowerup, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void setupCamera(int width, int height) {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
for(String cameraId : cameraManager.getCameraIdList()) {
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
mPreviewSize = getPreferredPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height);
mCameraId = cameraId;
return;
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private Size getPreferredPreviewSize(Size[] mapSizes, int width, int height) {
List<Size> collectorSizes = new ArrayList<>();
for(Size option : mapSizes) {
if(width > height) {
if(option.getWidth() > width &&
option.getHeight() > height) {
collectorSizes.add(option);
}
} else {
if(option.getWidth() > height &&
option.getHeight() > width) {
collectorSizes.add(option);
}
}
}
if(collectorSizes.size() > 0) {
return Collections.min(collectorSizes, new Comparator<Size>() {
@Override
public int compare(Size lhs, Size rhs) {
return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight());
}
});
}
return mapSizes[0];
}
private void openCamera() {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的logcat中的错误:
10-04 03:15:02.740 961-8780/? E/CameraService? Permission Denial: can't use the camera pid=20601, uid=10059
10-04 03:15:02.741 20601-20601/com.example.karudo.dbzrealpowerup E/AndroidRuntime? FATAL EXCEPTION: main
Process: com.example.karudo.dbzrealpowerup, PID: 20601
java.lang.SecurityException: Lacking privileges to access camera service
at android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:108)
at android.hardware.camera2.legacy.CameraDeviceUserShim.connectBinderShim(CameraDeviceUserShim.java:336)
at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:324)
at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:454)
at com.example.karudo.dbzrealpowerup.DBZStartPowerUp.openCamera(DBZStartPowerUp.java:163)
at com.example.karudo.dbzrealpowerup.DBZStartPowerUp.access$100(DBZStartPowerUp.java:23)
at com.example.karudo.dbzrealpowerup.DBZStartPowerUp$1.onSurfaceTextureAvailable(DBZStartPowerUp.java:34)
at android.view.TextureView.getHardwareLayer(TextureView.java:368)
at android.view.View.updateDisplayListIfDirty(View.java:15151)
at android.view.View.draw(View.java:15948)
at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
at android.view.View.updateDisplayListIfDirty(View.java:15169)
at android.view.View.draw(View.java:15948)
at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
at android.view.View.updateDisplayListIfDirty(View.java:15169)
at android.view.View.draw(View.java:15948)
at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
at android.view.View.updateDisplayListIfDirty(View.java:15169)
at android.view.View.draw(View.java:15948)
at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
at android.view.View.draw(View.java:16181)
at com.android.internal.policy.PhoneWindow$DecorView.draw(PhoneWindow.java:2690)
at android.view.View.updateDisplayListIfDirty(View.java:15174)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2615)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2434)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2067)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Run Code Online (Sandbox Code Playgroud)
我是应用程序开发的新手,不可否认我不擅长调试,但我的清单权限似乎与我所看到的其他人的文件(以及仅4个月大的教程)相同.
谁能告诉我我做错了什么?
干杯,李.
更新:我通过调试发现它一旦到达此方法就会崩溃...
private void openCamera() {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
}
...特别是一旦它运行try语句.
更新2:如果我注释掉try/catch语句,应用程序不会崩溃,但预期的结果(即打印"Camera Opened!")不会发生.有任何想法吗?
更新3:道歉,我刚刚意识到我上面的编辑是多么愚蠢.很明显为什么它不再崩溃,但至少我现在知道我必须调试我的cameraManager.openCamera参数.如果有人可以看看代码是那里:)
Rob*_*rto 10
如果您使用的是Android 6 Marshmallow,则此问题可能是由新的权限管理引起的.在我的情况下,我通过重写以下活动方法解决了这个问题:
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case CAMERA_PERMISSION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if(mClss != null) {
Intent intent = new Intent(this, ClassUsingCamera);
startActivity(intent);
}
} else {
Toast.makeText(this, "Please grant camera permission to use the QR Scanner", Toast.LENGTH_SHORT).show();
}
return;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我使用以下代码启动了需要摄像头的活动(ClassUsingCamera):
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION);
} else {
Intent intent = new Intent(this, ClassUsingCamera);
startActivity(intent);
}
Run Code Online (Sandbox Code Playgroud)
在第一个应用程序启动时,您将获得弹出窗口,要求您授予对摄像头的访问权限.
另一种选择是使用PermissionsDispatcher,如下所述https://github.com/hotchemi/PermissionsDispatcher
尝试将此代码放入您的manifest.xml 文件中。
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission
android:name="android.permission.INTERNET"
android:maxSdkVersion="19" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_DEBUG_APP"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21889 次 |
| 最近记录: |