I got this error when I tried to debug my app
java.lang.NoSuchMethodError: No virtual method requestPermissions([Ljava/lang/String;I)V in class Lcom/cscodetech/townclap/activity/LoginActivity; or its super classes (declaration of 'com.zestar.myclip.activity.LoginActivity' appears in /data/app/com.zestar.myclip-1/base.apk:classes2.dex)
at com.zestar.myclip.activity.LoginActivity.onCreate(LoginActivity.java:92)
The logcat pointed to this line of code
requestPermissions(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 1);
What is wrong with that line
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
FirebaseApp.initializeApp(this);
requestPermissions(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 1);
custPrograssbar = new CustPrograssbar();
sessionManager = new SessionManager(LoginActivity.this);
atCode.setOnFocusChangeListener((view, b) -> {
if (!b) {
// on focus off
String str = atCode.getText().toString();
ListAdapter listAdapter = atCode.getAdapter();
for (int i = 0; i < listAdapter.getCount(); i++) {
String temp = listAdapter.getItem(i).toString();
if (str.compareTo(temp) == 0) {
return;
}
}
atCode.setText("");
}
});
getCodelist();
}
as requestPermissions like #TylerV said, try using this way instead
as instructed in
Documentation for how to request app permissions | Android Developers
this should be the right way to request permissions in fragments which goes as this:
You first initialize this variable in fragment/activity which specifies what should happen if the permissions were granted or not:
private ActivityResultLauncher requestPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> { {
//result is a map(string permission,boolean granted or not)
//to check if all permissions were granted or not
if(result.containsValue(false)){
// Explain to the user that the feature is unavailable because
// the features requires a permission that the user has denied.
// At the same time, respect the user's decision. Don't link to
// system settings in an effort to convince the user to change
// their decision.
Toast.makeText(getContext(), "Can't continue without the required permissions", Toast.LENGTH_LONG).show();
}
else {
//continue your work flow
}
});
Then when you need to request for a permission you call launch on the object you declared with an array holding the permission you're requesting :
if (ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.ACCESS_FINE_LOCATION) {
requestPermissionLauncher.launch(new String[]{Manifest.permission.CALL_PHONE,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION});
} else // continue your work
Please provide your logs when exception occurs. Maybe error is because of android version. You must check if android version is bigger than Api level 26 (Marshmallow):
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
}
Related
so, I tried to get a permission with the new registerForActivityResult() method and ask for with button click with .launch() and it doesn´t seem to be opening any window to ask for it.
I´m always getting false in registerForActivityResult().
// Permission to get photo from gallery, gets permission and produce boolean
private ActivityResultLauncher<String> mPermissionResult = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
new ActivityResultCallback<Boolean>() {
#Override
public void onActivityResult(Boolean result) {
if(result) {
Log.e(TAG, "onActivityResult: PERMISSION GRANTED");
} else {
Log.e(TAG, "onActivityResult: PERMISSION DENIED");
}
}
});
// Launch the permission window -- this is in onCreateView()
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mPermissionResult.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
}
});
This is my LOG always: onActivityResult: PERMISSION DENIED
UPDATE
This answer works, but I found a better solution for permission requests with no open holes here.
From docs:
In your Activity/Fragment, create this field:
// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher, as an instance variable.
private ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(new RequestPermission(), isGranted -> {
if (isGranted) {
// Permission is granted. Continue the action or workflow in your
// app.
} else {
// Explain to the user that the feature is unavailable because the
// features requires a permission that the user has denied. At the
// same time, respect the user's decision. Don't link to system
// settings in an effort to convince the user to change their
// decision.
}
});
Somewhere in the same Activity/Fragment:
if (ContextCompat.checkSelfPermission(
context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...);
} else {
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
requestPermissionLauncher.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
}
If you are getting unreasonable "Permission denied" all the time, maybe you did not declare it in your manifest.xml?
Looking at Update to androidx.fragment:fragment:1.3.0-alpha08: registerForActivityResult not allowed after onCreate anymore. How to use after onCreate?,
private lateinit var checkLocationPermission: ActivityResultLauncher<Array<String>>
// Initialize checkLocationPermission in onAttach or onCreate.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
checkLocationPermission = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if (permissions[Manifest.permission.ACCESS_FINE_LOCATION] == true ||
permissions[Manifest.permission.ACCESS_COARSE_LOCATION] == true) {
initUserLocation()
} else {
// Permission was denied. Display an error message.
}
}
}
fun showMap() {
if (ActivityCompat.checkSelfPermission(requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(requireContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
initUserLocation()
} else {
checkLocationPermission.launch(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION))
}
}
private fun initUserLocation() {
googleMap?.isMyLocationEnabled = true
}
I going to change some system setting in android and i use this code :
ContentResolver cr = getContentResolver();
Settings.System.putInt(cr, Settings.System.HAPTIC_FEEDBACK_ENABLED, 0);
this code used for change screen Brightness use Brightness sensor,
but in android 6 I get this exception
java.lang.SecurityException: com.vpn.sabalan was not granted this permission: android.permission.WRITE_SETTINGS.
i can use this method to get permission from user , but i need get permission programmetically can any one help me ?
private void showBrightnessPermissionDialog( )
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !android.provider.Settings.System.canWrite(this))
{
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:"+getPackageName()));
startActivity(intent);
}
}
Update Android Marshmallow and Higher
You can start System settings to grant Write System Settings. Once this permission is grant by user you can set brightness without any issues
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.System.canWrite(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
}
Follow the step by step provided in documentation. It is very thorough.
https://developer.android.com/training/permissions/requesting.html
All you have to do is request permission, and override the callback for onRequestPermissionsResult to check if you got it or not. If you did, then you are good to go. You still need it in your manifest though or it won't work.
UPDATE to show details based on your comments.
public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback{
private static final int REQUEST_WRITE_PERMISSION = 1001;
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
doFileWork();
}else{
//handle user denied permission, maybe dialog box to user
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermission();
}
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 {
doFileWork();
}
}
}
There are also many good libraries out there that wrap this callback context if you really want to go that route, but it isn't that complex. Make sure you also have write permission in your Manifest.
I am trying to provide Notification Access to my app, for that I have added below permission in Manifest
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
Also I have registered listener as below on activity.
IntentFilter notlist = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
notlist = new IntentFilter(ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED);
}
Intent notlistch = registerReceiver(null,notlist);
Now when user clicks on button I have below code
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
startActivity(new Intent(ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS));
}
Now If I click on button with above code in it, this will always take me to notification settings, so if my app has got access during first click, how can I check it before throwing intent for opening settings.
I read to use ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED, but did not understand how to use it. Can anyone help me.
ideally I should check access status first and then on getting false, I should call intent to open notification settings.
You can check it in a way like this:
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_NOTIFICATION_POLICY) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_NOTIFICATION_POLICY)) {
} else {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_NOTIFICATION_POLICY}, RC_ACCESS_NOTIFICATION_POLICY);
}
}
RC_ACCESS_NOTIFICATION_POLICY is the key that you can get the result by this in this way with onPermissionGranted
if anyone still looking for a solution this is my solution
private boolean isNotificationServiceEnabled() {
String pkgName = getPackageName();
final String flat = Settings.Secure.getString(getContentResolver(),
ENABLED_NOTIFICATION_LISTENERS);
if (!TextUtils.isEmpty(flat)) {
final String[] names = flat.split(":");
for (String name : names) {
final ComponentName cn = ComponentName.unflattenFromString(name);
if (cn != null) {
if (TextUtils.equals(pkgName, cn.getPackageName())) {
return true;
}
}
}
}
return false;
}
Below code is working fine on pre-Marshmallow devices but not in Marshmallow.
These are the permissions in Manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Here is the code
public void saveImageToSDCard(Bitmap bitmap) {
File myDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
pref.getGalleryName());
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Wallpaper-" + n + ".jpg";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
Uri uri = getImageContentUri(_context,file);
Log.d(TAG, "Wallpaper saved to: " + file.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
}
And the same code works when I manually allow the storage permission
Here is the solution given by Nitesh Pareek.
private boolean hasPermissions(Context context, String[] permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
String[] PERMISSIONS = new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, 11);
return;
}
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
This is why it works in pre-lolipop versions, and doesn't on API 23. Permissions in Android Manifest alone are not enough, you need to add them at runtime as well. Refer here for more details.
give read write permissions on run time for marshmallow or newer version.
Do like below:-
String[] PERMISSIONS = new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, 11);
return;
}
private boolean hasPermissions(Context context, String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
You need to take application permissions at runtime instead of taking when install/update as convention
Beginning in Android 6.0 (API level 23), users grant permissions to
apps while the app is running, not when they install the app. This
approach streamlines the app install process, since the user does not
need to grant permissions when they install or update the app
For more help: Requesting Permissions at Run Time
By focusing on the documentation and after doing some google searches, finally I have compiled the code below to handle runtime permissions efficiently
To make it work, you need to follow the instructions below:
Call this method to check if storage permission is granted by user?
If not, then you need to request for it
public static boolean isStoragePermissionGranted(Activity activity) {
boolean flag = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
flag = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
return flag;
}
Call this method to request storage permission
public static void requestStoragePermission(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (isStoragePermissionGranted(activity)) {
return;
}
// Fire off an async request to actually get the permission
// This will show the standard permission request dialog UI
activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_STORAGE_PERMISSION);
}
}
Implement this method in your activity to handle response of permission callback
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_CODE_STORAGE_PERMISSION:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
boolean shouldShowRationale = shouldShowRequestPermissionRationale(permissions[0]);
if (!shouldShowRationale) {
// user denied flagging NEVER ASK AGAIN, you can either enable some fall back,
// disable features of your app or open another dialog explaining again the permission and directing to
// the app setting
dialogReasonStoragePermissionToSettings(this);
} else if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permissions[0])) {
// user denied WITHOUT never ask again, this is a good place to explain the user
// why you need the permission and ask if he want to accept it (the rationale)
dialogReasonStoragePermission(this);
}
} /*else {
// Do on permission granted work here
}*/
}
}
break;
}
}
public static void dialogReasonStoragePermission(final Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(activity.getString(R.string.reason_storage_permission));
builder.setCancelable(false);
builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
requestStoragePermission(activity);
}
});
builder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
public static void dialogReasonStoragePermissionToSettings(final Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(activity.getString(R.string.reason_storage_permission));
builder.setCancelable(false);
builder.setPositiveButton("Go to Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
goToAppDetailsForPermissionSettings(activity);
}
});
builder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
private static final int REQUEST_CODE_APP_DETAILS_PERMISSION_SETTING = 3995;
private static void goToAppDetailsForPermissionSettings(Activity activity) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri);
activity.startActivityForResult(intent, REQUEST_CODE_APP_DETAILS_PERMISSION_SETTING);
}
I am not providing you direct code for this but here is a reason API level 23 introduce a new Permission structure for more security below is a short but wast description of thing, in documentation here
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. This approach streamlines the app install process, since the user does not need to grant permissions when they install or update the app. It also gives the user more control over the app's functionality; for example, a user could choose to give a camera app access to the camera but not to the device location. The user can revoke the permissions at any time, by going to the app's Settings screen.
Code is good just you have to put something additional and that is Runtime Permissions for storage.
Read this blog to know everything from deep inside about Runtime Permissions gave me a clear picture about it, hope it helps you too.
Thanks
I am trying to create an app. App asking every time location Access in Marsh Mallow, always when we open the app. Please suggested the best Process for solve my problem. using following code-
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
//for marshmallow
final int LOCATION_PERMISSION_REQUEST_CODE = 100;
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
buildGoogleApiClient();
mGoogleApiClient.connect();
}
thanks.
Try writting in if else, if permission is not given ask for it or else do what you want to do.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(checkSelfPermission(Manifest.permission.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
} else {
// do your stuff
}
and also override onRequestPermissionsResult and apply your code afer you have granted permissions.
Please reflect your code yourself. Think about the order of requesting and checking the permission. You should check the permission before you're asking for it. This makes sure to prevent asking if the permission was already granted...
Have a look at the example provided by Google and consider adapting this example for your needs:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_CONTACTS)) {
// Show an expanation 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(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.
}
}
Additionally you should overwrite the callback method onRequestPermissionsResult to handle the user's grantResults.
// Callback with the request from calling requestPermissions(...)
#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(this, "Read Contacts permission granted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Read Contacts permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Edit:
This is thecode which you should change
ActivityCompat.requestPermissions(this, new String[] {android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
For further reading have a look at the article Understanding App Permissions