我创建了单独的类来授予权限。现在,我想在开始时为我的相机应用程序授予权限。当我第一次运行应用程序时,出现崩溃错误,然后显示权限对话框,我可以授予权限,然后我的应用程序崩溃了。在我再次进入应用程序后,它们开始工作。我该如何解决此首次运行问题权限崩溃?对于相机,我使用了来自android开发人员网站的示例。清单中的权限已添加。
我的权限等级
public abstract class AbsRuntimePermission extends Activity {
private SparseIntArray mErrorString;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mErrorString = new SparseIntArray();
}
public abstract void onPermissionsGranted(int requestCode);
public void requestAppPermissions(final String[]requestedPermissions, final int stringId, final int requestCode) {
mErrorString.put(requestCode, stringId);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
boolean showRequestPermissions = false;
for(String permission: requestedPermissions) {
permissionCheck = permissionCheck + ContextCompat.checkSelfPermission(this, permission);
showRequestPermissions = showRequestPermissions || ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
}
if (permissionCheck!=PackageManager.PERMISSION_GRANTED) {
if(showRequestPermissions) {
Snackbar.make(findViewById(android.R.id.content), stringId, Snackbar.LENGTH_INDEFINITE).setAction("GRANT", new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityCompat.requestPermissions(AbsRuntimePermission.this, requestedPermissions, requestCode);
}
}).show();
} else {
ActivityCompat.requestPermissions(this, requestedPermissions, requestCode);
}
} else {
onPermissionsGranted(requestCode);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
for(int permisson : grantResults) {
permissionCheck = permissionCheck + permisson;
}
if( (grantResults.length > 0) && PackageManager.PERMISSION_GRANTED == permissionCheck) {
onPermissionsGranted(requestCode);
} else {
//Display message when contain some Dangerous permisson not accept
Snackbar.make(findViewById(android.R.id.content), mErrorString.get(requestCode),
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE", new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent();
i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.setData(Uri.parse("package:" + getPackageName()));
i.addCategory(Intent.CATEGORY_DEFAULT);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(i);
}
}).show();
}
}
}
我的相机活动
public class CameraActivity extends AbsRuntimePermission {
private Camera mCamera;
private CameraPreview mPreview;
private static final int REQUEST_PERMISSION = 10;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
requestAppPermissions(new String[]{
Manifest.permission.CAMERA},
R.string.msg,REQUEST_PERMISSION);
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
@Override
public void onPermissionsGranted(int requestCode) {
//Do anything when permisson granted
Toast.makeText(getApplicationContext(), "Permission granted", Toast.LENGTH_LONG).show();
}
@Override
public void onPause() {
super.onPause();
// Stop camera access
releaseCamera();
}
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
private void releaseCamera(){
if (mCamera != null){
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
}
相机预览
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
//mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
堆栈跟踪
09-14 11:02:02.414 5592-5592/com.nopermissions.ivan.camerawithoutpermissions_01 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.nopermissions.ivan.camerawithoutpermissions_01, PID: 5592
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.setPreviewDisplay(android.view.SurfaceHolder)' on a null object reference
at com.nopermissions.ivan.camerawithoutpermissions_01.CameraPreview.surfaceCreated(CameraPreview.java:35)
at android.view.SurfaceView.updateWindow(SurfaceView.java:656)
at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:172)
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1013)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2542)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1537)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:959)
at android.view.Choreographer.doCallbacks(Choreographer.java:734)
at android.view.Choreographer.doFrame(Choreographer.java:670)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:945)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
答案 0 :(得分:0)
CameraActivity
中的 ... mCamera = getCameraInstance();
返回NULL
。
您可以通过在继续操作前检查if(mCamera != null)
来防止崩溃。
if(mCamera != null) {
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
该代码也应称为onRequestPermissionsResult
...
因此,最优雅的可能是将其放入自己的方法中。