Android Marshmallow Permission Error - android

i am adding certain permissions to my app to allow access to camera for example and everything is working fine. but when i minimize the app and disable the permission then open the app, the app crashes without asking me to re-enable the permission(until i close the app and then open it). how can i fix this error so that the app dont crash and ask again for permission or safe restart to ask for permissions.
here is my code
in the main activity:
onCreate:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
GlobalVariables.MY_PERMISSIONS_REQUEST_CAMERA);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode)
{
case GlobalVariables.MY_PERMISSIONS_REQUEST_CAMERA:
{
if (grantResults.length <= 0
|| grantResults[0] != PackageManager.PERMISSION_GRANTED) {
globalVariables.ShowOKAlert("Error","Please Accept All Requested Permissions or the app wont function properly",this,false);
}
return;
}
}
}
the activity implements ActivityCompat.OnRequestPermissionsResultCallback

step 1:
String[] permissions = new String[]{
Manifest.permission.INTERNET,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
};
Step 2:-
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p : permissions) {
result = ContextCompat.checkSelfPermission(this, p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), 100);
return false;
}
return true;
}
Step 3:
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (requestCode == 100) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// do something
}
return;
}
}

You are checking that permission in onCreate. When you minimize and maximize the app again that method is not called.
Maybe you should check that permission in the extact point where you need it, or at least in onResume which surely is called again when you re-open your app.
Calling it in onResume ensure the app continues to work also if the user disables the permission in another window with the screen splitted (Android N feature).

The easy way to achieve this to use direct static method of ActivityCompat
public static void requestPermissions(final #NonNull Activity activity,
final #NonNull String[] permissions, final int requestCode)
Here you can see what parameters you have required for this
-- Activity Instance
-- String array of permissions
-- a user defined request code
Usage
Define global variables
//Run-time permissions for MarshMallow +
public final String[] PERMISSION_ALL = {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
//validateRequestPermissionsRequestCode requires requestCode to be of 8 bits, i.e. range: 0-255.
public final int PERMISSION_REQUEST_CODE = 100;
Finally in your activity oncreate() method you can call static function mentioned above
public class MainActivity extends AppCompatActivity
{
//your code here
#Override
protected void onCreate(Bundle savedInstanceState)
{
//do other code work
super.onCreate(savedInstanceState);
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= android.os.Build.VERSION_CODES.M)
{
ActivityCompat.requestPermissions(this, PERMISSION_ALL, PERMISSION_REQUEST_CODE);
}
//do other code work
}
//your code here
}
And you are done....
For more Info Click here about Android Permissions At Run Time

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

Android requestPermission Dialog not showing up

I am working with a Samsung Galaxy Tab S tablet and try to grant permission to write on the external storage at runtime.
However the dialog to request the permission does not show up. Instead in the code onRequestPermissionResult will be executed instantly with the a PERMISSION_DENIED result. I even tried granting the storage permission manually in the application settings on the device, but even then the result will be PERMISSION_DENIED (grantResults is -1).
My code looks like this:
public class MainActivity extends AppCompatActivity {
public static final int REQUEST_STORAGE_PERMISSION = 225;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
process();
} else {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERMISSION);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_STORAGE_PERMISSION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Permission Granted", Toast.LENGTH_LONG).show();
process();
} else {
Toast.makeText(getApplicationContext(), "Permission Denied", Toast.LENGTH_LONG).show();
}
}
}
public void process() {
//...
}
}
When starting the application, it will instantly show the "Permission Denied"-Toast, without showing me any dialog before. That happens, even if i grant the Storage-permission manually in the app settings of the tablet.
My manifest-file also contains the permission at the right place (outside of the application tags) as suggested in similar threads.
I tried reinstalling the app and even reset the tablet already, but nothing seems to work.
instead of:
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERMISSION);
it works for fragments
You need to use this: As you are using AppCompatActivity
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERMISSION);
EDIT
As you have multiple project module: you need to add permission in both of those Manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Do this thing
private boolean RequestPermissions() {
int camera = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.CAMERA);
int storage = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
List<String> listPermissionsNeeded = new ArrayList<>();
if (camera != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(CAMERA);
}
if (storage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(WRITE_EXTERNAL_STORAGE);
listPermissionsNeeded.add(READ_EXTERNAL_STORAGE);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(getActivity(), listPermissionsNeeded.toArray
(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}

Android M permissions close my app

I check for the required permissions on my Log In screen. The dialog shows asking for the 4 permissions I need. All good, but when the dialog appears, the background becomes black and my app closes (doesn't crash, just closes). When I'm done with choosing the permissions I open the app again and it continues running from where it stopped. How can I make the app continue running while the permissions dialog is shown? I use a class which checks for permissions and call it in the Log In activity.
The class:
public abstract class RuntimePermissionsActivity extends AppCompatActivity {
private SparseIntArray mErrorString;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mErrorString = new SparseIntArray();
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
for (int permission : grantResults){
permissionCheck = permissionCheck + permission;
}
if ((grantResults.length>0) && permissionCheck == PackageManager.PERMISSION_GRANTED){
onPermissionsGranted(requestCode);
}
else {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);
}
}
public void requestAppPermissions(final String[] requestedPermissions, final int requestCode){
int stringId = 0;
mErrorString.put(requestCode, stringId);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
boolean shouldShowRequestPermissionRationale = false;
for (String permission : requestedPermissions){
permissionCheck = permissionCheck + ContextCompat.checkSelfPermission(this, permission);
shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
}
if(permissionCheck != PackageManager.PERMISSION_GRANTED){
if(shouldShowRequestPermissionRationale){
ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
}
else {
ActivityCompat.requestPermissions(this, requestedPermissions, requestCode);
Toast.makeText(RuntimePermissionsActivity.this, "Please relaunch the application in order for the changes to take effect!", Toast.LENGTH_LONG).show();
}
}
else {
onPermissionsGranted(requestCode);
}
}
public abstract void onPermissionsGranted(int requestCode);
}
The Log In activity call:
LoginActivity.super.requestAppPermissions(new
String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSIONS);
I faced same issue,check if activity android:noHistory="true" in your Manifest file.
Same problem here.
ankit jain was on the track. Removing android:noHistory="true" fixed the N.Park problem.
Although in my case I needed that value to be true, or at least the behaviour that makes (I had a SplashScreen where I managed the permissions, and after moving on, I wanted that Activity out of my stack).
So:
I deleted line android:noHistory="true"
In the activity I manage the permission without problems
After that, I move into the next activity with:
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK );
An example of implementing Permissions in any Activity.
SampleActivity.java
public class SampleActivity extends AppCompatActivity{
private final int PERMISSION_CODE = 1;
Button button;
#override
onCreate(Bundle savedInstance){
super.onCreate(savedInstance);
setContentView(R.layout.your_layout);
button = (Button)findViewById(R.id.button);
button.setOnClickListener(new OnClickListener(){
#override
public void onClick(View view){
requestPermissionAndContinue();
}
});
//remaining code to continue using the app
//your actual code should also be in this same class
}
private void requestPermissionAndContinue(){
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED){
if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)){
Log.e(TAG, "permission denied, show dialog");
}else{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, PERMISSION_CODE);
}
}else{
accessContacts();
}
}
private void accessContacts(){
//your code once you receive permission
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(grantResults.length > 0 && permissions[0]==PackageManager.PERMISSION_GRANTED){
accessContacts();
}else{
//redirect to settings page or ask permission again
}
}
}
Remove android:noHistory="true" attribute from respective RuntimePermissionsActivity tag from Android manifest file solved that problem.
Write just a few lines of codes:
final int requestCode=100;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
String[] per = {Manifest.permission.READ_CONTACTS};
requestPermissions(per, requestCode);
if (ActivityCompat.checkSelfPermission(CollectZone.this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
// recall permission until is not permitted
} else {
// write execution code here
}
}

Android Marshmallow: Changing permissions at run time crashes app

Marshmallow has redesigned getting permissions. So Handled permissions before calling the method which needs permissions and it works fine, but It crashes in the following scenario:
Step 1: Opened app and gave all the necessary permissions
Step 2: Clicked Home button(So the app is in background)
Step 3: Manually changed the permissions in the Settings
Step 4: Launched the app from multitasks, now it crashes because of app context becomes invalid
Observed that app gets created again, don't understand why this happens. Any suggestions to rectify this issue would be welcome!
It's because of additional features added from Marshmallow. You need to request from user at runtime. For this use this class which I have made. Then use it whereever required
public class AppPermission {
public static boolean isMarshmallowPlusDevice() {
return Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1;
}
#TargetApi(Build.VERSION_CODES.M)
public static boolean isPermissionRequestRequired(Activity activity, #NonNull String[] permissions, int requestCode) {
if (isMarshmallowPlusDevice() && permissions.length > 0) {
List<String> newPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (PackageManager.PERMISSION_GRANTED != activity.checkSelfPermission(permission)) {
newPermissionList.add(permission);
}
}
if (newPermissionList.size() > 0) {
activity.requestPermissions(newPermissionList.toArray(new String[newPermissionList.size()]), requestCode);
return true;
}
}
return false;
}
}
Then put this code where you require permission from user.
if (!AppPermission.isPermissionRequestRequired(SignInActivity.this, new String[]{"android.permission.GET_ACCOUNTS"},
REQUEST_APP_PERMISSION)) {
// Your code if permission available
}
After this, in your Fragment or Activity put this code -
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_APP_PERMISSION:
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i];
int grantResult = grantResults[i];
switch (permission) {
case "android.permission.GET_ACCOUNTS":
if (PackageManager.PERMISSION_GRANTED == grantResult) {
// Your code
}
break;
}
}
break;
}
}
The above code is for request permission for GET_ACCOUNTS you can change it to whatever required.
Observed that app gets created again, don't understand why this
happens. Any suggestions to rectify this issue would be welcome!
Because when permissions change, application "state" should be invalidated. The proper way to do that is destroy the root context, which is the application itself.
You have to check the permissions granted status each time you query the API methods that require these permissions. You can't rely on some SharedPreferences flag indicating that "user granted the permissions in onboarding, ok, lets have fun". Make your app stateless in this regards.
For example, you can create some BaseActivity/BaseFragment or Utility and move all the checking logic in there.
Define a boolean value at first
private boolean isPermissionGranted = false;
And then check if permission granted:
if (!isPermissionGranted) {
checkPermission();
}
Actual code for run time permission check is as follow:
private void checkPermission() {
int hasPermission = ContextCompat.checkSelfPermission(UserProfile.this, Manifest.permission.CAMERA);
int hasWritePermission = ContextCompat.checkSelfPermission(UserProfile.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasPermission != PackageManager.PERMISSION_GRANTED && hasWritePermission != PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(UserProfile.this, Manifest.permission.CAMERA) && !ActivityCompat.shouldShowRequestPermissionRationale(UserProfile.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
showMessage(getString(R.string.allow_access_to_camera_external_storage),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(UserProfile.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_ASK_PERMISSIONS);
}
});
return;
}
ActivityCompat.requestPermissions(UserProfile.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_ASK_PERMISSIONS);
return;
} else {
isPermissionGranted = true;
}
}
private void showMessage(String message, DialogInterface.OnClickListener listener) {
new AlertDialog.Builder(UserProfile.this)
.setMessage(message)
.setPositiveButton(R.string.ok, listener)
.setNegativeButton(R.string.cancel, null)
.create()
.show();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_PERMISSIONS:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
isPermissionGranted = true;
} else {
isPermissionGranted = false;
Toast.makeText(UserProfile.this, R.string.permission_denied, Toast.LENGTH_SHORT)
.show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
You can take reference from above code and implement it in your application.

Categories

Resources