Some phones need permission READ_CONTACTS to read from contact picker - java

I have a HTC ONE M7 (GPE 4.2.2) and HTC EVO 3D (4.0.3) HTC Sense 3.6
HTC ONE does not need:
<uses-permission android:name="android.permission.READ_CONTACTS" />
on HTC EVO 3D however, following code throws an exception:
public static String getPhoneNumberFromIntent(Context context, Intent data) throws SecurityException {
String contactNumber = null;
final Uri contactUri = data.getData();
if (contactUri != null) {
Cursor c = null;
try {
// Read contact number from contacts provider
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER};
c = context.getContentResolver().query(contactUri, projection, null, null, null);
if (c != null && c.moveToFirst()) {
int maxNumberLength = context.getResources().getInteger(R.integer.max_phone_number_cze);
contactNumber = cutOnlyLastPhoneNumberDigits(c.getString(0), maxNumberLength);
}
} finally {
if (c != null) {
c.close();
}
}
}
return contactNumber;
}
-
java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.HtcContactsProvider2
uri content://com.android.contacts/data/2158 from pid=14938, uid=10125 requires android.permission.READ_CONTACTS
I have read that appliaction is granted required permissions when user selects contact by hand. However on some phones this does not work (HTC EVO 3D).
Why is this happending? Is there a workaround such is ability to ask for this permission at runtime ?

HTC ONE does not need: <uses-permission android:name="android.permission.READ_CONTACTS" /> on HTC EVO 3D however, following code throws an exception
If the Uri you are getting is coming from ACTION_PICK or ACTION_GET_CONTENT, whether or not you have temporary read permissions for that contact will vary by contact-picking app.
I have read that appliaction is granted required permissions when user selects contact by hand. However on some phones this does not work (HTC EVO 3D).
There is no requirement that all contact-picking apps grant you temporary read access to the contact. In fact, I am unclear if third-party contact managers would have the ability to grant you temporary read access to the contact.
Is there a workaround such is ability to ask for this permission at runtime ?
You cannot change your mix of candidate permissions at runtime.
Your choices are:
Always ask for READ_CONTACTS in the manifest. This ensures you can do what you want, at the cost of requesting another permission, one that prospective users might not like.
Handle the SecurityException and simply do without the data that you are trying to query(), if that data is not essential.
Write a separate app with the READ_CONTACTS permission that can serve as a "plugin" for your app, securely retrieving contact data on behalf of your main app. You can then route users who get the SecurityException to install your contacts plugin. This is tricky to write without introducing security flaws, so I would encourage you to use either of the other options.

You can't ask permission at run-time. You can only add a level API to your permission for example:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
It means that the permission is no needed if api is 19 or higher.

Related

Android 10 (Q) ACCESS_BACKGROUND_LOCATION permission

I need the user to check and set permission to ACCESS_BACKGROUND_LOCATION ("Allow all the time") without the option to "Allow only while using the app". My GPS Tracking app needs to continue accessing location even when the application is minimised.
I have already permissions working for ACCESS_FINE_LOCATION for Android 9.
AndroidManifest.xml--------------------------------------------------->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
TrackingActivity.java (need to include ACCESS_BACKGROUND_LOCATION)---->
private void permissionCheck1() {
int permissionCheck1 = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck1 != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
} else {
grantedSetupGPSandMap();
}
}
I need the only permission option to be "Allow all the time" if possible. How do I set this up when checking and setting permissions?
For Android 10, if:
You omit ACCESS_BACKGROUND_LOCATION, and:
You use a foreground service with the android:foregroundServiceType="location" property set in the manifest, then:
The system will supply only the "Allow only while using the app" and "Deny" options to the user, in reference to the location permission.
I realize that's the exact opposite of what you asked for, but the point is, under this condition, "Allow only while using the app" effectively behaves like "Allow all the time", provided the aforementioned foreground service is running.
You will be able to receive location updates even when the app is offscreen. And the user does not have the option of only partially allowing location updates; they have to choose between fully allowing it, or fully denying it.
EDIT
This answer also assumes your targetSdkVersion is 29.

How to get permission for deleting contacts in xiaomi (MIUI) devices?

I am making an app for managing contacts. On most phones, everything works fine, but on some Xiaomi devices, I get an error when trying to delete a contact.
Here is my code to delete contact -
final ArrayList ops = new ArrayList();
final ContentResolver cr = getContext().getContentResolver();
ops.add(ContentProviderOperation
.newDelete(ContactsContract.RawContacts.CONTENT_URI)
.withSelection(ContactsContract.RawContacts.CONTACT_ID + " = ?",
new String[]{contact.getContactId()})
.build());
try {
cr.applyBatch(ContactsContract.AUTHORITY, ops);
LogUtil.log(getString(R.string.log_msg_delete, contact.getDisplayName()));
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
}
I have permissions in the manifest file-
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
and asking for them in the runtime.
The problem only appears on some Xiaomi devices. On other manufacturers, everything works. Also, I checked other apps from play store and in some contact managers this issue is not present, so there should certainly be a way to fix it
Go to App permissions > Contacts and see that if AutoPhoner is checked or not. If it is not checked (not allowed) then please check it. And yes, your user needs to do this thing by his hand (Manually allow the permission).
I also faced a problem like you for Xiaomi devices. My app needs user permission from App permissions screen from Sittings (Allow Autostart for my app). I just showed my users the App permissions screen programmatically to give him extra flexibility because manually open App permissions screen is a hassle and bad UX for users. This will help you to do that.
And then if it don't work then I'm quite sure that it is not possible (deleting contact from phone book) in Xiaomi because Xiaomi uses customized OS of Android and they maybe restricted to delete contact from third party apps because of security issue.

Why is Accountmanager.get(context).getAccounts() returning securityexception?

It was my understanding that Accountmanager.get(context).getAccounts could not return a securityexception because it does not require permissions. From the documentation:
Clients of this method that have not been granted the GET_ACCOUNTS
permission, will only see those accounts managed by
AbstractAccountAuthenticators whose signature matches the client.
https://developer.android.com/reference/android/accounts/AccountManager.html#getAccounts()
So it reads as though if you haven't got GET_ACCOUNTS then that's fine, but my app is crashing when calling the method with the following exception:
caller uid # lacks any of android.permission.GET_ACCOUNTS
Why would this happen?
Account[] accounts = AccountManager.get(parentActivity).getAccounts();
Your app lacks of the matching permission in your manifest.
Add
<uses-permission
android:name="android.permission.GET_ACCOUNTS" />
to your AndroidManifest.xml
Edit: For Android 6.0, request it at runtime: http://developer.android.com/training/permissions/requesting.html
GET ACCOUNTS:
Allows access to the list of accounts in the Accounts Service.
Protection level: dangerous

Android 6.0 open failed: EACCES (Permission denied)

I have added uses-permission including WRITE_EXTERNAL_STORAGE,MOUNT_UNMOUNT_FILESYSTEMS,READ_EXTERNAL_STORAGE to AndroidManifest.xml.
When I tried to run my application in Nexus5 (Android 6.0),it threw a exception as below:
java.io.IOException: open failed: EACCES (Permission denied)
And I tried another Android phone(Android 5.1),everything was OK.Here's the code:
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
currentPhotoPath = image.getAbsolutePath();
return image;
}
Does Android 6.0 have difference about permission?
Android added new permission model for Android 6.0 (Marshmallow).
http://www.captechconsulting.com/blogs/runtime-permissions-best-practices-and-how-to-gracefully-handle-permission-removal
So you have to check Runtime Permission :
What Are Runtime Permissions?
With Android 6.0 Marshmallow, Google introduced a new permission model that allows users to better understand why an application may be requesting specific permissions. Rather than the user blindly accepting all permissions at install time, the user is now prompted to accept permissions as they become necessary during application use.
When to Implement the New Model?
it doesn’t require full support until you choose to target version 23 in your application. If you are targeting version 22 or below, your application will request all permissions at install time just as it would on any device running an OS below Marshmallow.
This information is taken from here :
Please check How to implement from this link :
http://www.captechconsulting.com/blogs/runtime-permissions-best-practices-and-how-to-gracefully-handle-permission-removal
In Android 6(Marshmallow), even though the user accepted all your permissions at install time, they can later decide to take some of those permissions away from you.
Fast solution but not recommended: maybe if you change your targetSdkVersion in the gradle to 22, the problem will be solved.
How To Implement?(Best Practices)
First determine if the user’s device is a Marshmallow device or not:
private boolean shouldAskPermission(){
return(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1);
}
If shouldAskPermission() return true, ask for permission you need:
String[] perms = {"android.permission.WRITE_EXTERNAL_STORAGE"};
int permsRequestCode = 200;
requestPermissions(perms, permsRequestCode);
The method requestPermissions(String[] permissions, int requestCode); is a public method found inside of the Android Activity class.
You will receive the results of your request in the method onRequestPermissionResult as shown below:
#Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
switch(permsRequestCode){
case 200:
boolean writeAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
break;
}
}
After receiving the results, you will need to handle them appropriately.
Suggested Permissions Flow:
More Info:
A user with a Marshmallow device will now have the ability to revoke dangerous permissions via the application settings
Android defines some permissions as “dangerous” and some permissions as “normal.” Both are required in your application’s manifest but only dangerous permissions require a runtime request.
If you have chosen not to implement the new permissions model(runtime request), the revocation of permissions can cause unwanted user experiences and in some cases application crashes.
The table below lists all the current dangerous permissions and their respective groups:
If the user accepts one permission in a group/category they accept the entire group!
Source:http://www.captechconsulting.com
Using Dexter Library:
You can use Dexter. Android library that simplifies the process of requesting permissions at runtime.
You can also use ActivityCompat.requestPermissions for backwards compatible.
example:
private static final int REQUEST_CODE = 0x11;
String[] permissions = {"android.permission.WRITE_EXTERNAL_STORAGE"};
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE); // without sdk version check
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// save file
} else {
Toast.makeText(getApplicationContext(), "PERMISSION_DENIED", Toast.LENGTH_SHORT).show();
}
}
}
From API-23 you need to declare the permission in activity even if you have already declared in manifest.
// Storage Permissions variables
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
//persmission method.
public static void verifyStoragePermissions(Activity activity) {
// Check if we have read or write permission
int writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int readPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
if (writePermission != PackageManager.PERMISSION_GRANTED || readPermission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
To use simply call verifyStoragePermissions(this); in onCreate.
That should do it hopefully.
If you are lazy, just downgrade targetSdkVersion to 22 (before lollipop)
This worked for me.
Go to Settings -> Applications -> YourApp -> Provide permissions to Storage, Contacts etc.
Google has a new feature on Android Q: filtered view for external storage. A quick fix for that is to add this code in the AndroidManifest.xml file:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting Android Q. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
You can read more about it here: https://developer.android.com/training/data-storage/compatibility
For me, my phone connected as USB as MTP was the issue even after doing everything stated here. Switched it to "Charging Only" worked for me.
I met the same trouble.
Maybe it is caused by your phone security mechanism. You may go to 'settings' to authorize write/read permissions.

How can I get all applications that have the internet permission in Android Applications?

How can I get all applications that have the internet permission in Android?
How can I do that?
any idea?
You need to iterate over all installed apps, using the PackageManager.GET_PERMISSIONS flag. You can then check if the internet permission is in the returned value.
Sample code (based on this answer):
PackageManager p = context.getPackageManager();
final List<PackageInfo> apps = p.getInstalledPackages(PackageManager.GET_PERMISSIONS);
for (PackageInfo pkg : apps) {
for (String permission : pkg.requestedPermissions) {
// Check if permission is the internet permission
}
}

Categories