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

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
}

Related

onReqestPermissionResult not being called in android dynamic permission

i am trying to invoke the user to enable their write external storage permission at run time. i have used the below code. it shows the run time permission dialog. when i click allow or deny, it will doesn't call the onReqestPermissionResult (call back method) method.
what i have to do for that?
public class PermissionCheck extends Activity {
private static final String TAG = "PermissionCheck";
private Fragment mFragment;
private Activity mActivity;
public PermissionCheck(Fragment fragment){
mFragment = fragment;
mActivity = fragment.getActivity();
}
public boolean isStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
return true;
} else {
ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
}
else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]);
}
}
}
You are passing another activity's instance in requestPermissions, so the onRequestPermissionResult is called in your mActivity and not in the PermissionCheck. Try changing requestPermissions to this :
ActivityCompat.requestPermissions(PermissionCheck.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
Replace:
ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
With :
ActivityCompat.requestPermissions(PermissionCheck.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
And replace onRequestPermissionsResult() to this:
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getActivity(), "Permission is granted", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(), "Please give your permission.", Toast.LENGTH_LONG).show();
}
break;
}
}
}

Can we ask same runtime permission at the different location in android?

I have a navigation drawer. In navigation drawer I am doing inflate the fragment. At the first fragment I ask to user for the runtime permission. but in the second fragment I want to do that it ask user for the same permission again. but in my case first fragment ask the permission. but in the second fragment it does not ask for the permission. so can anyone tell me what is the issue? because I am using the same code in the both situation.
This is my first fragment code :-
if (checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, getActivity().getApplicationContext(), getActivity())) {
IsConsumed = 1;
fetchLocationData();
} else {
requestPermission(Manifest.permission.ACCESS_FINE_LOCATION, PERMISSION_REQUEST_CODE_LOCATION, getActivity().getApplicationContext(), getActivity());
}
public void requestPermission(String strPermission, int perCode, Context _c, Activity _a) {
if (ActivityCompat.shouldShowRequestPermissionRationale(_a, strPermission)) {
Toast.makeText(getActivity(), "GPS permission allows us to access location data. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(_a, new String[]{strPermission}, perCode);
}
}
public static boolean checkPermission(String strPermission, Context _c, Activity _a) {
int result = ContextCompat.checkSelfPermission(_c, strPermission);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE_LOCATION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
fetchLocationData();
} else {
Toast.makeText(getActivity(), "Permission Denied, You cannot access location data.", Toast.LENGTH_LONG).show();
}
break;
}
}
I am using the same code in the second fragment. but it does not ask for the permission.I tried to print the log it goes into the if() condition.and print the log. but it does not ask for the permission.

request permission window force application to stop

I need to request a permission manually for API level 23 and where the dialog window appears and the application goes into background.
Here is my code:
#Override
public void onDialogDone(int dialog, boolean result) {
DialogFragment newFragment;
switch (dialog) {
case EULA_DIALOG:
if (result) {
boolean numberExists = _appRegistration.checkPhoneNumber();
if (!numberExists) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_PHONE_STATE_READ);
return;
} else {
//do some work
}
} else {
Intent intent = new Intent(...);
startActivity(intent);
finish();
}
break;....
}
}
Also, in the MainActivity I have overridden the following method:
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case MY_PERMISSIONS_PHONE_STATE_READ: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// do some work
} else {
// do some work
}
return;
}
}
But if I click "allow" or "deny", this method is not called, because application is in background mode... I logged onPause and onStop methods and both of them are called after the permission window is shown.
There was MainActivity problem, in manifest file it was configured as:
android:noHistory="true"
I just removed this property and application started working as it was expected.
Try with this
if (!numberExists) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_PHONE_STATE_READ);
return;
This way you are starting the request from your activity and the callbacks will be received.

Understanding the Android 6 permission method

I am trying to take an image from Gallery and set it to an imageview but in Android 6 there are some permission problems. Below is the method to ask for the permission. Should I ask for read external storage or write external storage?
Here is what I have done so far:
private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1;
public void getPermissionToReadExternalStorage() {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(
Manifest.permission.READ_EXTERNAL_STORAGE)) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
READ_CONTACTS_PERMISSIONS_REQUEST);
}}}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[],
#NonNull int[] grantResults){
// Make sure it's our original READ_CONTACTS request
if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getActivity(), "Read Contacts permission granted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "Read Contacts permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Now my on click listener to pick data from the Gallery:
pro.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
if (android.os.Build.VERSION.SDK_INT >= 23) {
getPermissionToReadExternalStorage();
if (getPermissionToReadExternalStorage () this???? <==)
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
} else {
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
}}
});
return v;
}
Now I want to get result of the method getPermissionToReadExternalStorage() so I can start the Activity for picking gallery for Android 6. How can I get the result of the void class?
And another thing is do I have to write method for every permission my app asks for?
So I have completely rewritten the code to request permissions.
Now it supports requesting for multiple permissions and running code with proper result.
Also it works with preMarshmallow devices, so you don't have to check and copy the code in that case.
First, create an Activity class with this code (You can extend any king of activity you need, e.g. AppCompatActivity):
public abstract class PermissionActivity extends AppCompatActivity {
private final ArrayList<PermissionListener> permissionListeners = new ArrayList<>();
#SuppressWarnings("unused")
public void requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener) {
requestPermissions(requestCode, requestPermissions, null, permissionListener);
}
#SuppressWarnings("unused")
public void requestPermissions(final int requestCode, String[] requestPermissions, String message, final PermissionListener permissionListener) {
final int[] grantResults = new int[requestPermissions.length];
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList<String> list_notGranted = new ArrayList<>();
for (String requestPermission : requestPermissions)
if (ContextCompat.checkSelfPermission(this, requestPermission) != PackageManager.PERMISSION_GRANTED)
list_notGranted.add(requestPermission);
if (list_notGranted.size() > 0) {
permissionListeners.add(permissionListener);
requestPermissions = list_notGranted.toArray(new String[list_notGranted.size()]);
if (message != null) {
boolean shouldShowRequestPermissionRationale = false;
for (String permission : requestPermissions)
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
shouldShowRequestPermissionRationale = true;
break;
}
if (shouldShowRequestPermissionRationale) {
final String[] f_requestPermissions = requestPermissions;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message);
DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
PermissionActivity.super.requestPermissions(f_requestPermissions, requestCode);
break;
default:
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_DENIED;
if (permissionListener != null)
permissionListener.onResult(requestCode, f_requestPermissions, grantResults);
break;
}
}
};
builder.setPositiveButton("OK", onClickListener);
builder.setNegativeButton("Cancel", onClickListener);
builder.show();
} else {
super.requestPermissions(requestPermissions, requestCode);
}
} else {
super.requestPermissions(requestPermissions, requestCode);
}
} else {
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_GRANTED;
if (permissionListener != null)
permissionListener.onResult(requestCode, requestPermissions, grantResults);
}
} else {
if (permissionListener != null) {
for (int i = 0; i < grantResults.length; i++)
grantResults[i] = PackageManager.PERMISSION_GRANTED;
permissionListener.onResult(requestCode, requestPermissions, grantResults);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
for (Iterator<PermissionListener> it = permissionListeners.iterator(); it.hasNext(); ) {
PermissionListener permissionListener = it.next();
if (permissionListener.onResult(requestCode, permissions, grantResults)) {
it.remove();
}
}
}
public interface PermissionListener {
boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults);
}
}
If you want to request permissions from Fragments, add this class:
public class PermissionFragment extends Fragment {
#SuppressWarnings("unused")
public void requestPermissions(int requestCode, String[] requestPermissions, PermissionActivity.PermissionListener permissionListener) {
requestPermissions(requestCode, requestPermissions, null, permissionListener);
}
#SuppressWarnings("unused")
public void requestPermissions(final int requestCode, String[] requestPermissions, String message, PermissionActivity.PermissionListener permissionListener) {
((PermissionActivity) getActivity()).requestPermissions(requestCode, requestPermissions, message, permissionListener);
}
}
Your Activities and Fragments should extend these classes instead of the standart ones.
Now you are ready to request the permissions by calling a method:
requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener)
If the permission is required for the app to work, you should call this method and specify the message saying why the permission is required.
requestPermissions(int requestCode, String[] requestPermissions, String message, PermissionListener permissionListener)
DONT MISSCALL THE DEFAULT METHOD, WHICH IS
// DON'T USE THIS ONE!
requestPermissions(String[] requestPermissions, int requestCode)
// DON'T USE THIS ONE!
Here is the example of requesting contacts:
private void requestAndLoadContacts() {
String[] permissions = new String[]{Manifest.permission.READ_CONTACTS};
requestPermissions(REQUEST_PERMISSIONS_CONTACTS, permissions, "Read contacts permission is required for the app to work!", new PermissionListener() {
#Override
public boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults) {
// Check if the requestCode is ours
if (requestCode == REQUEST_PERMISSIONS_CONTACTS) {
// Check if the permission is correct and is granted
if (requestPermissions[0].equals(Manifest.permission.READ_CONTACTS) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted
// Calling a method to actually load the contacts
loadContacts();
} else {
// Permission not granted
Toast.makeText(MainActivity.this, "Access denied!", Toast.LENGTH_SHORT).show();
}
return true;
}
return false;
}
});
}
NOTE:
When you implement the PermissionListener, don't forget to return true when the requestCode is the correct one, otherwise the PermissionListener won't be removed from the ArrayList and you'll most likely get a small memory leak.
EDIT
I have rewritted the code and posted in another answer.
Old answer:
Yes, you have to check and ask for permission every time.
Usually I write the code like this:
private int requestPermissionCode;
private Runnable requestPermissionRunnable;
private void runPermissionCode(String requestPermission, int requestCode, Runnable codeToRun) {
if (android.os.Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissionCode = requestCode;
requestPermissionRunnable = codeToRun;
requestPermissions(new String[]{requestPermission},
requestCode);
}
} else {
codeToRun.run();
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[],
#NonNull int[] grantResults) {
if (requestCode == requestPermissionCode) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestPermissionRunnable != null)
requestPermissionRunnable.run();
} else {
Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
and run it like this:
runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() {
#Override
public void run() {
// your code here
}
});
I am sure it is not a best way, but at least it gives a possibility to request permission and make actions easier.
Initialize Your Permission
private static final int INITIAL_REQUEST = 1337;
private static final int GET_ACCOUNTS = INITIAL_REQUEST+2;
private static final int LOCATION_REQUEST =INITIAL_REQUEST+3;
private static final String[] INITIAL_PERMS = {
Manifest.permission.GET_ACCOUNTS,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_FINE_LOCATION
};
Check for device and Request for permissions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!canAccessAccounts()|| !canAccessLocation() ||!canAccessInternet()) {
requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
}
}
Check Permission is granted Or not
private boolean canAccessAccounts() {
return (hasPermission(Manifest.permission.GET_ACCOUNTS));
}
private boolean canAccessLocation() {
return (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
private boolean canAccessInternet() {
return (hasPermission(Manifest.permission.INTERNET));
}
private boolean hasPermission(String perm) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
}
return (true);
}
Update Permissions and Check method for permissions onRequestPermissionsResult
void UpdatePermissions(){
canAccessInternet();
canAccessLocation();
canAccessInternet();
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
UpdatePermissions();
switch(requestCode) {
case GET_ACCOUNTS:
if (canAccessAccounts()) {
}
else {
}
break;
case LOCATION_REQUEST:
if (canAccessLocation()) {
}
else {
}
break;
case INITIAL_REQUEST:
if(canAccessInternet()){
}else {
}
break;
}
}

Android Preview M: activity recreates after permission grant

I play around with the Preview M and test my app on it, especially the "saving a file to external storage" part.
Before the download/save process starts, i request for
Manifest.permission.WRITE_EXTERNAL_STORAGE
permission as described on the developer page: https://developer.android.com/preview/features/runtime-permissions.html
The dialog occurs as expected:
"Allow <AppName> to access photos, media, and files on your device?" Deny / Allow
If i hit the "deny"-button, the onRequestPermissionsResult-method of the activity is called.
If i press the "allow"-button, the activity is first recreated and afterwards the onRequestPermissionsResult-method is called. I think it's a result of the granted permission.
But the second situation is tricky because i want to trigger a callback that starts the download, but this object is null at this point:
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
getLogger().error("onRequestPermissionsResult ( " + requestCode + ", " + permissions + ", " + grantResults + " )");
switch (requestCode) {
//permission for saving files?
case PermissionCode.WRITE_EXTERNAL_STORAGE: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//HERE IS THE NULL-OBJECT
if (controller != null) {
controller.triggerCallback();
}
}
break;
}
default: {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
So my questions are:
Can I avoid this recreation?
If no, how can i redesign my code to solve the problem - i'm totally idealess at the moment
EDIT 1:
I tried to solve the problem with a handler and postDelayed - but i skipped it.
EDIT 2:
I preliminary solved it and show a Toast to user with the request to push the download button again (in case of granted permission). But Google: ARE YOU SERIOUS?
EDIT 3:
No recreation happens with the latest SDK 6.0 (Version 23) - maybe somebody heard my weeping in Mountain View :-)
You can always check the download condition immediately after the activity recreates itself in onCreate():
static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 0;
boolean initiateDownload = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
initiateDownload = savedInstanceState.getBoolean("toDownload");
}
}
#Override
public void onResume() {
super.onResume();
final boolean hasPermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED;
if(initiateDownload && hasPermission) {
// start download here...
} else {
requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE},
MainActivity.MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE) {
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initiateDownload = true;
} else {
// denied permission...
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("toDownload", initiateDownload);
}
Android may destroy and recreate your activity for a number of reasons. The use case of requesting permissions is no exception. You can use your preferred way of saving and restoring UI state. If your state is parcelable you can do it like the example below. Why this is not mentioned in Request App Permissions or Android RuntimePermissions Sample I don't know.
See more in
Saving and restoring transient UI state
and
Saving UI States
public class ExampleActivity extends AppCompatActivity {
private static final String CURRENT_DOWNLOAD_ITEM = "CURRENT_DOWNLOAD_ITEM";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
currentDownloadItem = savedInstanceState.getParcelable(CURRENT_DOWNLOAD_ITEM);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putParcelable(CURRENT_DOWNLOAD_ITEM, currentDownloadItem);
super.onSaveInstanceState(outState);
}
public void downloadItem(Parcelable item) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
currentDownloadItem = item;
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
} else
perfornDownload(item);
}
private Parcelable currentDownloadItem;
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (currentDownloadItem != null) {
perfornDownload(currentDownloadItem);
currentDownloadItem = null;
} else
Toast.makeText(this, "Please select download again now that we have permission to save it", Toast.LENGTH_LONG).show();
} else
Toast.makeText(this, "Download cancelled, as we don\'t have permission to save the downloaded files", Toast.LENGTH_LONG).show();
break;
}
}
private void perfornDownload(Parcelable item) {
// Here we are sure we have the permission
}
}

Categories

Resources