Hi there I am making my app and I am worried that I might have left some permissions out and can really never be sure I have used the right permissions can you put in any sort of code to see what my app is actually using? or something like that as it is always a guessing game for me when selecting my permissions as I can never be sure.
Heres an example I make a "Check for Updates" Button. From that I launch an Intent to go to my app in the market is that using the internet connection ? or am I just using an Intent because some people will not have a working data connection so would I have to write access full network or something like that? Its just really confusing me
I think u have to check it during testing phase of apps.if there is not proper permissions given by u then the apps give error and u can add proper permission according to error.
Here is an example to walk through permissions:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo("<INTERESTING PACKAGE NAME>", PackageManager.GET_PERMISSIONS);
if ((null == pi.requestedPermissions) ||
(pi.requestedPermissions.length == 0)) {
Log.d("NOTE", "Package has NO permissions!");
return;
}
for (int i = 0; i < pi.requestedPermissions.length; ++i) {
Log.d("NOTE", pi.requestedPermissions[i] + " " + checkCallingOrSelfPermission(pi.requestedPermissions[i]));
}
} catch (NameNotFoundException e) {
Log.d("ERR", "Package name is wrong!");
}
}
Edit: your question seems to ask what permissions your app is using; this code tells your app what permissions you've requested. If you want to know what is being used, you need to strip all permissions from your app (which will cause runtime errors if you actually need any of them), and then through reading error logs and/or incrementally adding permissions until things work correctly, determine by hand what is actually needed.
Related
I've read around the internet for two options to check if an app is granted a permission or not.
Option 1:
getPackageManager().checkPermission(permission_string, packageName);
Option 2:
(PackageInfo.requestedPermissionsFlag[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0
I'm running on Android 11. I'm implementing a mechanism that upon clicking an app, the permissions state will be checked and if a permission is not allowed, the user will be prompt to allow it. I'm only checking this for "advanced" permissions, meaning, permissions that requires the user to allow them from settings screen, such as manage external storage (for android 11), drawOverlay, writeSettings and such. Anyway, this is the code I'm using:
try {
PackageInfo pi = getPackageManager().getPackageInfo(currAppInfo.getName(), PackageManager.GET_PERMISSIONS);
for(int i=0; i<pi.requestedPermissions.length; i++)
{
String perm = pi.requestedPermissions[i];
PermissionInfo permi = getPackageManager().getPermissionInfo(perm, PackageManager.GET_META_DATA);
if(getPackageManager().checkPermission(perm, currAppInfo.getName()) == 0)
continue;
if(AdvancedPermissionHandler.isAdvancedPermission(permi))
{
AdvancedPermissionHandler.openSettingsPage(permi, currAppInfo.getName(), MainActivity.this);
return;
}
}
} catch (Exception e) {
e.printStackTrace();
}
The only problem I'm facing is that even if I'm using option 1 and even if I'm using option 2, I'm ALWAYS getting false on the check. Meaning, say I click an app that requires manage external storage and it's state is currently not allowed. I click the app, I get moved to the appropriate screen, I allow the permission, I go back to the main screen, when I click the app again, instead of opening, I'm being moved to the same permission screen. Debugger shows that
getPackageManager().checkPermission(permission_string, packageName);
is returning false, even though the permission is given. Same for when I'm using option 2.
So my question is, what other methods are available to determine if a different app is granted a permission or, what am I doing wrong here in this code.
After digging some more I've found AppOps.
This is the code I've used to work, Android 11:
AppOpsManager appOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);
ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo(currAppInfo.getName(), 0);
PackageInfo pi = getPackageManager().getPackageInfo(currAppInfo.getName(), PackageManager.GET_PERMISSIONS);
for(int i=0; i<pi.requestedPermissions.length; i++)
{
String perm = pi.requestedPermissions[i];
PermissionInfo permi = getPackageManager().getPermissionInfo(perm, PackageManager.GET_META_DATA);
if(AppOpsManager.permissionToOp(permi.name) == null)
continue;
boolean granted = (appOps.unsafeCheckOpNoThrow(AppOpsManager.permissionToOp(permi.name),applicationInfo.uid,currAppInfo.getName()) == AppOpsManager.MODE_ALLOWED);
if(granted)
continue;
}
This is due to Android 11 restrictions to prevent installed apps fingerprinting.
You need to add target package name (e.g com.termux) to queries element or declare QUERY_ALL_PACKAGES permission in AndroidManifest.xml if targetSdkVersion is 30+. Check Package Visibility or this article for more info. Otherwise, you will will get PackageSetting{...... com.termux/......} BLOCKED errors in logcat.
<manifest
<queries>
<package android:name="com.termux" />
</queries>
</manifest>
I have a security system in schools, where my tablets are the consoles for each classroom. I've noticed teachers and admin are not restarting the tablets very often (or ever), which has caused issues. I would like to take the task from the clients and program a weekly reboot or shutdown. I have taken a few steps in the right direction:
I have:
Spoken with the Tablet Provider/Scheme Provider, and they have added my app as a privileged app.
Added a whitelist for (what I think are) all required permissions.
Confirmed the privileges exist.
Code to Check Permissions:
public void getGrantedPermissions(final String appPackage) {
List<String> granted = new ArrayList<String>();
try {
PackageInfo pi = getPackageManager().getPackageInfo(appPackage, PackageManager.GET_PERMISSIONS);
for (int i = 0; i < pi.requestedPermissions.length; i++) {
if ((pi.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
granted.add(pi.requestedPermissions[i]);
}
}
} catch (Exception e) {}
for(int i = 0; i < granted.size(); i++){
Log.e("Permissions", granted.get(i));
}
}
Below is what the log reported. The green permissions are all that I could get on my personal phone. The yellow permissions are what I was able to get, additionally, from the Tablet provider's whitelist. We can confirm by these permissions that I have a privileged app, as well as the shutdown and reboot permissions.
I was able to find a section of code to shutdown the app, but it seems that I can't quite figure out how to use it. Below is the code I have tried, and the error follows:
Intent intent = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN");
intent.putExtra("android.intent.extra.KEY_CONFIRM", false);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Error upon running code:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.ACTION_REQUEST_SHUTDOWN flg=0x10000000 (has extras) }
"This exception is thrown when a call to Context#startActivity or one of its variants fails because an Activity can not be found to execute the given Intent."
I am assuming that this may require me to modify my manifist.xml, is that correct? If so, I'm unsure how to do so. I feel that I may have to add an to my main activity, where the call is made. Though, I've tried this and it didn't work, or I wrote the code improperly.
Thank you in advance for any assistance!
Figured this one out. I didn't realize a PowerManager existed, but it does, and it works. My solution below. Also, if you didn't read the full question, my app is a privileged/System app, which gives me the authority to manage power. Normal apps will not be able to do this.
Currently running Android 9.0 (might matter, not sure)
try{
PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
powerManager.reboot(null);
} catch (Exception e){
Toast.makeText(this, "Error performing this action", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
I am trying to check whether an external application (i.e. not the one I am writing, but another one running on the debug device) has draw-over permissions. However, regardless of the method I use, I always get "false" as answer, whence I know for certain that said application can draw over other apps. In fact, not only I explicitly gave it permissions through the Settings interface, but I actually witnessed it performing a view overlay.
This is the first method I used:
pm.checkPermission(Manifest.permission.SYSTEM_ALERT_WINDOW, "target.package")
This is the second method I used (packageInfo being the PackageInfo object associated with "target.package"):
boolean requestedPermissionGranted = false;
for (int i = 0; i < packageInfo.requestedPermissions.length; ++i) {
if (packageInfo.requestedPermissions[i].equals(Manifest.permission.SYSTEM_ALERT_WINDOW)) {
requestedPermissionGranted =
(packageInfo.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
break;
}
}
hasPermission = requestedPermissionGranted;
Both expressions return false. By the way, I verified that packageInfo.requestedPermissions actually contains SYSTEM_ALERT_WINDOW.
I searched far and wide, but I could not find any topic that would answer my doubts. I only managed to find threads about how to check an app's own permissions, which I am not interested in.
P.S: I cannot use the shell through getRuntime().exec() and list active windows, as I get permission denied.
I am stuck writing some code that uses reflection that calls IConnectivityManager.startLegacyVpn
The error I get is java.lang.SecurityException: Unauthorized Caller
Looking through the android source I see this is the code hanging me up:
if (Binder.getCallingUid() != Process.SYSTEM_UID) { raise the above exception }
My question is if I root my AVD and install my app in system/app will this be sufficient to get around this error?
If so, any tips on how to do this (every time I try to move my apk to the system/app folder it says the app is not installed when I click on the app icon.
Thanks!
I have the same problem, following android 4.01 open source, i see somethings like this:
public synchronized LegacyVpnInfo getLegacyVpnInfo() {
// Only system user can call this method.
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Unauthorized Caller");
}
return (mLegacyVpnRunner == null) ? null : mLegacyVpnRunner.getInfo();
}
Or,
// Only system user can revoke a package.
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Unauthorized Caller");
}
Or,
public void protect(ParcelFileDescriptor socket, String interfaze) throws Exception {
PackageManager pm = mContext.getPackageManager();
ApplicationInfo app = pm.getApplicationInfo(mPackage, 0);
if (Binder.getCallingUid() != app.uid) {
throw new SecurityException("Unauthorized Caller");
}
jniProtect(socket.getFd(), interfaze);
}
However, these block of code above is belongs to com.android.server.connectivity.Vpn
(class Vpn), which is not defined in interface IConnectivityManager.
I also find in startLegacyVpnInfo() function but i can't see anything involve exception
"Unauthorized Caller", so i wonder why startLegacyVpnInfo() function throws this exception?
Any solutions for this?
I am trying to make the same calls. So far I can confirm that rooting the device and copying the apk to /system/app does not work, it does not start under the system uid.
Also, this does not work:
Field uidField = Process.class.getDeclaredField("SYSTEM_UID");
uidField.setAccessible(true);
uidField.set(null, Process.myUid());
Those calls succeed, but they don't seem to affect the SYSTEM_UID field, the field is probably optimized out at compile time.
If you include android: sharedUserId="android.uid.system" into your manifest tag (not just the manifest), this should then run the application as system. This should now let you run the code.
As for pushing to /system/app, you need to run adb root followed by adb remount. This will now let you push to /system/app.
I am writing a service which needs to see if its caller holds a particular private permission. I do not want to prevent callers that lack this permission, I only want to know the status so that I can react accordingly. It would seem that the Context method checkCallingPermission() is perfect for what I need, returning 0 if the caller has the specified permission and -1 otherwise. I'm finding that -1 is returned in all cases though.
I wrote a test case (using the similar method checkCallingOrSelfPermission() where I pulled my package's PackageInfo from the system, enumerated each of my permissions (only one requested for the package), and display the result of checkCallingOrSelfPermission(). Since the permissions I'm checking against in this case are exactly the permissions I hold, I would expect checkCallingOrSelfPermission() to return 0 (PackageManager.PERMISSION_GRANTED) only... buy it only returns -1 (PackageManager.PERMISSION_DENIED).
I've checked this and received the same results on both a 4.0 emulator and a 2.3 device.
Any idea what I'm doing wrong to cause these calls to fail?
My test manifest includes:
<permission
android:protectionLevel="signatureOrSystem"
android:name="abcd" />
<uses-permission android:name="abcd" />
My test activity code is:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo("com.test.check", PackageManager.GET_PERMISSIONS);
if ((null == pi.requestedPermissions) ||
(pi.requestedPermissions.length == 0)) {
Log.d("CHECK", "Package has NO permissions!");
finish();
return;
}
for (int i = 0; i < pi.requestedPermissions.length; ++i) {
Log.d("CHECK", pi.requestedPermissions[i] + " " + checkCallingOrSelfPermission(pi.requestedPermissions[i]));
}
} catch (NameNotFoundException e) {
Log.d("CHECK", "Package name is wrong!");
}
finish();
}
and my test results are:
D/CHECK ( 3600): abcd -1
I have not been able to resolve this within the scope of my service needing to check permissions, but I have found a work-around for the service (and a problem in my test case).
My test case failed because the permission I created and checked with, "abcd", was renamed by Android in the <permission> entry, however Android failed to equally rename it in the <uses-permission> entry. It was renamed to have my package name prepended to it (and this renaming does not occur if I provide a name including a period in it, such as "test.abcd").
Though changing the permission name fixed my test case, my actual case within a service was already using a fully qualified permission name and checkCallingPermission() continues to fail. I discovered, however, that the PackageManager's checkPermission() method does work as expected (at the expense of my needing to retrieve the name of the caller's package).
So to summarize, the following does not work correctly (though I do not know why):
boolean permission = (PackageManager.PERMISSION_GRANTED == checkCallingPermission(PERMISSION_NAME));
while this seems to work correctly:
PackageManager pm = getPackageManager();
boolean permission = (PackageManager.PERMISSION_GRANTED == pm.checkPermission(PERMISSION_NAME, pm.getNameForUid(getCallingUid())));