Android camera permission - android

I have this code which i make using official developer android sites. I want to create camera preview, but first ask for permissions. When i start the app they crash, but before app exit, they ask me for permissions which i grant, and then app crash. After i enter app again it work just fine, but i want to get rid of that crash. Anyone know a solution?
CameraActivity.java
public class CameraActivity extends AppCompatActivity {
private Camera mCamera;
private CameraPreview mPreview;
private static final int PERMISSION_CAMERA = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
PERMISSION_CAMERA);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
// 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 = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_CAMERA: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
#Override
public void onPause() {
super.onPause();
// Stop camera access
releaseCamera();
}
/** A safe way to get an instance of the Camera object. */
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;
}
}
}
Logcat
FATAL EXCEPTION: main
Process: com.example.ivan.cameratest1, PID: 7690
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.setPreviewDisplay(android.view.SurfaceHolder)' on a null object reference
at com.example.ivan.cameratest1.CameraPreview.surfaceCreated(CameraPreview.java:36)
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)

private final String TAG = "Debug_MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkCameraPermission();
}
private final int MY_PERMISSIONS_REQUEST_USE_CAMERA = 0x00AF;
private void checkCameraPermission(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA ) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG,"Permission not available requesting permission");
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_USE_CAMERA);
} else {
Log.d(TAG,"Permission has already granted");
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_USE_CAMERA: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG,"permission was granted! Do your stuff");
} else {
Log.d(TAG,"permission denied! Disable the function related with permission.");
}
return;
}
}
}

I think you are getting an error with permission.. You are trying to open camera even when you don't have permission to. That's why it crashes on first start up and not on second time.
Try to perform the changes below (I changed onCreate and onRequestPermissionsResult):
public class CameraActivity extends AppCompatActivity {
private Camera mCamera;
private CameraPreview mPreview;
private static final int PERMISSION_CAMERA = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
PERMISSION_CAMERA);
}
} else {
mCamera = getCameraInstance();
}
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_CAMERA: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mCamera = getCameraInstance();
}
return;
}
}
}
...
}

Related

How to detect and selecting user local country?

I'm using that library: https://github.com/AlmogBaku/IntlPhoneInput to get user phone number.
I want to detect and select automatically the local country of the user.
Reading that: https://github.com/AlmogBaku/IntlPhoneInput#public-methods,
I added that: android.permission.READ_PHONE_STATE in my AndroidManifest.xml but can't detect and select automatically the local country of the user.
Any help ?
If you are using API-level 23+, then android.permission.READ_PHONE_STATE in manifest won't be sufficient and you need to request it programmatically, and to do so
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_READ_STATE = 21;
private IntlPhoneInput mPhoneInputView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
// We do not have this permission. Let's ask the user by showingg a dialog
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, PERMISSION_READ_STATE);
}
mPhoneInputView = findViewById(R.id.my_phone_input);
}
// Called when the user decides the dialog permission
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_READ_STATE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission granted!
mPhoneInputView.setDefault();
} else {
// permission denied
}
}
}
...
}

How to ask permissions only once?

I have a method in the beginning of the activity to ask the permissions, but in the code when I want to get location coordinates, appear a error about permissions request.
This is for Android SDK 28.0.2. I've tried adding the permissions requeste in all lines that I request for coordinates.
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
checkPermissions();
...
}
public void myPosition() {
//One of lines where appear the error
Location loca = locaMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loca != null) {
mapCamera(loca.getLatitude(), loca.getLongitude());
pass = true;
savePosition(loca);
}
}
private void checkPermissions() {
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) ||
(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
}
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
switch (requestCode) {
case 1: {
if (!(grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
//Show error
finish();
}
}
}
}
I want do this permissions check only once. But now I see the following error:
Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException

How can delay in program, until user response to run-time permission?

I have problem for run time permission.my code is:
public class MainActivity extends AppCompatActivity {
int i = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
ActivityCompat.requestPermissions(MainActivity.this, permissions, 0x3);
while (i == 0) {
//
}
//
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 0x3:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(G.context, "allowed",Toast.LENGTH_LONG).show();
} else {
Toast.makeText(G.context, "deney", Toast.LENGTH_LONG).show();
}
break; } }}
I want whlie block run after user response permission. but while block dont wait for permission result. How can delay in program, until user response to run-time permission, and after run whlie and another line?
You just have to call the rest of your code if the "allowed" case of your onRequestPermissionResult method.
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(G.context, "allowed",Toast.LENGTH_LONG).show();
//The rest of your code
} else {
Toast.makeText(G.context, "deney", Toast.LENGTH_LONG).show();
//Ask again
}

Why does my app crash when using android.hardware.Camera.Open()?

I am re-writing an app for most versions of Android. The app is set to call android.hardware.Camera.Open() on launch. When the app launches it gives the error Camera Error: Could not connect to camera
The permissions in AndroidManifest.xml are
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-permission android:name="android.permission.camera"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>`.
Why can't it connect to the camera?
Problem solved!
The issue was simply a matter of capitalization. The line <uses-permission android:name="android.permission.camera"/> should actually read <uses-permission android:name="android.permission.CAMERA"/>. This happened because camera is a hardware feature, while CAMERA is a permission.
In previous versions of android in order to use camera hardware there was enough to state proper permissions and uses in android manifest, but since the Marshmallow version has appeared it's not enough to run the app anymore. As there is also need to enable runtime permissions. Consider using similar code, and suit it to your project, as it gives You opportunity to check and enable permission.
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
cameraPreview.initializeCamera();
} else {
}
return;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PERMISSION_REQUEST_CODE) {
cameraPreview.initializeCamera();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
public void requestCameraPermission() {
ActivityCompat.requestPermissions(this,
new String[]{
Manifest.permission.CAMERA
},
PERMISSION_REQUEST_CODE);
}
public void requestPermissionWithRationale() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
Snackbar.make(findViewById(android.R.id.content), R.string.no_cam_permission, Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.snackbar_action_grant, new View.OnClickListener() {
#Override
public void onClick(View v) {
requestCameraPermission();
}
})
.show();
} else {
requestCameraPermission();
}
}
Use Camera for Deprecated
Below is the code
UPDATE --->
#Module
public class CameraModule {
#Provides
CameraSupport provideCameraSupport() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return new CameraNew(context);
} else {
return new CameraOld();
}
}
}
and then for Old target :
#SuppressWarnings("deprecation")
public class CameraOld implements CameraSupport {
private Camera camera;
#Override
public CameraSupport open(final int cameraId) {
this.camera = Camera.open(cameraId);
return this;
}
#Override
public int getOrientation(final int cameraId) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
return info.orientation;
}
}
for New Target :
public class CameraNew implements CameraSupport {
private CameraDevice camera;
private CameraManager manager;
public CameraNew(final Context context) {
this.manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public CameraSupport open(final int cameraId) {
try {
String[] cameraIds = manager.getCameraIdList();
if (ActivityCompat.checkSelfPermission(CameraPreview.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return null;
}
manager.openCamera(cameraIds[cameraId], new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
CameraNew.this.camera = camera;
}
#Override
public void onDisconnected(CameraDevice camera) {
CameraNew.this.camera = camera;
// TODO handle
}
#Override
public void onError(CameraDevice camera, int error) {
CameraNew.this.camera = camera;
// TODO handle
}
}, null);
} catch (Exception e) {
// TODO handle
}
return this;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public int getOrientation(final int cameraId) {
try {
String[] cameraIds = manager.getCameraIdList();
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
} catch (CameraAccessException e) {
// TODO handle
return 0;
}
}
}

Lollipop vs Nougat Runtime directory permission to external storage folder

I have a code that runs fine in Lollipop device but don't do anything in Nougat
private ArrayList<PDFDoc> getPDFs() {
File downloadsFolder=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
if (downloadsFolder.exists()) {
//GET ALL FILES IN DOWNLOAD FOLDER
File[] files = downloadsFolder.listFiles();
//LOOP THRU THOSE FILES GETTING NAME AND URI
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.getPath().endsWith("pdf")) {
pdfDoc = new PDFDoc();
pdfDoc.setName(file.getName());
pdfDoc.setPath(file.getAbsolutePath());
pdfDocs.add(pdfDoc);
}
}
}
return pdfDocs;
}
This block runs fine with desired result in lollipop but not in Nougat, kindly help me out with genuine changes or addition.
Before calling the method getPDFs() you need to check whether the storage permission is granted by the user or not.
From android marshmallow, only defining the permissions in Manifest file will not work you need to ask for the permission on runtime.
So first you need to check if the device running the app is marshmallow or above. You can do it by using this code.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
//ask for permission here
}
For asking the runtime permission you can use the following code.
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// Permission has already been granted
}
You have to do this for the storage permission. I copied the above code from the Android Developer's Page.
For more details check Requesting App's permission
For this you need to add runtime permissions
private static final int REQUEST_WRITE_PERMISSION = 786;
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//call func here
}
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
} else {
//call func here
}
}
AppConstants
public static final String CAMERA_PERMISSION = CAMERA;
public static final String READ_STORAGE_PERMISSION = READ_EXTERNAL_STORAGE;
public static final String WRITE_STORAGE_PERMISSION = WRITE_EXTERNAL_STORAGE;
public static final String LOCATION_PERMISSION = ACCESS_FINE_LOCATION;
public static final String READ_PHONE_STATE_PERMISSION= READ_PHONE_STATE;
Call this Function From your (Activity OR Fragment OR Button) for checking the permissions
//Getting permission here
public boolean needPermission() {
try {
int readPhoneState = ContextCompat.checkSelfPermission(this, AppConstants.READ_PHONE_STATE_PERMISSION);
int location = ContextCompat.checkSelfPermission(this, AppConstants.LOCATION_PERMISSION);
if (readPhoneState == PackageManager.PERMISSION_GRANTED && location == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
if (readPhoneState != PackageManager.PERMISSION_GRANTED) {
AppGlobal.checkSinglePermission(this, AppConstants.READ_PHONE_STATE_PERMISSION);
} else if (location != PackageManager.PERMISSION_GRANTED) {
AppGlobal.checkSinglePermission(this, AppConstants.LOCATION_PERMISSION);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
This function will check permission type
//Check single permission
public static boolean checkSinglePermission(final Context context, String permissionType) {
ArrayList<String> permissionList = new ArrayList<>();
String type = "";
if (permissionType != null) {
if (permissionType.equals(AppConstants.CAMERA_PERMISSION)) {
type = permissionType;
}
if (permissionType.equals(AppConstants.READ_STORAGE_PERMISSION)) {
type = permissionType;
}
if (permissionType.equals(AppConstants.WRITE_STORAGE_PERMISSION)) {
type = permissionType;
}
if (permissionType.equals(AppConstants.READ_PHONE_STATE_PERMISSION)) {
type = permissionType;
}
if (permissionType.equals(AppConstants.LOCATION_PERMISSION)) {
type = permissionType;
}
int getPermission = ContextCompat.checkSelfPermission(context, type);
if (getPermission != PackageManager.PERMISSION_GRANTED) {
permissionList.add(type);
if (!permissionList.isEmpty()) {
ActivityCompat.requestPermissions((Activity) context, permissionList.toArray
(new String[permissionList.size()]), SINGLE_PERMISSION_REQUEST);
return false;
}
}
}
return true;
}
Then you will get permission success and failure response in this onRequestPermissionsResult()
//Permission request result here
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
for (String permission : permissions) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
AppLog.e("denied" + permission);//denied
needPermission();//needed permission for getting Country code
} else {
if (ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
AppLog.e("allowed" + permission);//allowed
needPermission();//set data
} else {
//set to never ask again
AppLog.e("set to never ask again" + permission);
AppDialog.showAlertDialog(this, null,
getString(R.string.read_phone_state_permission_txt), getString(R.string.txt_ok), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
AppGlobal.permissionSettingView(LoginActivity.this);
}
});
}
}
}
}

Categories

Resources