Hello to all programmers.
While creating my first android app in Visual studio Xamarin, I stuck with one more problem (there was lot of them =) ). I try to make permissions check for Android Marshmallow+. And while I try to launch Camera Activity (MediaStore.ActionImageCapture), my app crashes. Here the code
const int REQUEST_CAMERA = 1;
const int REQUEST_EXTERNAL_STORAGE = 2;
const string cameraPermission = Android.Manifest.Permission.Camera;
const string storageWritePermission = Android.Manifest.Permission.WriteExternalStorage;
const string storageReadPermission = Android.Manifest.Permission.ReadExternalStorage;
public static class App
{
public static File _file;
public static File _dir;
public static Bitmap bitmap;
public static string fileName;
}
private bool IsThereAnAppToTakePicture()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
IList<ResolveInfo> availableActivities =
PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);
return availableActivities != null && availableActivities.Count > 0;
}
private void CreateDirectoryForPictures()
{
App._dir = new File(Enviroment.GetExternalStoragePublicDirectory(Enviroment.DirectoryPictures), "Kuponguru");
if (!App._dir.Exists())
{
App._dir.Mkdirs();
}
}
private void StartCameraActivity()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
App.fileName = String.Format("picture_{0}.jpg", Guid.NewGuid());
App._file = new File(App._dir, App.fileName);
intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(App._file));
StartActivityForResult(intent, REQUEST_CAMERA);
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.TakePicture);
pictureImageButton = FindViewById<ImageView>(Resource.Id.pictureButton);
pictureImageButton.Click += TakePicture;
if (Build.VERSION.SdkInt >= BuildVersionCodes.M)
{
if (CheckSelfPermission(storageReadPermission) == (int)Permission.Granted &&
CheckSelfPermission(storageWritePermission) == (int)Permission.Granted)
{
if (IsThereAnAppToTakePicture())
{
CreateDirectoryForPictures();
}
}
else
{
RequestPermissions(new string[] { storageWritePermission, storageReadPermission }, REQUEST_EXTERNAL_STORAGE);
}
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
switch (requestCode)
{
case REQUEST_EXTERNAL_STORAGE:
{
if (grantResults[0] == Permission.Granted)
{
if (IsThereAnAppToTakePicture())
{
CreateDirectoryForPictures();
}
}
}
break;
case REQUEST_CAMERA:
{
if (grantResults[0] == Permission.Granted)
{
StartCameraActivity();
}
}
}
}
private void TakePicture(object sender, EventArgs e)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.M) {
if (CheckSelfPermission(cameraPermission) == (int)Permission.Granted &&
CheckSelfPermission(storageWritePermission) == (int)Permission.Granted)
{
StartCameraActivity();
}
else
{
RequestPermissions(new string[] { cameraPermission, storageWritePermission }, REQUEST_CAMERA);
}
}
else
{
StartCameraActivity();
}
}
If I delete string intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(App._file)); in StartCameraActivity, then camera works, but with this command app crashed.
I'll be appreciated for all suggestions.
--UPDATED--
I check Uri.FromFile(App._file) in intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(App._file)); File is not exists So, problem is - app can't create file (but can create directory)
--UPDATED--
I check application on Marshmallow emulator. All works fine. Also I check on emulated device - file, where camera should save photo, is not exists when I send it to Camera activity in intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(App._file)); Well problem is still here.
--UPDATED--
Added try catch for Camera activity start and get exception file:///storage/emulated/0/Pictures/MyApp/picture_123.jpg exposed beyond app through ClipData.Item.getUri
At least I found whats wrong. It's god damned version issue. In Android N+ there are no more file:// URIs, only content:// URIs instead. That's why Camera Activity can't work with Uri.FromFile(App._file).
For this solution I have to thank request Answer of question by questioner SuperThomasLab and users Pkosta, hqzxzwb and Java coder
The solution, changed for VS Xamarin, I used:
**Solution **
protected override void OnCreate(Bundle savedInstanceState){
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.SetVmPolicy(builder.Build());
base.OnCreate(savedInstanceState);
...
}
Other code is without changes.
I tried it on Android N 7.1.1 on real device and it's works.
Thanks to all, who take attention to my problem.
Related
I am building barcode scanning functionality into an app, and have followed this guide: https://learntodroid.com/how-to-create-a-qr-code-scanner-app-in-android/.
I have a main activity, which launches my QR scanning activity. When I detect a particular uri from the QR code (based on scheme, host and path), I want to end the QR scanning activity, return to my main activity and launch a dialog.
This is all working - the first time. However, if I relaunch the scanning activity, it no longer detects QR codes, and my onQRCodeFound never gets hit. (Killing and restarting the app resets it, I can scan 1 QR code successfully again, but then it stops detecting them if I reopen the QR activity). The image preview is shown, but the QR never gets recognised.
I do get W/System.err: com.google.zxing.NotFoundException printed to the log repeatedly while the activity is open.
UPDATE
On more investigation I found that on the 2nd (and subsequent times) I launch this activity the previewView has a width and height of 0 (the first time, it's correctly getting the size of 1080x2280). Setting a target resolution of 0x0 for the ImageAnalysis was the problem.
If I hard code the resolution, rather than using previewView.getWidth() and previewView.getHeight(), then it works fine every time.
If I change the call to bindCameraPreview(cameraProvider) to previewView.post(()->bindCameraPreview(cameraProvider)) it works.
Not sure if this is the best/correct solution, but it's working for me. I still don't understand why my previewView has the correct dimensions the first time, and 0s the 2nd - if anyone knows, please enlighten me!
END UPDATE
Here is my ScanQRActivity:
public class ScanQRActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_CAMERA = 0;
private PreviewView previewView;
private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
private Button qrCodeFoundButton;
private String qrCode;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qr_scan);
previewView = findViewById(R.id.activity_main_previewView);
qrCodeFoundButton = findViewById(R.id.activity_main_qrCodeFoundButton);
qrCodeFoundButton.setVisibility(View.INVISIBLE);
cameraProviderFuture = ProcessCameraProvider.getInstance(this);
requestCamera();
}
private void requestCamera() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
startCamera();
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
ActivityCompat.requestPermissions(ScanQRActivity.this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CAMERA) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startCamera();
} else {
// Toast.makeText(this, "Camera Permission Denied", Toast.LENGTH_SHORT).show();
}
}
}
private void startCamera() {
cameraProviderFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
bindCameraPreview(cameraProvider);
} catch (ExecutionException | InterruptedException e) {
Toast.makeText(this, "Error starting camera " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}, ContextCompat.getMainExecutor(this));
}
private void bindCameraPreview(#NonNull ProcessCameraProvider cameraProvider) {
previewView.setImplementationMode(PreviewView.ImplementationMode.COMPATIBLE);
Preview preview = new Preview.Builder()
.build();
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
preview.setSurfaceProvider(previewView.getSurfaceProvider());
ImageAnalysis imageAnalysis =
new ImageAnalysis.Builder()
.setTargetResolution(new Size(previewView.getWidth(), previewView.getHeight() ))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(this), new QRCodeImageAnalyzer(new QRCodeImageAnalyzer.QRCodeFoundListener() {
#Override
public void onQRCodeFound(String _qrCode) {
qrCode = _qrCode;
qrCodeFoundButton.setVisibility(View.VISIBLE);
Uri code = Uri.parse(qrCode);
if(code.getScheme().equals("myCustomScheme") && code.getHost().equals("app")){
String path = code.getPath();
String host = code.getHost() ;
String query = code.getQuery();
List<String> params = code.getQueryParameters("a");
if(path.equals("/voucher")){
Intent intent = new Intent();
intent.putExtra("type", "voucher");
intent.putExtra("voucherCode", code.getQueryParameter("c"));
intent.putExtra("timestamp", code.getQueryParameter("t"));
setResult(Activity.RESULT_OK, intent);
finish();
}
}
}
#Override
public void qrCodeNotFound() {
}
}));
Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector,imageAnalysis, preview);
}
}
And my ActivityResultLauncher:
ActivityResultLauncher<Intent> startQRActivity = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
// Add same code that you want to add in onActivityResult method
if (result.getResultCode() == Activity.RESULT_OK) {
// There are no request codes
Intent data = result.getData();
String code = data.getStringExtra("voucherCode");
String time = data.getStringExtra("timestamp");
voucherDetailBusinessDialog dia = new voucherDetailBusinessDialog(getColor(R.color.appThemeColor), getColor(R.color.orange), code);
dia.show(getSupportFragmentManager(),null);
}
}
});
I'm upgrading the app to target android 12, before its targeting android 10. So, now I'm using MANAGE_EXTERNAL_STORAGE with registerForActivityResult but when user allow access to manage files and press back button the registerForActivityResult do not get called. Here is my code.
In onCreate method
registerLauncher();
if (checkPermissionsGranted()) {
initMainActivity();
} else {
requestPermission();
}
The above methods in sequence.
private void registerLauncher() {
permissionLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Log.e(TAG, "inside activity result");
initMainActivity();
}
}
});
}
private boolean checkPermissionsGranted() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return Environment.isExternalStorageManager();
} else {
int readPermission = ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE);
int writePermission = ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE);
// int storagePermission = ContextCompat.checkSelfPermission(mContext, Manifest.permission_group.STORAGE);
return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED;
}
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
try {
// Uri uri = Uri.parse("package:" + BuildConfig.APPLICATION_ID);
// Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri);
// startActivity(intent);
// permissionLauncher.launch(intent);
// startActivityForResult(intent, AppConstants.STORAGE_PERMISSION_CODE);
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse(String.format("package:%s", getApplicationContext().getPackageName())));
// startActivityForResult(intent, AppConstants.STORAGE_PERMISSION_CODE);
permissionLauncher.launch(intent);
} catch (Exception e) {
Log.e(TAG, "Exp... " + e.toString());
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
permissionLauncher.launch(intent);
}
} else {
ActivityCompat.requestPermissions(Splashscreen.this, new String[]{Manifest.permission_group.STORAGE}, AppConstants.STORAGE_PERMISSION_CODE);
}
}
I also tried with startActivityForResult(intent, AppConstants.STORAGE_PERMISSION_CODE); (I know startActivityForResult is deprecated) with overriding onRequestPermissionsResult but none of these two get called
1 - registerForActivityResult
2 - onRequestPermissionsResult
Please let me know what I'm doing wrong here? As I'm check the permission on splash activity, the app get stuck on the splash as onResult is not being called.
Thanks & Regards
after checking the permission on splash activity, you have two options back to the App. either click on back button on the top left corner or click on app icon. but you will be get never Activity.RESULT_OK as result. Therefore, you should handle it differently by querying Environment.isExternalStorageManager().
change your registerLauncher() function as bellow.
private void registerLauncher() {
permissionLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (Environment.isExternalStorageManager()) {
Log.e(TAG, "inside activity result");
initMainActivity();
}
}
});
}
MediaStore.MediaColumns.DATA constant was deprecated in API level Q.
Apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver#openFileDescriptor(Uri, String) to gain access. This value will always be NULL for apps targeting Build.VERSION_CODES.Q or higher.
This is true we can't get the real path. Just Simple method open stream with contentResolver() and copy the whole content of file into new file and for getting file information we need to call a query() method of a getContentResolver().query() then we can get DISPLAY_NAME of the file and some more info like FILE_SIZE.
Simple code Example for those who upvoted the question:
public class MainFragment extends Fragment {
private Button openGallery;
private File selectedFile;
private Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
context = container.getContext();
return inflater.inflate(R.layout.fragment_question, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
openGallery = view.findViewById(R.id.openGallery);
openGallery.setOnClickListener(v->browseFile());
}
private void browseFile() {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
openFiles();
} else {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 786);
}
}
private void openFiles() {
deleteFileFromCacheDir();
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
if (intent.resolveActivity(context.getPackageManager()) != null) {
startActivityForResult(intent, 786);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 786 && resultCode == -1 && data != null) {
Uri uri = data.getData();
openStreamAndCopyContent(uri); // Here i am just copy the content of file and paste it into my new file. You can check the type of the file image/video/audio & do it whatever you want
// Now here is your file
if (selectedFile != null && selectedFile.exists()){
// Do it whatever you want Or send it to server
}
}
}
private void openStreamAndCopyContent(Uri uri) {
try {
String fileName = "temp" + System.currentTimeMillis() + "." + MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri));
selectedFile = new File(context.getCacheDir().getAbsolutePath() + File.separator + fileName);
InputStream inputStream = context.getContentResolver().openInputStream(uri);
if (inputStream != null) {
Utility.copy(inputStream, selectedFile);
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 786) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openFiles();
} else if (grantResults[0] == PackageManager.PERMISSION_DENIED && getActivity() != null) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(context).setTitle(R.string.permission_required).setMessage(R.string.permission_message)
.setPositiveButton(R.string.open_settings, (dialog, which) ->
context.startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.parse("package:" + BuildConfig.APPLICATION_ID)))).setNegativeButton(R.string.close, null).show();
}
}
}
}
private void deleteFileFromCacheDir() {
if (selectedFile != null && selectedFile.exists()) {
if (selectedFile.delete()) {
selectedFile = null;
}
}
}
#Override
public void onDestroyView() {
deleteFileFromCacheDir();
super.onDestroyView();
}
}
I believe it is not possible, as you simply don't need that path from a programming stand point.
You cannot read/change/delete the file with the real path. You should use a ContentResolver for these operations as stated in your question.
If you just want to show the path to the user, then I would suggest to either give an option to open/share the file with an Intent.createChooser or just show the MediaColumns.RELATIVE_PATH.
I need to open overlay setting window for my app. Of course, my manifest file use SYSTEM_ALERT_WINDOW permission already.
public class MainActivity extends ReactActivity {
private static final int CODE_DRAW_OVER_OTHER_APP_PERMISSION = 2084;
#Override
protected String getMainComponentName() {
return "MyToolbox";
}
#Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
#Override
protected ReactRootView createRootView() {
return new RNGestureHandlerEnabledRootView(MainActivity.this);
}
};
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requireDrawOverlayPermission();
}
//Ask draw overlay permission
void requireDrawOverlayPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package: " + getPackageName()));
startActivityForResult(intent, CODE_DRAW_OVER_OTHER_APP_PERMISSION);
} else {
//TODO: Permission granted
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CODE_DRAW_OVER_OTHER_APP_PERMISSION) {
if (Settings.canDrawOverlays(this)) {
//TODO: Permission granted
} else {
Toast.makeText(this, "Draw over the app is not available", Toast.LENGTH_SHORT).show();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
The first debug run from my Android Studio, my app got crashed.
And next time, it's not crash, but it doesn't show overlay setting window for me. I can see a screen is flashed but close immediately.
What wrong in my code?
Thank you!
Finally, I figured it out afterall. That settings window need package name to know which app require this permission. And the uri can't parse my package name because I put a space between "package:" and "getPackageName()". I removed it as below, and everything works fine!
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
I am trying to learn how to use the camera in an app and this is what I reached , the idea is having a button that opens the camera and that the picture will instantly show on the screen after we take the picture, the second button is from an earlier version that couldn't show the picture immediately and had to be clicked in order to show it.
Anyways my problem is that this code doesn't show the picture at android 6.. on my android 5 device it works fine.. the picture is saved in the "sdcard/camera_app/cam_image.jpg" path either way and the button doesn't work as well so I'm thinking something about the imageview has changed from android 5 to 6? the question is pretty much how to make this work for android 6 phones
public class Add_Comment_Picture extends AppCompatActivity {
static final int CAM_REQUEST = 1;
ImageView imageView;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add__comment__picture);
button = (Button) findViewById(R.id.button);
imageView = (ImageView) findViewById(R.id.imageView);
Button button2 = (Button) findViewById(R.id.button3);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent camera_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = getFile();
camera_intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(camera_intent , CAM_REQUEST);
}
});
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String path = "sdcard/camera_app/cam_image.jpg";
imageView.setImageDrawable(Drawable.createFromPath(path));
}
});
}
private File getFile()
{
File folder = new File("sdcard/camera_app");
if (!folder.exists())
{
folder.mkdir();
}
File image_file = new File(folder,"cam_image.jpg");
return image_file;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String path = "sdcard/camera_app/cam_image.jpg";
imageView.setImageDrawable(Drawable.createFromPath(path));
super.onActivityResult(requestCode, resultCode, data);
}
}
You need to give READ_EXTERNAL_STORAGE and WRITE_EXTERNAL STORANGE permissions programmatically.
MANIFEST PERMISSIONS WON'T WORK on Android 6
With marshmallow(newest version of Android). We have got some restrictions in Using Sensitive permissions like : Storage,Contacts access, etc..In edition to give these permissions in manifest, We need to request them from users at Runtime.
For more details refer this : Android M permissions
For coding reference please refer this SO question : Android marshmallow request permission?
Add this code in your activity :
#Override
protected void onStart() {
super.onStart();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int hasWritePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
int hasReadPermission = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
int hasCameraPermission = checkSelfPermission(Manifest.permission.CAMERA);
List<String> permissions = new ArrayList<String>();
if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (hasReadPermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (hasCameraPermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.CAMERA);
}
if (!permissions.isEmpty()) {
requestPermissions(permissions.toArray(new String[permissions.size()]), 111);
}
}
}
Add this after onActivityResult :
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 111: {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
System.out.println("Permissions --> " + "Permission Granted: " + permissions[i]);
} else if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
System.out.println("Permissions --> " + "Permission Denied: " + permissions[i]);
}
}
}
break;
default: {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
After android 6.0 permission structure has changed. You must check permission on run-time. For example you will select a picture from image gallery, User give permission for gallery access before entering gallery.
You can look this document for this newness.
https://developer.android.com/training/permissions/requesting.html
Sample code for your issue
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
return true;
}
If not, you need to ask the user to grant your app a permission:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
Good luck :)