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.
Related
How to add extra protection in my device owner application so that if someone tries bypassing the FRP they can't use the phone.
I have seen this in some devices. they show a notification 'Device managed by admin automatically resetting soon' like this:
screenshot1
screenshot2
The app that showed this was using 'Android Management API'. I read about this but what I understood is that I think they install their own app as device owner in the device to add the FRP policy. In that case I think I will not be able to install my device owner app (or is it possible?).
I am using this code and it adds FRP (asks for the required gMail address during device setup) but it can be easily bypassed by following some YouTube videos and after that device does not show above notification.
try {
Bundle bundle = new Bundle();
bundle.putString("factoryResetProtectionAdmin", 432112340987654321234);//google Id
devicePolicyManager.setApplicationRestrictions(adminComponentName, "com.google.android.gms", bundle);
// send broadcast
Intent broadcastIntent = new Intent("com.google.android.gms.auth.FRP_CONFIG_CHANGED");
broadcastIntent.setPackage("com.google.android.gms");
broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
getApplicationContext().sendBroadcast(broadcastIntent);
} catch (Exception e) {
Log.d("FRP", e.getLocalizedMessage());
e.printStackTrace();
}
I am trying to clear a data from within the app and my app is device owner, hence I am getting and error
java.lang.SecurityExeception :Clearing DeviceOwner data is forbidden.
Code I am using is
public void onClearData(View view) {
try {
boolean isCleared = ((ActivityManager) getSystemService(ACTIVITY_SERVICE)).clearApplicationUserData();
if (!isCleared) {
Toast.makeText(this, "Not able to clear the data", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Now, my question is that how it will be possible to clear a data of device owner app from within the app? Would appreciate a help.
The way you're doing it is how it's done, according to the docs.
But since you're getting that security exception, your app is probably set as a device owner app, and you're not allowed to deactivate it, remove its data nor uninstall it while it is on this state.
If that's really the case I'd suggest you to unset it as a Device Owner App. Try to use dpm remove-active-admin for that.
Take a look at those questions for more info:
How to make my app a device owner?
How to remove set-device-owner in Android DPM?
Disable a device owner app from android terminal
I'm trying to develop an app that can get the Network stats from specific packages, but I'm getting these problems:
When I try to use the NetworkStats Library of Android 6.0(Marshmallow), I get this Exception:
NetworkStats: Neither user 10412 nor current process has
android.permission.READ_NETWORK_USAGE_HISTORY.
Here is the code:
try {
TelephonyManager tm;String subscriberID;
NetworkStatsManager networkStatsManager;
NetworkStats networkStats;NetworkStats.Bucket bucket;
tm = (TelephonyManager) mContext.getSystemService(mContext.TELEPHONY_SERVICE);
subscriberID = tm.getSubscriberId();
networkStatsManager = mContext.getSystemService(NetworkStatsManager.class);
networkStats = networkStatsManager.queryDetailsForUid
(typeMobile, subscriberID, dtBegin, dtEnd, uidPackage);
if(networkStats !=null){
while (networkStats.hasNextBucket()) {
bucket = new NetworkStats.Bucket();
networkStats.getNextBucket(bucket);
Log.d("Bucket RX:",bucket.getUid()+" -" +String.valueOf(bucket.getRxBytes()));
Log.d("Bucket TX:",bucket.getUid()+" -" +String.valueOf(bucket.getTxBytes()));
}
}
}
catch (Exception ex){
Logger.e(ex.getMessage());
}
How can I get the functionality of NetworkStats in previous versions of Android (5.0 & 4.0)? Is there any library?
READ_NETWORK_USAGE_HISTORY permission is only granted for system applications. So, unless you are using a rooted phone, you won't be able to use it. The only way out is to use TrafficStats which is available since API level 8.
Mmm ... After a little bit research over internet I give up on using this Android Native Library. I have managed to make it work, but its necessary that the user enables it through "User Data Access" option (Located under Settings App). Then I try to launch this app to the user so the user can enable by himself, but this doesnt not work on many devices. See this link:
Devices without "Apps using Usage Data" or android.settings.USAGE_ACCESS_SETTINGS intent
enter image description here
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.
I released my Android app two days ago, using admob advertising. I used my personal phone as the test phone, but took out the test mode code before releasing it. My admob status is active and I get requests and impressions on the report, but whenever I try to use the app on my personal phone i only get "test ads". I don't know why. I looked through the code of my app and can't find anything amiss. And i did delete the test version of the app and then download the released version from the market.
I'm not sure why the test ads are appearing in your app, but one way to shut them off is to go to your Admob App Settings, and choose the option "Disable test mode for all requests" as your Test Mode setting.
You customers would not have been seeing the debug ads. You probably have a line like:
AdManager.setTestDevices( new String[] {
AdManager.TEST_EMULATOR, // Android emulator
"E83D20734F72FB3108F104ABC0FFC738", // My T-Mobile G1 Test Phone
}
Assuming E83D20734F72FB3108F104ABC0FFC738 is you're personal phone, any time that phone makes a request it will get a test ad. All other phones will not be eligible for test ads, unless they are also individually added to that method.
Nick's answer works. (But is missing the final parenthesis.)
But what if I want to give my (not yet released) Android app out to 10 friends?
Is there any java code that says "treat ALL phones as test devices"?
Here is code for treat all devices as test devices:
String aid = Settings.Secure.getString(context.getContentResolver(), "android_id");
try {
Object obj;
((MessageDigest) (obj = MessageDigest.getInstance("MD5"))).update(aid.getBytes(), 0, aid.length());
aid = String.format("%032X", new Object[] { new BigInteger(1, ((MessageDigest) obj).digest()) });
} catch (NoSuchAlgorithmException localNoSuchAlgorithmException) {
aid = aid.substring(0, 32);
}
adRequest.addTestDevice(aid);